summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gemfile5
-rw-r--r--Gemfile.lock5
-rw-r--r--app/assets/config/manifest.js1
-rw-r--r--app/assets/javascripts/admin_bundle.js5
-rwxr-xr-xapp/assets/javascripts/jquery.hotkeys.js244
-rw-r--r--app/helpers/link_helper.rb12
-rw-r--r--app/helpers/nodes_helper.rb16
-rw-r--r--app/views/admin/_drafts.html.erb2
-rw-r--r--app/views/admin/_menu.html.erb2
-rw-r--r--app/views/assets/index.html.erb2
-rw-r--r--app/views/events/index.html.erb2
-rw-r--r--app/views/layouts/admin.html.erb5
-rw-r--r--app/views/menu_items/index.html.erb9
-rw-r--r--app/views/nodes/edit.html.erb2
-rw-r--r--app/views/occurrences/index.html.erb2
-rw-r--r--app/views/pages/index.html.erb2
-rw-r--r--app/views/revisions/index.html.erb38
-rw-r--r--app/views/users/_user.html.erb9
-rw-r--r--config/environments/development.rb3
-rw-r--r--public/assets/.sprockets-manifest-0856c2516a5e648c9c4b24cbb135cf0e.json1
-rw-r--r--public/assets/actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js510
-rw-r--r--public/assets/actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js.gzbin0 -> 3844 bytes
-rw-r--r--public/assets/actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js512
-rw-r--r--public/assets/actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js.gzbin0 -> 3612 bytes
-rw-r--r--public/assets/actiontext-338257afa53cc53f94018abf7a897120d1eb3ee71f39e4641b2058442c9c4dc6.js862
-rw-r--r--public/assets/actiontext-338257afa53cc53f94018abf7a897120d1eb3ee71f39e4641b2058442c9c4dc6.js.gzbin0 -> 6532 bytes
-rw-r--r--public/assets/actiontext.esm-e787c6f528f0a88ee04de7c5ce4e3ab37fcf2691629ed21f0b30ee2db848c8c8.js889
-rw-r--r--public/assets/actiontext.esm-e787c6f528f0a88ee04de7c5ce4e3ab37fcf2691629ed21f0b30ee2db848c8c8.js.gzbin0 -> 6429 bytes
-rw-r--r--public/assets/activestorage-7dbadea816242c6d03cc2f59c58398ab55bb9a70ee859fa962ad4c7ad4c48594.js829
-rw-r--r--public/assets/activestorage-7dbadea816242c6d03cc2f59c58398ab55bb9a70ee859fa962ad4c7ad4c48594.js.gzbin0 -> 6362 bytes
-rw-r--r--public/assets/activestorage.esm-b2d9aa45888a540d7e6969e484dbdb0a0a501ff56542ce737db6599b311e3385.js848
-rw-r--r--public/assets/activestorage.esm-b2d9aa45888a540d7e6969e484dbdb0a0a501ff56542ce737db6599b311e3385.js.gzbin0 -> 6136 bytes
-rw-r--r--public/assets/admin_bundle-e15d8265faa7d827f0b57416f9aeec7a730d7f47ede994b76014444669fb2081.js31775
-rw-r--r--public/assets/admin_bundle-e15d8265faa7d827f0b57416f9aeec7a730d7f47ede994b76014444669fb2081.js.gzbin0 -> 219302 bytes
-rw-r--r--public/assets/manifest-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.js0
-rw-r--r--public/assets/manifest-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.js.gzbin0 -> 20 bytes
-rw-r--r--public/assets/trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js13720
-rw-r--r--public/assets/trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js.gzbin0 -> 99552 bytes
-rw-r--r--public/assets/trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css412
-rw-r--r--public/assets/trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css.gzbin0 -> 4283 bytes
-rw-r--r--public/stylesheets/admin.css22
41 files changed, 50700 insertions, 46 deletions
diff --git a/Gemfile b/Gemfile
index 2f6e394..f3bd1a1 100644
--- a/Gemfile
+++ b/Gemfile
@@ -4,6 +4,7 @@ ruby '3.2.11'
4 4
5gem 'rails', '~> 7.2.3' 5gem 'rails', '~> 7.2.3'
6gem 'concurrent-ruby', '~> 1.3' 6gem 'concurrent-ruby', '~> 1.3'
7gem 'sprockets-rails'
7gem 'puma' 8gem 'puma'
8 9
9gem 'pg', '~> 1.4.6' 10gem 'pg', '~> 1.4.6'
@@ -17,8 +18,10 @@ gem 'will_paginate', '~> 3.0'
17gem 'exception_notification', '~> 4.5' 18gem 'exception_notification', '~> 4.5'
18gem 'libxml-ruby', '~> 5.0', :require => 'xml' 19gem 'libxml-ruby', '~> 5.0', :require => 'xml'
19 20
20gem 'nokogiri', '~> 1.18'
21gem 'jquery-rails' 21gem 'jquery-rails'
22gem 'jquery-ui-rails'
23
24gem 'nokogiri', '~> 1.18'
22 25
23gem 'unicorn', '~> 6.1' 26gem 'unicorn', '~> 6.1'
24 27
diff --git a/Gemfile.lock b/Gemfile.lock
index 9d5ec90..36a64cd 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -142,6 +142,8 @@ GEM
142 rails-dom-testing (>= 1, < 3) 142 rails-dom-testing (>= 1, < 3)
143 railties (>= 4.2.0) 143 railties (>= 4.2.0)
144 thor (>= 0.14, < 2.0) 144 thor (>= 0.14, < 2.0)
145 jquery-ui-rails (8.0.0)
146 railties (>= 3.2.16)
145 kgio (2.11.4) 147 kgio (2.11.4)
146 libxml-ruby (5.0.6) 148 libxml-ruby (5.0.6)
147 logger (1.7.0) 149 logger (1.7.0)
@@ -320,6 +322,7 @@ DEPENDENCIES
320 exception_notification (~> 4.5) 322 exception_notification (~> 4.5)
321 globalize (~> 7.0) 323 globalize (~> 7.0)
322 jquery-rails 324 jquery-rails
325 jquery-ui-rails
323 libxml-ruby (~> 5.0) 326 libxml-ruby (~> 5.0)
324 minitest (~> 5.25) 327 minitest (~> 5.25)
325 nokogiri (~> 1.18) 328 nokogiri (~> 1.18)
@@ -329,6 +332,7 @@ DEPENDENCIES
329 rails-controller-testing 332 rails-controller-testing
330 routing-filter (~> 0.7.0) 333 routing-filter (~> 0.7.0)
331 sass-rails (~> 6.0) 334 sass-rails (~> 6.0)
335 sprockets-rails
332 test-unit (~> 3.5) 336 test-unit (~> 3.5)
333 uglifier (>= 1.0.3) 337 uglifier (>= 1.0.3)
334 unicorn (~> 6.1) 338 unicorn (~> 6.1)
@@ -385,6 +389,7 @@ CHECKSUMS
385 io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc 389 io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc
386 irb (1.18.0) sha256=de9454a0703a54704b9811a5ef31a60c86949fbf4013fcf244fabc7c775248e3 390 irb (1.18.0) sha256=de9454a0703a54704b9811a5ef31a60c86949fbf4013fcf244fabc7c775248e3
387 jquery-rails (4.6.1) sha256=619f3496cdcdeaae1fd6dafa52dbac3fc45b745d4e09712da4184a16b3a8d9c0 391 jquery-rails (4.6.1) sha256=619f3496cdcdeaae1fd6dafa52dbac3fc45b745d4e09712da4184a16b3a8d9c0
392 jquery-ui-rails (8.0.0) sha256=e198f0ccd84587bc1030e79333db5fdb1100c8d459ed378ff285f57720f6b9c9
388 kgio (2.11.4) sha256=bda7a2146115998a5b07154e708e0ac02c38dcee7e793c33e2e14f600fdfffc6 393 kgio (2.11.4) sha256=bda7a2146115998a5b07154e708e0ac02c38dcee7e793c33e2e14f600fdfffc6
389 libxml-ruby (5.0.6) sha256=ef82ff4b4c6aaaa9629f0a2d5deccd9502507e368bf2c5a98d675f634013ca46 394 libxml-ruby (5.0.6) sha256=ef82ff4b4c6aaaa9629f0a2d5deccd9502507e368bf2c5a98d675f634013ca46
390 logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203 395 logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js
index e69de29..56d7f6d 100644
--- a/app/assets/config/manifest.js
+++ b/app/assets/config/manifest.js
@@ -0,0 +1 @@
//= link admin_bundle.js
diff --git a/app/assets/javascripts/admin_bundle.js b/app/assets/javascripts/admin_bundle.js
new file mode 100644
index 0000000..687266c
--- /dev/null
+++ b/app/assets/javascripts/admin_bundle.js
@@ -0,0 +1,5 @@
1//= require jquery
2//= require jquery_ujs
3//= require jquery-ui
4//= require jquery.hotkeys
5//= require_self
diff --git a/app/assets/javascripts/jquery.hotkeys.js b/app/assets/javascripts/jquery.hotkeys.js
new file mode 100755
index 0000000..9a8f2de
--- /dev/null
+++ b/app/assets/javascripts/jquery.hotkeys.js
@@ -0,0 +1,244 @@
1/*
2(c) Copyrights 2007 - 2008
3
4Original idea by by Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
5
6jQuery Plugin by Tzury Bar Yochay
7tzury.by@gmail.com
8http://evalinux.wordpress.com
9http://facebook.com/profile.php?id=513676303
10
11Project's sites:
12http://code.google.com/p/js-hotkeys/
13http://github.com/tzuryby/hotkeys/tree/master
14
15License: same as jQuery license.
16
17USAGE:
18 // simple usage
19 $(document).bind('keydown', 'Ctrl+c', function(){ alert('copy anyone?');});
20
21 // special options such as disableInIput
22 $(document).bind('keydown', {combi:'Ctrl+x', disableInInput: true} , function() {});
23
24Note:
25 This plugin wraps the following jQuery methods: $.fn.find, $.fn.bind and $.fn.unbind
26*/
27
28(function (jQuery){
29 // keep reference to the original $.fn.bind, $.fn.unbind and $.fn.find
30 jQuery.fn.__bind__ = jQuery.fn.bind;
31 jQuery.fn.__unbind__ = jQuery.fn.unbind;
32 jQuery.fn.__find__ = jQuery.fn.find;
33
34 var hotkeys = {
35 version: '0.7.9',
36 override: /keypress|keydown|keyup/g,
37 triggersMap: {},
38
39 specialKeys: { 27: 'esc', 9: 'tab', 32:'space', 13: 'return', 8:'backspace', 145: 'scroll',
40 20: 'capslock', 144: 'numlock', 19:'pause', 45:'insert', 36:'home', 46:'del',
41 35:'end', 33: 'pageup', 34:'pagedown', 37:'left', 38:'up', 39:'right',40:'down',
42 109: '-',
43 112:'f1',113:'f2', 114:'f3', 115:'f4', 116:'f5', 117:'f6', 118:'f7', 119:'f8',
44 120:'f9', 121:'f10', 122:'f11', 123:'f12', 191: '/'},
45
46 shiftNums: { "`":"~", "1":"!", "2":"@", "3":"#", "4":"$", "5":"%", "6":"^", "7":"&",
47 "8":"*", "9":"(", "0":")", "-":"_", "=":"+", ";":":", "'":"\"", ",":"<",
48 ".":">", "/":"?", "\\":"|" },
49
50 newTrigger: function (type, combi, callback) {
51 // i.e. {'keyup': {'ctrl': {cb: callback, disableInInput: false}}}
52 var result = {};
53 result[type] = {};
54 result[type][combi] = {cb: callback, disableInInput: false};
55 return result;
56 }
57 };
58 // add firefox num pad char codes
59 //if (jQuery.browser.mozilla){
60 // add num pad char codes
61 hotkeys.specialKeys = jQuery.extend(hotkeys.specialKeys, { 96: '0', 97:'1', 98: '2', 99:
62 '3', 100: '4', 101: '5', 102: '6', 103: '7', 104: '8', 105: '9', 106: '*',
63 107: '+', 109: '-', 110: '.', 111 : '/'
64 });
65 //}
66
67 // a wrapper around of $.fn.find
68 // see more at: http://groups.google.com/group/jquery-en/browse_thread/thread/18f9825e8d22f18d
69 jQuery.fn.find = function( selector ) {
70 this.query = selector;
71 return jQuery.fn.__find__.apply(this, arguments);
72 };
73
74 jQuery.fn.unbind = function (type, combi, fn){
75 if (jQuery.isFunction(combi)){
76 fn = combi;
77 combi = null;
78 }
79 if (combi && typeof combi === 'string'){
80 var selectorId = ((this.prevObject && this.prevObject.query) || (this[0].id && this[0].id) || this[0]).toString();
81 var hkTypes = type.split(' ');
82 for (var x=0; x<hkTypes.length; x++){
83 delete hotkeys.triggersMap[selectorId][hkTypes[x]][combi];
84 }
85 }
86 // call jQuery original unbind
87 return this.__unbind__(type, fn);
88 };
89
90 jQuery.fn.bind = function(type, data, fn){
91 // grab keyup,keydown,keypress
92 var handle = type.match(hotkeys.override);
93
94 if (jQuery.isFunction(data) || !handle){
95 // call jQuery.bind only
96 return this.__bind__(type, data, fn);
97 }
98 else{
99 // split the job
100 var result = null,
101 // pass the rest to the original $.fn.bind
102 pass2jq = jQuery.trim(type.replace(hotkeys.override, ''));
103
104 // see if there are other types, pass them to the original $.fn.bind
105 if (pass2jq){
106 result = this.__bind__(pass2jq, data, fn);
107 }
108
109 if (typeof data === "string"){
110 data = {'combi': data};
111 }
112 if(data.combi){
113 for (var x=0; x < handle.length; x++){
114 var eventType = handle[x];
115 var combi = data.combi.toLowerCase(),
116 trigger = hotkeys.newTrigger(eventType, combi, fn),
117 selectorId = ((this.prevObject && this.prevObject.query) || (this[0].id && this[0].id) || this[0]).toString();
118
119 //trigger[eventType][combi].propagate = data.propagate;
120 trigger[eventType][combi].disableInInput = data.disableInInput;
121
122 // first time selector is bounded
123 if (!hotkeys.triggersMap[selectorId]) {
124 hotkeys.triggersMap[selectorId] = trigger;
125 }
126 // first time selector is bounded with this type
127 else if (!hotkeys.triggersMap[selectorId][eventType]) {
128 hotkeys.triggersMap[selectorId][eventType] = trigger[eventType];
129 }
130 // make trigger point as array so more than one handler can be bound
131 var mapPoint = hotkeys.triggersMap[selectorId][eventType][combi];
132 if (!mapPoint){
133 hotkeys.triggersMap[selectorId][eventType][combi] = [trigger[eventType][combi]];
134 }
135 else if (mapPoint.constructor !== Array){
136 hotkeys.triggersMap[selectorId][eventType][combi] = [mapPoint];
137 }
138 else {
139 hotkeys.triggersMap[selectorId][eventType][combi][mapPoint.length] = trigger[eventType][combi];
140 }
141
142 // add attribute and call $.event.add per matched element
143 this.each(function(){
144 // jQuery wrapper for the current element
145 var jqElem = jQuery(this);
146
147 // element already associated with another collection
148 if (jqElem.attr('hkId') && jqElem.attr('hkId') !== selectorId){
149 selectorId = jqElem.attr('hkId') + ";" + selectorId;
150 }
151 jqElem.attr('hkId', selectorId);
152 });
153 result = this.__bind__(handle.join(' '), data, hotkeys.handler)
154 }
155 }
156 return result;
157 }
158 };
159 // work-around for opera and safari where (sometimes) the target is the element which was last
160 // clicked with the mouse and not the document event it would make sense to get the document
161 hotkeys.findElement = function (elem){
162 if (!jQuery(elem).attr('hkId')){
163 if (jQuery.browser.opera || jQuery.browser.safari){
164 while (!jQuery(elem).attr('hkId') && elem.parentNode){
165 elem = elem.parentNode;
166 }
167 }
168 }
169 return elem;
170 };
171 // the event handler
172 hotkeys.handler = function(event) {
173 var target = hotkeys.findElement(event.currentTarget),
174 jTarget = jQuery(target),
175 ids = jTarget.attr('hkId');
176
177 if(ids){
178 ids = ids.split(';');
179 var code = event.which,
180 type = event.type,
181 special = hotkeys.specialKeys[code],
182 // prevent f5 overlapping with 't' (or f4 with 's', etc.)
183 character = !special && String.fromCharCode(code).toLowerCase(),
184 shift = event.shiftKey,
185 ctrl = event.ctrlKey,
186 // patch for jquery 1.2.5 && 1.2.6 see more at:
187 // http://groups.google.com/group/jquery-en/browse_thread/thread/83e10b3bb1f1c32b
188 alt = event.altKey || event.originalEvent.altKey,
189 mapPoint = null;
190
191 for (var x=0; x < ids.length; x++){
192 if (hotkeys.triggersMap[ids[x]][type]){
193 mapPoint = hotkeys.triggersMap[ids[x]][type];
194 break;
195 }
196 }
197
198 //find by: id.type.combi.options
199 if (mapPoint){
200 var trigger;
201 // event type is associated with the hkId
202 if(!shift && !ctrl && !alt) { // No Modifiers
203 trigger = mapPoint[special] || (character && mapPoint[character]);
204 }
205 else{
206 // check combinations (alt|ctrl|shift+anything)
207 var modif = '';
208 if(alt) modif +='alt+';
209 if(ctrl) modif+= 'ctrl+';
210 if(shift) modif += 'shift+';
211 // modifiers + special keys or modifiers + character or modifiers + shift character or just shift character
212 trigger = mapPoint[modif+special];
213 if (!trigger){
214 if (character){
215 trigger = mapPoint[modif+character]
216 || mapPoint[modif+hotkeys.shiftNums[character]]
217 // '$' can be triggered as 'Shift+4' or 'Shift+$' or just '$'
218 || (modif === 'shift+' && mapPoint[hotkeys.shiftNums[character]]);
219 }
220 }
221 }
222 if (trigger){
223 var result = false;
224 for (var x=0; x < trigger.length; x++){
225 if(trigger[x].disableInInput){
226 // double check event.currentTarget and event.target
227 var elem = jQuery(event.target);
228 if (jTarget.is("input") || jTarget.is("textarea") || jTarget.is("select")
229 || elem.is("input") || elem.is("textarea") || elem.is("select")) {
230 return true;
231 }
232 }
233 // call the registered callback function
234 result = result || trigger[x].cb.apply(this, [event]);
235 }
236 return result;
237 }
238 }
239 }
240 };
241 // place it under window so it can be extended and overridden by others
242 window.hotkeys = hotkeys;
243 return jQuery;
244})(jQuery);
diff --git a/app/helpers/link_helper.rb b/app/helpers/link_helper.rb
index cb13c8d..ea6c26f 100644
--- a/app/helpers/link_helper.rb
+++ b/app/helpers/link_helper.rb
@@ -39,11 +39,11 @@ module LinkHelper
39 end 39 end
40 40
41 def unlock_link 41 def unlock_link
42 message = "Are you sure you want to unlock?\n" + 42 message = "Are you sure you want to unlock?\n" \
43 "Locked by #{@node.lock_owner.login}\n" + 43 "Locked by #{@node.lock_owner.login}\n" \
44 "Last modified #{@page.updated_at.to_fs(:db)}" 44 "Last modified #{@page.updated_at.to_fs(:db)}"
45 45 button_to 'Unlock', unlock_node_path(@node),
46 link_to 'Unlock', unlock_node_path(@node), :method => :put, :data => { :confirm => message } 46 method: :put,
47 form: { data: { confirm: message } }
47 end 48 end
48
49end 49end
diff --git a/app/helpers/nodes_helper.rb b/app/helpers/nodes_helper.rb
index c739ccd..a054a2e 100644
--- a/app/helpers/nodes_helper.rb
+++ b/app/helpers/nodes_helper.rb
@@ -28,14 +28,20 @@ module NodesHelper
28 def user_list 28 def user_list
29 User.all.map {|u| [u.login, u.id]} 29 User.all.map {|u| [u.login, u.id]}
30 end 30 end
31 31
32 def event_information 32 def event_information
33 if @node.event 33 if @node.event
34 "#{@node.event.start_time.to_fs(:db)} - #{@node.event.end_time.to_fs(:db)} > " \ 34 safe_join([
35 "#{link_to 'show', event_path(@node.event)} " \ 35 "#{@node.event.start_time.to_fs(:db)} - #{@node.event.end_time.to_fs(:db)} > ",
36 "#{link_to 'edit', edit_event_path(@node.event)}" 36 link_to('show', event_path(@node.event)),
37 ' ',
38 link_to('edit', edit_event_path(@node.event))
39 ])
37 else 40 else
38 "no event attached > #{link_to 'add', new_event_path(:node_id => @node.id)}" 41 safe_join([
42 'no event attached > ',
43 link_to('add', new_event_path(:node_id => @node.id))
44 ])
39 end 45 end
40 end 46 end
41end 47end
diff --git a/app/views/admin/_drafts.html.erb b/app/views/admin/_drafts.html.erb
index 2036d12..a35b0ab 100644
--- a/app/views/admin/_drafts.html.erb
+++ b/app/views/admin/_drafts.html.erb
@@ -17,7 +17,7 @@
17 <td class="actions"> 17 <td class="actions">
18 <%= link_to 'Show', node_path(draft.node) %> 18 <%= link_to 'Show', node_path(draft.node) %>
19 <%= link_to "Revisions", revision_path(draft.node.id) %> 19 <%= link_to "Revisions", revision_path(draft.node.id) %>
20 <%= link_to "Publish", publish_node_path(draft.node), :method => :put, :data => { :confirm => "Do you really want to publish?" } %> 20 <%= button_to "Publish", publish_node_path(draft.node), method: :put, form: { data: { confirm: "Do you really want to publish?" } } %>
21 </td> 21 </td>
22 </tr> 22 </tr>
23 <% end %> 23 <% end %>
diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb
index 3188d94..6f217eb 100644
--- a/app/views/admin/_menu.html.erb
+++ b/app/views/admin/_menu.html.erb
@@ -1,5 +1,5 @@
1<%= language_selector %> 1<%= language_selector %>
2<%= link_to 'Logout', logout_path, :method => :delete %> 2<%= button_to 'Logout', logout_path, method: :delete %>
3<%= link_to 'Overview', admin_path %> 3<%= link_to 'Overview', admin_path %>
4<%= link_to 'Nodes', nodes_path, selected?('nodes') %> 4<%= link_to 'Nodes', nodes_path, selected?('nodes') %>
5<%= link_to 'Assets', assets_path, selected?('assets') %> 5<%= link_to 'Assets', assets_path, selected?('assets') %>
diff --git a/app/views/assets/index.html.erb b/app/views/assets/index.html.erb
index e7ef313..83d55c2 100644
--- a/app/views/assets/index.html.erb
+++ b/app/views/assets/index.html.erb
@@ -15,7 +15,7 @@
15 <td><%= asset.upload.content_type %></td> 15 <td><%= asset.upload.content_type %></td>
16 <td><%= link_to 'Show', asset %></td> 16 <td><%= link_to 'Show', asset %></td>
17 <td><%= link_to 'Edit', edit_asset_path(asset) %></td> 17 <td><%= link_to 'Edit', edit_asset_path(asset) %></td>
18 <td><%= link_to 'Destroy', asset, :data => { :confirm => 'Are you sure?' }, :method => :delete %></td> 18 <td><%= button_to 'Destroy', asset, method: :delete, form: { data: { confirm: 'Are you sure?' } } %></td>
19 </tr> 19 </tr>
20<% end %> 20<% end %>
21</table> 21</table>
diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb
index 93c95fa..19b21ce 100644
--- a/app/views/events/index.html.erb
+++ b/app/views/events/index.html.erb
@@ -26,7 +26,7 @@
26 <td><%=h event.node_id %></td> 26 <td><%=h event.node_id %></td>
27 <td><%= link_to 'Show', event %></td> 27 <td><%= link_to 'Show', event %></td>
28 <td><%= link_to 'Edit', edit_event_path(event) %></td> 28 <td><%= link_to 'Edit', edit_event_path(event) %></td>
29 <td><%= link_to 'Destroy', event, :data => { :confirm => 'Are you sure?' }, :method => :delete %></td> 29 <td><%= button_to 'Destroy', event, method: :delete, form: { data: { confirm: 'Are you sure?' } } %></td>
30 </tr> 30 </tr>
31<% end %> 31<% end %>
32</table> 32</table>
diff --git a/app/views/layouts/admin.html.erb b/app/views/layouts/admin.html.erb
index e64850b..2a90786 100644
--- a/app/views/layouts/admin.html.erb
+++ b/app/views/layouts/admin.html.erb
@@ -7,14 +7,13 @@
7 <%= csrf_meta_tags %> 7 <%= csrf_meta_tags %>
8 8
9 <title><%= "#{params[:controller]} | #{params[:action]}" %></title> 9 <title><%= "#{params[:controller]} | #{params[:action]}" %></title>
10 <%= javascript_include_tag 'jquery', 'jquery_ujs' %> 10 <%= javascript_include_tag 'admin_bundle' %>
11 <%= javascript_include_tag 'jquery-ui-1.7.2.custom.min' %>
12 <%= javascript_include_tag 'jquery.hotkeys' %>
13 <%= javascript_include_tag 'tiny_mce/jquery.tinymce.js' %> 11 <%= javascript_include_tag 'tiny_mce/jquery.tinymce.js' %>
14 <%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %> 12 <%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %>
15 <%= stylesheet_link_tag 'admin' %> 13 <%= stylesheet_link_tag 'admin' %>
16 <%= javascript_include_tag 'admin_search.js' %> 14 <%= javascript_include_tag 'admin_search.js' %>
17 <%= javascript_include_tag 'admin_interface.js' %> 15 <%= javascript_include_tag 'admin_interface.js' %>
16 <%= stylesheet_link_tag 'admin' %>
18 </head> 17 </head>
19 18
20 <body> 19 <body>
diff --git a/app/views/menu_items/index.html.erb b/app/views/menu_items/index.html.erb
index 7d0ce62..c52c150 100644
--- a/app/views/menu_items/index.html.erb
+++ b/app/views/menu_items/index.html.erb
@@ -14,12 +14,9 @@
14 <td class="menu_item_title"><%= menu_item.title %></td> 14 <td class="menu_item_title"><%= menu_item.title %></td>
15 <td><%= link_to "Edit", edit_menu_item_path(menu_item) %></td> 15 <td><%= link_to "Edit", edit_menu_item_path(menu_item) %></td>
16 <td> 16 <td>
17 <%= link_to( 17 <%= button_to "Delete", menu_item_path(menu_item),
18 "Delete", 18 method: :delete,
19 menu_item_path(menu_item), 19 form: { data: { confirm: "Are you sure?" } } %>
20 :method => :delete,
21 :data => { :confirm => "Are you sure?" }
22 ) %>
23 </td> 20 </td>
24 </tr> 21 </tr>
25 <% end %> 22 <% end %>
diff --git a/app/views/nodes/edit.html.erb b/app/views/nodes/edit.html.erb
index 64884cf..596f992 100644
--- a/app/views/nodes/edit.html.erb
+++ b/app/views/nodes/edit.html.erb
@@ -2,7 +2,7 @@
2 <%= link_to 'metadata', '#', :id => 'button', :class => "unselected" %> 2 <%= link_to 'metadata', '#', :id => 'button', :class => "unselected" %>
3 <%= link_to 'Show', @node %> 3 <%= link_to 'Show', @node %>
4 <%= link_to 'Preview', preview_page_path(@draft) %> 4 <%= link_to 'Preview', preview_page_path(@draft) %>
5 <%= link_to 'Publish', publish_node_path, :method => :put, :data => { :confirm => "Publish this draft?" } %> 5 <%= button_to 'Publish', publish_node_path(@node), method: :put, form: { data: { confirm: "Publish this draft?" } } %>
6 <%= link_to 'Revisions', node_revisions_path(@node) %> 6 <%= link_to 'Revisions', node_revisions_path(@node) %>
7<% end %> 7<% end %>
8 8
diff --git a/app/views/occurrences/index.html.erb b/app/views/occurrences/index.html.erb
index 7b8ffb8..0e99857 100644
--- a/app/views/occurrences/index.html.erb
+++ b/app/views/occurrences/index.html.erb
@@ -18,7 +18,7 @@
18 <td><%=h occurrence.event_id %></td> 18 <td><%=h occurrence.event_id %></td>
19 <td><%= link_to 'Show', occurrence %></td> 19 <td><%= link_to 'Show', occurrence %></td>
20 <td><%= link_to 'Edit', edit_occurrence_path(occurrence) %></td> 20 <td><%= link_to 'Edit', edit_occurrence_path(occurrence) %></td>
21 <td><%= link_to 'Destroy', occurrence, :data => { :confirm => 'Are you sure?' }, :method => :delete %></td> 21 <td><%= button_to 'Destroy', occurrence, method: :delete, form: { data: { confirm: 'Are you sure?' } } %></td>
22 </tr> 22 </tr>
23<% end %> 23<% end %>
24</table> 24</table>
diff --git a/app/views/pages/index.html.erb b/app/views/pages/index.html.erb
index 4b28c9b..91e5359 100644
--- a/app/views/pages/index.html.erb
+++ b/app/views/pages/index.html.erb
@@ -12,7 +12,7 @@
12 <td><%=h page.title %></td> 12 <td><%=h page.title %></td>
13 <td><%= link_to 'Show', content_path(:page_path => page.node.unique_path) %></td> 13 <td><%= link_to 'Show', content_path(:page_path => page.node.unique_path) %></td>
14 <td><%= link_to 'Edit', edit_page_path(page) %></td> 14 <td><%= link_to 'Edit', edit_page_path(page) %></td>
15 <td><%= link_to 'Destroy', page, :data => { :confirm => 'Are you sure?' }, :method => :delete %></td> 15 <td><%= button_to 'Destroy', page, method: :delete, form: { data: { confirm: 'Are you sure?' } } %></td>
16 </tr> 16 </tr>
17<% end %> 17<% end %>
18</table> 18</table>
diff --git a/app/views/revisions/index.html.erb b/app/views/revisions/index.html.erb
index e038ed2..b875a4f 100644
--- a/app/views/revisions/index.html.erb
+++ b/app/views/revisions/index.html.erb
@@ -4,7 +4,6 @@
4 4
5<h2>Revisions for Node: <%= @node.unique_name %></h2> 5<h2>Revisions for Node: <%= @node.unique_name %></h2>
6 6
7<%= form_tag diff_node_revisions_path(@node) do %>
8<table id="revisions"> 7<table id="revisions">
9 <tr class="header"> 8 <tr class="header">
10 <th>First</th> 9 <th>First</th>
@@ -14,6 +13,7 @@
14 <th>Editor</th> 13 <th>Editor</th>
15 <th>Date</th> 14 <th>Date</th>
16 <th></th> 15 <th></th>
16 <th></th>
17 </tr> 17 </tr>
18<% (@pages || @node.pages.all).reverse.each do |page| %> 18<% (@pages || @node.pages.all).reverse.each do |page| %>
19 <tr> 19 <tr>
@@ -23,22 +23,36 @@
23 <td class="title"><%= page.title %></td> 23 <td class="title"><%= page.title %></td>
24 <td class="user"><%= page.editor.try(:login) %></td> 24 <td class="user"><%= page.editor.try(:login) %></td>
25 <td class="date"><%= page.updated_at %></td> 25 <td class="date"><%= page.updated_at %></td>
26 <td><%= link_to 'show', node_revision_path(@node, page) %></td>
26 <td> 27 <td>
27 <%= link_to 'show', node_revision_path(@node, page) %> 28 <%= button_to 'restore', restore_node_revision_path(@node, page),
28 </td> 29 method: :put,
29 <td> 30 form: { data: { confirm: "Restore this revision?" } } %>
30 <%= link_to(
31 'restore',
32 restore_node_revision_path(@node, page),
33 :method => :put,
34 :data => { :confirm => "Restore this revision?" }
35 ) %>
36 </td> 31 </td>
37 </tr> 32 </tr>
38<% end %> 33<% end %>
39 <tr class="no_hover"> 34 <tr class="no_hover">
40 <td colspan="8" class="right"><%= submit_tag 'Diff revisions' %></td> 35 <td colspan="8" class="right">
36 <%= button_to 'Diff revisions', diff_node_revisions_path(@node),
37 method: :post,
38 form: { id: 'diff_form' } %>
39 </td>
41 </tr> 40 </tr>
42</table> 41</table>
43 42
44<% end %> 43<script>
44 document.getElementById('diff_form').addEventListener('submit', function(e) {
45 var start = document.querySelector('input[name="start_revision"]:checked');
46 var end = document.querySelector('input[name="end_revision"]:checked');
47 if (start) {
48 var s = document.createElement('input');
49 s.type = 'hidden'; s.name = 'start_revision'; s.value = start.value;
50 this.appendChild(s);
51 }
52 if (end) {
53 var en = document.createElement('input');
54 en.type = 'hidden'; en.name = 'end_revision'; en.value = end.value;
55 this.appendChild(en);
56 }
57 });
58</script>
diff --git a/app/views/users/_user.html.erb b/app/views/users/_user.html.erb
index 9987e31..ddb7afd 100644
--- a/app/views/users/_user.html.erb
+++ b/app/views/users/_user.html.erb
@@ -7,12 +7,9 @@
7 <%= link_to "edit", edit_user_path(user) %> 7 <%= link_to "edit", edit_user_path(user) %>
8 </td> 8 </td>
9 <td> 9 <td>
10 <%= link_to( 10 <%= button_to "destroy", user_path(user),
11 "destroy", 11 method: :delete,
12 user_path(user), 12 form: { data: { confirm: "Do you really want to delete user #{user.login}?" } } %>
13 :method => :delete,
14 :data => { :confirm => "Do you really want to delete user #{user.login}?" }
15 ) %>
16 </td> 13 </td>
17 <% end %> 14 <% end %>
18</tr> 15</tr>
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 43a6846..1c26f7d 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -22,4 +22,7 @@ Cccms::Application.configure do
22 config.hosts.clear 22 config.hosts.clear
23 23
24 config.middleware.delete ExceptionNotification::Rack 24 config.middleware.delete ExceptionNotification::Rack
25
26 config.assets.debug = false
27 config.assets.digest = true
25end 28end
diff --git a/public/assets/.sprockets-manifest-0856c2516a5e648c9c4b24cbb135cf0e.json b/public/assets/.sprockets-manifest-0856c2516a5e648c9c4b24cbb135cf0e.json
new file mode 100644
index 0000000..855368b
--- /dev/null
+++ b/public/assets/.sprockets-manifest-0856c2516a5e648c9c4b24cbb135cf0e.json
@@ -0,0 +1 @@
{"files":{"manifest-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.js":{"logical_path":"manifest.js","mtime":"2026-06-26T13:19:31+02:00","size":0,"digest":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","integrity":"sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="},"admin_bundle-e15d8265faa7d827f0b57416f9aeec7a730d7f47ede994b76014444669fb2081.js":{"logical_path":"admin_bundle.js","mtime":"2026-06-26T13:19:31+02:00","size":861801,"digest":"e15d8265faa7d827f0b57416f9aeec7a730d7f47ede994b76014444669fb2081","integrity":"sha256-4V2CZfqn2CfwtXQW+a7senMNf0ft6ZS3YBRERmn7IIE="},"actiontext-338257afa53cc53f94018abf7a897120d1eb3ee71f39e4641b2058442c9c4dc6.js":{"logical_path":"actiontext.js","mtime":"2026-06-26T13:19:31+02:00","size":30336,"digest":"338257afa53cc53f94018abf7a897120d1eb3ee71f39e4641b2058442c9c4dc6","integrity":"sha256-M4JXr6U8xT+UAYq/eolxINHrPucfOeRkGyBYRCycTcY="},"actiontext.esm-e787c6f528f0a88ee04de7c5ce4e3ab37fcf2691629ed21f0b30ee2db848c8c8.js":{"logical_path":"actiontext.esm.js","mtime":"2026-06-26T13:19:31+02:00","size":28519,"digest":"e787c6f528f0a88ee04de7c5ce4e3ab37fcf2691629ed21f0b30ee2db848c8c8","integrity":"sha256-54fG9SjwqI7gTefFzk46s3/PJpFintIfCzDuLbhIyMg="},"trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js":{"logical_path":"trix.js","mtime":"2026-06-26T13:19:31+02:00","size":512990,"digest":"488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc","integrity":"sha256-SIrIi1Dt7oqrc92CbplnB17tkAChP9E8vMF3RfhmUMw="},"trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css":{"logical_path":"trix.css","mtime":"2026-06-26T13:19:31+02:00","size":20027,"digest":"4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211","integrity":"sha256-TH9WdnaZrmwI8hAEydwjobdrBzSw/KYdRTSQDuD+8hE="},"activestorage-7dbadea816242c6d03cc2f59c58398ab55bb9a70ee859fa962ad4c7ad4c48594.js":{"logical_path":"activestorage.js","mtime":"2026-06-26T13:19:31+02:00","size":29379,"digest":"7dbadea816242c6d03cc2f59c58398ab55bb9a70ee859fa962ad4c7ad4c48594","integrity":"sha256-fbreqBYkLG0DzC9ZxYOYq1W7mnDuhZ+pYq1MetTEhZQ="},"activestorage.esm-b2d9aa45888a540d7e6969e484dbdb0a0a501ff56542ce737db6599b311e3385.js":{"logical_path":"activestorage.esm.js","mtime":"2026-06-26T13:19:31+02:00","size":27247,"digest":"b2d9aa45888a540d7e6969e484dbdb0a0a501ff56542ce737db6599b311e3385","integrity":"sha256-stmqRYiKVA1+aWnkhNvbCgpQH/VlQs5zfbZZmzEeM4U="},"actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js":{"logical_path":"actioncable.js","mtime":"2026-06-26T13:19:31+02:00","size":16474,"digest":"1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e","integrity":"sha256-GiOf+WZEvI/WJvh6dBdbTufq/SAfUDQDSkM8ItjE3D4="},"actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js":{"logical_path":"actioncable.esm.js","mtime":"2026-06-26T13:19:31+02:00","size":14813,"digest":"555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0","integrity":"sha256-VVZ55E8Rm+en5UEh/KC+sKWDLykzwaHtzQUVu6+tIuA="}},"assets":{"manifest.js":"manifest-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.js","admin_bundle.js":"admin_bundle-e15d8265faa7d827f0b57416f9aeec7a730d7f47ede994b76014444669fb2081.js","actiontext.js":"actiontext-338257afa53cc53f94018abf7a897120d1eb3ee71f39e4641b2058442c9c4dc6.js","actiontext.esm.js":"actiontext.esm-e787c6f528f0a88ee04de7c5ce4e3ab37fcf2691629ed21f0b30ee2db848c8c8.js","trix.js":"trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js","trix.css":"trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css","activestorage.js":"activestorage-7dbadea816242c6d03cc2f59c58398ab55bb9a70ee859fa962ad4c7ad4c48594.js","activestorage.esm.js":"activestorage.esm-b2d9aa45888a540d7e6969e484dbdb0a0a501ff56542ce737db6599b311e3385.js","actioncable.js":"actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js","actioncable.esm.js":"actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js"}} \ No newline at end of file
diff --git a/public/assets/actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js b/public/assets/actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js
new file mode 100644
index 0000000..5fc9943
--- /dev/null
+++ b/public/assets/actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js
@@ -0,0 +1,510 @@
1(function(global, factory) {
2 typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define([ "exports" ], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self,
3 factory(global.ActionCable = {}));
4})(this, (function(exports) {
5 "use strict";
6 var adapters = {
7 logger: typeof console !== "undefined" ? console : undefined,
8 WebSocket: typeof WebSocket !== "undefined" ? WebSocket : undefined
9 };
10 var logger = {
11 log(...messages) {
12 if (this.enabled) {
13 messages.push(Date.now());
14 adapters.logger.log("[ActionCable]", ...messages);
15 }
16 }
17 };
18 const now = () => (new Date).getTime();
19 const secondsSince = time => (now() - time) / 1e3;
20 class ConnectionMonitor {
21 constructor(connection) {
22 this.visibilityDidChange = this.visibilityDidChange.bind(this);
23 this.connection = connection;
24 this.reconnectAttempts = 0;
25 }
26 start() {
27 if (!this.isRunning()) {
28 this.startedAt = now();
29 delete this.stoppedAt;
30 this.startPolling();
31 addEventListener("visibilitychange", this.visibilityDidChange);
32 logger.log(`ConnectionMonitor started. stale threshold = ${this.constructor.staleThreshold} s`);
33 }
34 }
35 stop() {
36 if (this.isRunning()) {
37 this.stoppedAt = now();
38 this.stopPolling();
39 removeEventListener("visibilitychange", this.visibilityDidChange);
40 logger.log("ConnectionMonitor stopped");
41 }
42 }
43 isRunning() {
44 return this.startedAt && !this.stoppedAt;
45 }
46 recordMessage() {
47 this.pingedAt = now();
48 }
49 recordConnect() {
50 this.reconnectAttempts = 0;
51 delete this.disconnectedAt;
52 logger.log("ConnectionMonitor recorded connect");
53 }
54 recordDisconnect() {
55 this.disconnectedAt = now();
56 logger.log("ConnectionMonitor recorded disconnect");
57 }
58 startPolling() {
59 this.stopPolling();
60 this.poll();
61 }
62 stopPolling() {
63 clearTimeout(this.pollTimeout);
64 }
65 poll() {
66 this.pollTimeout = setTimeout((() => {
67 this.reconnectIfStale();
68 this.poll();
69 }), this.getPollInterval());
70 }
71 getPollInterval() {
72 const {staleThreshold: staleThreshold, reconnectionBackoffRate: reconnectionBackoffRate} = this.constructor;
73 const backoff = Math.pow(1 + reconnectionBackoffRate, Math.min(this.reconnectAttempts, 10));
74 const jitterMax = this.reconnectAttempts === 0 ? 1 : reconnectionBackoffRate;
75 const jitter = jitterMax * Math.random();
76 return staleThreshold * 1e3 * backoff * (1 + jitter);
77 }
78 reconnectIfStale() {
79 if (this.connectionIsStale()) {
80 logger.log(`ConnectionMonitor detected stale connection. reconnectAttempts = ${this.reconnectAttempts}, time stale = ${secondsSince(this.refreshedAt)} s, stale threshold = ${this.constructor.staleThreshold} s`);
81 this.reconnectAttempts++;
82 if (this.disconnectedRecently()) {
83 logger.log(`ConnectionMonitor skipping reopening recent disconnect. time disconnected = ${secondsSince(this.disconnectedAt)} s`);
84 } else {
85 logger.log("ConnectionMonitor reopening");
86 this.connection.reopen();
87 }
88 }
89 }
90 get refreshedAt() {
91 return this.pingedAt ? this.pingedAt : this.startedAt;
92 }
93 connectionIsStale() {
94 return secondsSince(this.refreshedAt) > this.constructor.staleThreshold;
95 }
96 disconnectedRecently() {
97 return this.disconnectedAt && secondsSince(this.disconnectedAt) < this.constructor.staleThreshold;
98 }
99 visibilityDidChange() {
100 if (document.visibilityState === "visible") {
101 setTimeout((() => {
102 if (this.connectionIsStale() || !this.connection.isOpen()) {
103 logger.log(`ConnectionMonitor reopening stale connection on visibilitychange. visibilityState = ${document.visibilityState}`);
104 this.connection.reopen();
105 }
106 }), 200);
107 }
108 }
109 }
110 ConnectionMonitor.staleThreshold = 6;
111 ConnectionMonitor.reconnectionBackoffRate = .15;
112 var INTERNAL = {
113 message_types: {
114 welcome: "welcome",
115 disconnect: "disconnect",
116 ping: "ping",
117 confirmation: "confirm_subscription",
118 rejection: "reject_subscription"
119 },
120 disconnect_reasons: {
121 unauthorized: "unauthorized",
122 invalid_request: "invalid_request",
123 server_restart: "server_restart",
124 remote: "remote"
125 },
126 default_mount_path: "/cable",
127 protocols: [ "actioncable-v1-json", "actioncable-unsupported" ]
128 };
129 const {message_types: message_types, protocols: protocols} = INTERNAL;
130 const supportedProtocols = protocols.slice(0, protocols.length - 1);
131 const indexOf = [].indexOf;
132 class Connection {
133 constructor(consumer) {
134 this.open = this.open.bind(this);
135 this.consumer = consumer;
136 this.subscriptions = this.consumer.subscriptions;
137 this.monitor = new ConnectionMonitor(this);
138 this.disconnected = true;
139 }
140 send(data) {
141 if (this.isOpen()) {
142 this.webSocket.send(JSON.stringify(data));
143 return true;
144 } else {
145 return false;
146 }
147 }
148 open() {
149 if (this.isActive()) {
150 logger.log(`Attempted to open WebSocket, but existing socket is ${this.getState()}`);
151 return false;
152 } else {
153 const socketProtocols = [ ...protocols, ...this.consumer.subprotocols || [] ];
154 logger.log(`Opening WebSocket, current state is ${this.getState()}, subprotocols: ${socketProtocols}`);
155 if (this.webSocket) {
156 this.uninstallEventHandlers();
157 }
158 this.webSocket = new adapters.WebSocket(this.consumer.url, socketProtocols);
159 this.installEventHandlers();
160 this.monitor.start();
161 return true;
162 }
163 }
164 close({allowReconnect: allowReconnect} = {
165 allowReconnect: true
166 }) {
167 if (!allowReconnect) {
168 this.monitor.stop();
169 }
170 if (this.isOpen()) {
171 return this.webSocket.close();
172 }
173 }
174 reopen() {
175 logger.log(`Reopening WebSocket, current state is ${this.getState()}`);
176 if (this.isActive()) {
177 try {
178 return this.close();
179 } catch (error) {
180 logger.log("Failed to reopen WebSocket", error);
181 } finally {
182 logger.log(`Reopening WebSocket in ${this.constructor.reopenDelay}ms`);
183 setTimeout(this.open, this.constructor.reopenDelay);
184 }
185 } else {
186 return this.open();
187 }
188 }
189 getProtocol() {
190 if (this.webSocket) {
191 return this.webSocket.protocol;
192 }
193 }
194 isOpen() {
195 return this.isState("open");
196 }
197 isActive() {
198 return this.isState("open", "connecting");
199 }
200 triedToReconnect() {
201 return this.monitor.reconnectAttempts > 0;
202 }
203 isProtocolSupported() {
204 return indexOf.call(supportedProtocols, this.getProtocol()) >= 0;
205 }
206 isState(...states) {
207 return indexOf.call(states, this.getState()) >= 0;
208 }
209 getState() {
210 if (this.webSocket) {
211 for (let state in adapters.WebSocket) {
212 if (adapters.WebSocket[state] === this.webSocket.readyState) {
213 return state.toLowerCase();
214 }
215 }
216 }
217 return null;
218 }
219 installEventHandlers() {
220 for (let eventName in this.events) {
221 const handler = this.events[eventName].bind(this);
222 this.webSocket[`on${eventName}`] = handler;
223 }
224 }
225 uninstallEventHandlers() {
226 for (let eventName in this.events) {
227 this.webSocket[`on${eventName}`] = function() {};
228 }
229 }
230 }
231 Connection.reopenDelay = 500;
232 Connection.prototype.events = {
233 message(event) {
234 if (!this.isProtocolSupported()) {
235 return;
236 }
237 const {identifier: identifier, message: message, reason: reason, reconnect: reconnect, type: type} = JSON.parse(event.data);
238 this.monitor.recordMessage();
239 switch (type) {
240 case message_types.welcome:
241 if (this.triedToReconnect()) {
242 this.reconnectAttempted = true;
243 }
244 this.monitor.recordConnect();
245 return this.subscriptions.reload();
246
247 case message_types.disconnect:
248 logger.log(`Disconnecting. Reason: ${reason}`);
249 return this.close({
250 allowReconnect: reconnect
251 });
252
253 case message_types.ping:
254 return null;
255
256 case message_types.confirmation:
257 this.subscriptions.confirmSubscription(identifier);
258 if (this.reconnectAttempted) {
259 this.reconnectAttempted = false;
260 return this.subscriptions.notify(identifier, "connected", {
261 reconnected: true
262 });
263 } else {
264 return this.subscriptions.notify(identifier, "connected", {
265 reconnected: false
266 });
267 }
268
269 case message_types.rejection:
270 return this.subscriptions.reject(identifier);
271
272 default:
273 return this.subscriptions.notify(identifier, "received", message);
274 }
275 },
276 open() {
277 logger.log(`WebSocket onopen event, using '${this.getProtocol()}' subprotocol`);
278 this.disconnected = false;
279 if (!this.isProtocolSupported()) {
280 logger.log("Protocol is unsupported. Stopping monitor and disconnecting.");
281 return this.close({
282 allowReconnect: false
283 });
284 }
285 },
286 close(event) {
287 logger.log("WebSocket onclose event");
288 if (this.disconnected) {
289 return;
290 }
291 this.disconnected = true;
292 this.monitor.recordDisconnect();
293 return this.subscriptions.notifyAll("disconnected", {
294 willAttemptReconnect: this.monitor.isRunning()
295 });
296 },
297 error() {
298 logger.log("WebSocket onerror event");
299 }
300 };
301 const extend = function(object, properties) {
302 if (properties != null) {
303 for (let key in properties) {
304 const value = properties[key];
305 object[key] = value;
306 }
307 }
308 return object;
309 };
310 class Subscription {
311 constructor(consumer, params = {}, mixin) {
312 this.consumer = consumer;
313 this.identifier = JSON.stringify(params);
314 extend(this, mixin);
315 }
316 perform(action, data = {}) {
317 data.action = action;
318 return this.send(data);
319 }
320 send(data) {
321 return this.consumer.send({
322 command: "message",
323 identifier: this.identifier,
324 data: JSON.stringify(data)
325 });
326 }
327 unsubscribe() {
328 return this.consumer.subscriptions.remove(this);
329 }
330 }
331 class SubscriptionGuarantor {
332 constructor(subscriptions) {
333 this.subscriptions = subscriptions;
334 this.pendingSubscriptions = [];
335 }
336 guarantee(subscription) {
337 if (this.pendingSubscriptions.indexOf(subscription) == -1) {
338 logger.log(`SubscriptionGuarantor guaranteeing ${subscription.identifier}`);
339 this.pendingSubscriptions.push(subscription);
340 } else {
341 logger.log(`SubscriptionGuarantor already guaranteeing ${subscription.identifier}`);
342 }
343 this.startGuaranteeing();
344 }
345 forget(subscription) {
346 logger.log(`SubscriptionGuarantor forgetting ${subscription.identifier}`);
347 this.pendingSubscriptions = this.pendingSubscriptions.filter((s => s !== subscription));
348 }
349 startGuaranteeing() {
350 this.stopGuaranteeing();
351 this.retrySubscribing();
352 }
353 stopGuaranteeing() {
354 clearTimeout(this.retryTimeout);
355 }
356 retrySubscribing() {
357 this.retryTimeout = setTimeout((() => {
358 if (this.subscriptions && typeof this.subscriptions.subscribe === "function") {
359 this.pendingSubscriptions.map((subscription => {
360 logger.log(`SubscriptionGuarantor resubscribing ${subscription.identifier}`);
361 this.subscriptions.subscribe(subscription);
362 }));
363 }
364 }), 500);
365 }
366 }
367 class Subscriptions {
368 constructor(consumer) {
369 this.consumer = consumer;
370 this.guarantor = new SubscriptionGuarantor(this);
371 this.subscriptions = [];
372 }
373 create(channelName, mixin) {
374 const channel = channelName;
375 const params = typeof channel === "object" ? channel : {
376 channel: channel
377 };
378 const subscription = new Subscription(this.consumer, params, mixin);
379 return this.add(subscription);
380 }
381 add(subscription) {
382 this.subscriptions.push(subscription);
383 this.consumer.ensureActiveConnection();
384 this.notify(subscription, "initialized");
385 this.subscribe(subscription);
386 return subscription;
387 }
388 remove(subscription) {
389 this.forget(subscription);
390 if (!this.findAll(subscription.identifier).length) {
391 this.sendCommand(subscription, "unsubscribe");
392 }
393 return subscription;
394 }
395 reject(identifier) {
396 return this.findAll(identifier).map((subscription => {
397 this.forget(subscription);
398 this.notify(subscription, "rejected");
399 return subscription;
400 }));
401 }
402 forget(subscription) {
403 this.guarantor.forget(subscription);
404 this.subscriptions = this.subscriptions.filter((s => s !== subscription));
405 return subscription;
406 }
407 findAll(identifier) {
408 return this.subscriptions.filter((s => s.identifier === identifier));
409 }
410 reload() {
411 return this.subscriptions.map((subscription => this.subscribe(subscription)));
412 }
413 notifyAll(callbackName, ...args) {
414 return this.subscriptions.map((subscription => this.notify(subscription, callbackName, ...args)));
415 }
416 notify(subscription, callbackName, ...args) {
417 let subscriptions;
418 if (typeof subscription === "string") {
419 subscriptions = this.findAll(subscription);
420 } else {
421 subscriptions = [ subscription ];
422 }
423 return subscriptions.map((subscription => typeof subscription[callbackName] === "function" ? subscription[callbackName](...args) : undefined));
424 }
425 subscribe(subscription) {
426 if (this.sendCommand(subscription, "subscribe")) {
427 this.guarantor.guarantee(subscription);
428 }
429 }
430 confirmSubscription(identifier) {
431 logger.log(`Subscription confirmed ${identifier}`);
432 this.findAll(identifier).map((subscription => this.guarantor.forget(subscription)));
433 }
434 sendCommand(subscription, command) {
435 const {identifier: identifier} = subscription;
436 return this.consumer.send({
437 command: command,
438 identifier: identifier
439 });
440 }
441 }
442 class Consumer {
443 constructor(url) {
444 this._url = url;
445 this.subscriptions = new Subscriptions(this);
446 this.connection = new Connection(this);
447 this.subprotocols = [];
448 }
449 get url() {
450 return createWebSocketURL(this._url);
451 }
452 send(data) {
453 return this.connection.send(data);
454 }
455 connect() {
456 return this.connection.open();
457 }
458 disconnect() {
459 return this.connection.close({
460 allowReconnect: false
461 });
462 }
463 ensureActiveConnection() {
464 if (!this.connection.isActive()) {
465 return this.connection.open();
466 }
467 }
468 addSubProtocol(subprotocol) {
469 this.subprotocols = [ ...this.subprotocols, subprotocol ];
470 }
471 }
472 function createWebSocketURL(url) {
473 if (typeof url === "function") {
474 url = url();
475 }
476 if (url && !/^wss?:/i.test(url)) {
477 const a = document.createElement("a");
478 a.href = url;
479 a.href = a.href;
480 a.protocol = a.protocol.replace("http", "ws");
481 return a.href;
482 } else {
483 return url;
484 }
485 }
486 function createConsumer(url = getConfig("url") || INTERNAL.default_mount_path) {
487 return new Consumer(url);
488 }
489 function getConfig(name) {
490 const element = document.head.querySelector(`meta[name='action-cable-${name}']`);
491 if (element) {
492 return element.getAttribute("content");
493 }
494 }
495 exports.Connection = Connection;
496 exports.ConnectionMonitor = ConnectionMonitor;
497 exports.Consumer = Consumer;
498 exports.INTERNAL = INTERNAL;
499 exports.Subscription = Subscription;
500 exports.SubscriptionGuarantor = SubscriptionGuarantor;
501 exports.Subscriptions = Subscriptions;
502 exports.adapters = adapters;
503 exports.createConsumer = createConsumer;
504 exports.createWebSocketURL = createWebSocketURL;
505 exports.getConfig = getConfig;
506 exports.logger = logger;
507 Object.defineProperty(exports, "__esModule", {
508 value: true
509 });
510}));
diff --git a/public/assets/actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js.gz b/public/assets/actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js.gz
new file mode 100644
index 0000000..cc38acc
--- /dev/null
+++ b/public/assets/actioncable-1a239ff96644bc8fd626f87a74175b4ee7eafd201f5034034a433c22d8c4dc3e.js.gz
Binary files differ
diff --git a/public/assets/actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js b/public/assets/actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js
new file mode 100644
index 0000000..1832009
--- /dev/null
+++ b/public/assets/actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js
@@ -0,0 +1,512 @@
1var adapters = {
2 logger: typeof console !== "undefined" ? console : undefined,
3 WebSocket: typeof WebSocket !== "undefined" ? WebSocket : undefined
4};
5
6var logger = {
7 log(...messages) {
8 if (this.enabled) {
9 messages.push(Date.now());
10 adapters.logger.log("[ActionCable]", ...messages);
11 }
12 }
13};
14
15const now = () => (new Date).getTime();
16
17const secondsSince = time => (now() - time) / 1e3;
18
19class ConnectionMonitor {
20 constructor(connection) {
21 this.visibilityDidChange = this.visibilityDidChange.bind(this);
22 this.connection = connection;
23 this.reconnectAttempts = 0;
24 }
25 start() {
26 if (!this.isRunning()) {
27 this.startedAt = now();
28 delete this.stoppedAt;
29 this.startPolling();
30 addEventListener("visibilitychange", this.visibilityDidChange);
31 logger.log(`ConnectionMonitor started. stale threshold = ${this.constructor.staleThreshold} s`);
32 }
33 }
34 stop() {
35 if (this.isRunning()) {
36 this.stoppedAt = now();
37 this.stopPolling();
38 removeEventListener("visibilitychange", this.visibilityDidChange);
39 logger.log("ConnectionMonitor stopped");
40 }
41 }
42 isRunning() {
43 return this.startedAt && !this.stoppedAt;
44 }
45 recordMessage() {
46 this.pingedAt = now();
47 }
48 recordConnect() {
49 this.reconnectAttempts = 0;
50 delete this.disconnectedAt;
51 logger.log("ConnectionMonitor recorded connect");
52 }
53 recordDisconnect() {
54 this.disconnectedAt = now();
55 logger.log("ConnectionMonitor recorded disconnect");
56 }
57 startPolling() {
58 this.stopPolling();
59 this.poll();
60 }
61 stopPolling() {
62 clearTimeout(this.pollTimeout);
63 }
64 poll() {
65 this.pollTimeout = setTimeout((() => {
66 this.reconnectIfStale();
67 this.poll();
68 }), this.getPollInterval());
69 }
70 getPollInterval() {
71 const {staleThreshold: staleThreshold, reconnectionBackoffRate: reconnectionBackoffRate} = this.constructor;
72 const backoff = Math.pow(1 + reconnectionBackoffRate, Math.min(this.reconnectAttempts, 10));
73 const jitterMax = this.reconnectAttempts === 0 ? 1 : reconnectionBackoffRate;
74 const jitter = jitterMax * Math.random();
75 return staleThreshold * 1e3 * backoff * (1 + jitter);
76 }
77 reconnectIfStale() {
78 if (this.connectionIsStale()) {
79 logger.log(`ConnectionMonitor detected stale connection. reconnectAttempts = ${this.reconnectAttempts}, time stale = ${secondsSince(this.refreshedAt)} s, stale threshold = ${this.constructor.staleThreshold} s`);
80 this.reconnectAttempts++;
81 if (this.disconnectedRecently()) {
82 logger.log(`ConnectionMonitor skipping reopening recent disconnect. time disconnected = ${secondsSince(this.disconnectedAt)} s`);
83 } else {
84 logger.log("ConnectionMonitor reopening");
85 this.connection.reopen();
86 }
87 }
88 }
89 get refreshedAt() {
90 return this.pingedAt ? this.pingedAt : this.startedAt;
91 }
92 connectionIsStale() {
93 return secondsSince(this.refreshedAt) > this.constructor.staleThreshold;
94 }
95 disconnectedRecently() {
96 return this.disconnectedAt && secondsSince(this.disconnectedAt) < this.constructor.staleThreshold;
97 }
98 visibilityDidChange() {
99 if (document.visibilityState === "visible") {
100 setTimeout((() => {
101 if (this.connectionIsStale() || !this.connection.isOpen()) {
102 logger.log(`ConnectionMonitor reopening stale connection on visibilitychange. visibilityState = ${document.visibilityState}`);
103 this.connection.reopen();
104 }
105 }), 200);
106 }
107 }
108}
109
110ConnectionMonitor.staleThreshold = 6;
111
112ConnectionMonitor.reconnectionBackoffRate = .15;
113
114var INTERNAL = {
115 message_types: {
116 welcome: "welcome",
117 disconnect: "disconnect",
118 ping: "ping",
119 confirmation: "confirm_subscription",
120 rejection: "reject_subscription"
121 },
122 disconnect_reasons: {
123 unauthorized: "unauthorized",
124 invalid_request: "invalid_request",
125 server_restart: "server_restart",
126 remote: "remote"
127 },
128 default_mount_path: "/cable",
129 protocols: [ "actioncable-v1-json", "actioncable-unsupported" ]
130};
131
132const {message_types: message_types, protocols: protocols} = INTERNAL;
133
134const supportedProtocols = protocols.slice(0, protocols.length - 1);
135
136const indexOf = [].indexOf;
137
138class Connection {
139 constructor(consumer) {
140 this.open = this.open.bind(this);
141 this.consumer = consumer;
142 this.subscriptions = this.consumer.subscriptions;
143 this.monitor = new ConnectionMonitor(this);
144 this.disconnected = true;
145 }
146 send(data) {
147 if (this.isOpen()) {
148 this.webSocket.send(JSON.stringify(data));
149 return true;
150 } else {
151 return false;
152 }
153 }
154 open() {
155 if (this.isActive()) {
156 logger.log(`Attempted to open WebSocket, but existing socket is ${this.getState()}`);
157 return false;
158 } else {
159 const socketProtocols = [ ...protocols, ...this.consumer.subprotocols || [] ];
160 logger.log(`Opening WebSocket, current state is ${this.getState()}, subprotocols: ${socketProtocols}`);
161 if (this.webSocket) {
162 this.uninstallEventHandlers();
163 }
164 this.webSocket = new adapters.WebSocket(this.consumer.url, socketProtocols);
165 this.installEventHandlers();
166 this.monitor.start();
167 return true;
168 }
169 }
170 close({allowReconnect: allowReconnect} = {
171 allowReconnect: true
172 }) {
173 if (!allowReconnect) {
174 this.monitor.stop();
175 }
176 if (this.isOpen()) {
177 return this.webSocket.close();
178 }
179 }
180 reopen() {
181 logger.log(`Reopening WebSocket, current state is ${this.getState()}`);
182 if (this.isActive()) {
183 try {
184 return this.close();
185 } catch (error) {
186 logger.log("Failed to reopen WebSocket", error);
187 } finally {
188 logger.log(`Reopening WebSocket in ${this.constructor.reopenDelay}ms`);
189 setTimeout(this.open, this.constructor.reopenDelay);
190 }
191 } else {
192 return this.open();
193 }
194 }
195 getProtocol() {
196 if (this.webSocket) {
197 return this.webSocket.protocol;
198 }
199 }
200 isOpen() {
201 return this.isState("open");
202 }
203 isActive() {
204 return this.isState("open", "connecting");
205 }
206 triedToReconnect() {
207 return this.monitor.reconnectAttempts > 0;
208 }
209 isProtocolSupported() {
210 return indexOf.call(supportedProtocols, this.getProtocol()) >= 0;
211 }
212 isState(...states) {
213 return indexOf.call(states, this.getState()) >= 0;
214 }
215 getState() {
216 if (this.webSocket) {
217 for (let state in adapters.WebSocket) {
218 if (adapters.WebSocket[state] === this.webSocket.readyState) {
219 return state.toLowerCase();
220 }
221 }
222 }
223 return null;
224 }
225 installEventHandlers() {
226 for (let eventName in this.events) {
227 const handler = this.events[eventName].bind(this);
228 this.webSocket[`on${eventName}`] = handler;
229 }
230 }
231 uninstallEventHandlers() {
232 for (let eventName in this.events) {
233 this.webSocket[`on${eventName}`] = function() {};
234 }
235 }
236}
237
238Connection.reopenDelay = 500;
239
240Connection.prototype.events = {
241 message(event) {
242 if (!this.isProtocolSupported()) {
243 return;
244 }
245 const {identifier: identifier, message: message, reason: reason, reconnect: reconnect, type: type} = JSON.parse(event.data);
246 this.monitor.recordMessage();
247 switch (type) {
248 case message_types.welcome:
249 if (this.triedToReconnect()) {
250 this.reconnectAttempted = true;
251 }
252 this.monitor.recordConnect();
253 return this.subscriptions.reload();
254
255 case message_types.disconnect:
256 logger.log(`Disconnecting. Reason: ${reason}`);
257 return this.close({
258 allowReconnect: reconnect
259 });
260
261 case message_types.ping:
262 return null;
263
264 case message_types.confirmation:
265 this.subscriptions.confirmSubscription(identifier);
266 if (this.reconnectAttempted) {
267 this.reconnectAttempted = false;
268 return this.subscriptions.notify(identifier, "connected", {
269 reconnected: true
270 });
271 } else {
272 return this.subscriptions.notify(identifier, "connected", {
273 reconnected: false
274 });
275 }
276
277 case message_types.rejection:
278 return this.subscriptions.reject(identifier);
279
280 default:
281 return this.subscriptions.notify(identifier, "received", message);
282 }
283 },
284 open() {
285 logger.log(`WebSocket onopen event, using '${this.getProtocol()}' subprotocol`);
286 this.disconnected = false;
287 if (!this.isProtocolSupported()) {
288 logger.log("Protocol is unsupported. Stopping monitor and disconnecting.");
289 return this.close({
290 allowReconnect: false
291 });
292 }
293 },
294 close(event) {
295 logger.log("WebSocket onclose event");
296 if (this.disconnected) {
297 return;
298 }
299 this.disconnected = true;
300 this.monitor.recordDisconnect();
301 return this.subscriptions.notifyAll("disconnected", {
302 willAttemptReconnect: this.monitor.isRunning()
303 });
304 },
305 error() {
306 logger.log("WebSocket onerror event");
307 }
308};
309
310const extend = function(object, properties) {
311 if (properties != null) {
312 for (let key in properties) {
313 const value = properties[key];
314 object[key] = value;
315 }
316 }
317 return object;
318};
319
320class Subscription {
321 constructor(consumer, params = {}, mixin) {
322 this.consumer = consumer;
323 this.identifier = JSON.stringify(params);
324 extend(this, mixin);
325 }
326 perform(action, data = {}) {
327 data.action = action;
328 return this.send(data);
329 }
330 send(data) {
331 return this.consumer.send({
332 command: "message",
333 identifier: this.identifier,
334 data: JSON.stringify(data)
335 });
336 }
337 unsubscribe() {
338 return this.consumer.subscriptions.remove(this);
339 }
340}
341
342class SubscriptionGuarantor {
343 constructor(subscriptions) {
344 this.subscriptions = subscriptions;
345 this.pendingSubscriptions = [];
346 }
347 guarantee(subscription) {
348 if (this.pendingSubscriptions.indexOf(subscription) == -1) {
349 logger.log(`SubscriptionGuarantor guaranteeing ${subscription.identifier}`);
350 this.pendingSubscriptions.push(subscription);
351 } else {
352 logger.log(`SubscriptionGuarantor already guaranteeing ${subscription.identifier}`);
353 }
354 this.startGuaranteeing();
355 }
356 forget(subscription) {
357 logger.log(`SubscriptionGuarantor forgetting ${subscription.identifier}`);
358 this.pendingSubscriptions = this.pendingSubscriptions.filter((s => s !== subscription));
359 }
360 startGuaranteeing() {
361 this.stopGuaranteeing();
362 this.retrySubscribing();
363 }
364 stopGuaranteeing() {
365 clearTimeout(this.retryTimeout);
366 }
367 retrySubscribing() {
368 this.retryTimeout = setTimeout((() => {
369 if (this.subscriptions && typeof this.subscriptions.subscribe === "function") {
370 this.pendingSubscriptions.map((subscription => {
371 logger.log(`SubscriptionGuarantor resubscribing ${subscription.identifier}`);
372 this.subscriptions.subscribe(subscription);
373 }));
374 }
375 }), 500);
376 }
377}
378
379class Subscriptions {
380 constructor(consumer) {
381 this.consumer = consumer;
382 this.guarantor = new SubscriptionGuarantor(this);
383 this.subscriptions = [];
384 }
385 create(channelName, mixin) {
386 const channel = channelName;
387 const params = typeof channel === "object" ? channel : {
388 channel: channel
389 };
390 const subscription = new Subscription(this.consumer, params, mixin);
391 return this.add(subscription);
392 }
393 add(subscription) {
394 this.subscriptions.push(subscription);
395 this.consumer.ensureActiveConnection();
396 this.notify(subscription, "initialized");
397 this.subscribe(subscription);
398 return subscription;
399 }
400 remove(subscription) {
401 this.forget(subscription);
402 if (!this.findAll(subscription.identifier).length) {
403 this.sendCommand(subscription, "unsubscribe");
404 }
405 return subscription;
406 }
407 reject(identifier) {
408 return this.findAll(identifier).map((subscription => {
409 this.forget(subscription);
410 this.notify(subscription, "rejected");
411 return subscription;
412 }));
413 }
414 forget(subscription) {
415 this.guarantor.forget(subscription);
416 this.subscriptions = this.subscriptions.filter((s => s !== subscription));
417 return subscription;
418 }
419 findAll(identifier) {
420 return this.subscriptions.filter((s => s.identifier === identifier));
421 }
422 reload() {
423 return this.subscriptions.map((subscription => this.subscribe(subscription)));
424 }
425 notifyAll(callbackName, ...args) {
426 return this.subscriptions.map((subscription => this.notify(subscription, callbackName, ...args)));
427 }
428 notify(subscription, callbackName, ...args) {
429 let subscriptions;
430 if (typeof subscription === "string") {
431 subscriptions = this.findAll(subscription);
432 } else {
433 subscriptions = [ subscription ];
434 }
435 return subscriptions.map((subscription => typeof subscription[callbackName] === "function" ? subscription[callbackName](...args) : undefined));
436 }
437 subscribe(subscription) {
438 if (this.sendCommand(subscription, "subscribe")) {
439 this.guarantor.guarantee(subscription);
440 }
441 }
442 confirmSubscription(identifier) {
443 logger.log(`Subscription confirmed ${identifier}`);
444 this.findAll(identifier).map((subscription => this.guarantor.forget(subscription)));
445 }
446 sendCommand(subscription, command) {
447 const {identifier: identifier} = subscription;
448 return this.consumer.send({
449 command: command,
450 identifier: identifier
451 });
452 }
453}
454
455class Consumer {
456 constructor(url) {
457 this._url = url;
458 this.subscriptions = new Subscriptions(this);
459 this.connection = new Connection(this);
460 this.subprotocols = [];
461 }
462 get url() {
463 return createWebSocketURL(this._url);
464 }
465 send(data) {
466 return this.connection.send(data);
467 }
468 connect() {
469 return this.connection.open();
470 }
471 disconnect() {
472 return this.connection.close({
473 allowReconnect: false
474 });
475 }
476 ensureActiveConnection() {
477 if (!this.connection.isActive()) {
478 return this.connection.open();
479 }
480 }
481 addSubProtocol(subprotocol) {
482 this.subprotocols = [ ...this.subprotocols, subprotocol ];
483 }
484}
485
486function createWebSocketURL(url) {
487 if (typeof url === "function") {
488 url = url();
489 }
490 if (url && !/^wss?:/i.test(url)) {
491 const a = document.createElement("a");
492 a.href = url;
493 a.href = a.href;
494 a.protocol = a.protocol.replace("http", "ws");
495 return a.href;
496 } else {
497 return url;
498 }
499}
500
501function createConsumer(url = getConfig("url") || INTERNAL.default_mount_path) {
502 return new Consumer(url);
503}
504
505function getConfig(name) {
506 const element = document.head.querySelector(`meta[name='action-cable-${name}']`);
507 if (element) {
508 return element.getAttribute("content");
509 }
510}
511
512export { Connection, ConnectionMonitor, Consumer, INTERNAL, Subscription, SubscriptionGuarantor, Subscriptions, adapters, createConsumer, createWebSocketURL, getConfig, logger };
diff --git a/public/assets/actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js.gz b/public/assets/actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js.gz
new file mode 100644
index 0000000..dee797d
--- /dev/null
+++ b/public/assets/actioncable.esm-555679e44f119be7a7e54121fca0beb0a5832f2933c1a1edcd0515bbafad22e0.js.gz
Binary files differ
diff --git a/public/assets/actiontext-338257afa53cc53f94018abf7a897120d1eb3ee71f39e4641b2058442c9c4dc6.js b/public/assets/actiontext-338257afa53cc53f94018abf7a897120d1eb3ee71f39e4641b2058442c9c4dc6.js
new file mode 100644
index 0000000..ef283f2
--- /dev/null
+++ b/public/assets/actiontext-338257afa53cc53f94018abf7a897120d1eb3ee71f39e4641b2058442c9c4dc6.js
@@ -0,0 +1,862 @@
1(function(factory) {
2 typeof define === "function" && define.amd ? define(factory) : factory();
3})((function() {
4 "use strict";
5 var sparkMd5 = {
6 exports: {}
7 };
8 (function(module, exports) {
9 (function(factory) {
10 {
11 module.exports = factory();
12 }
13 })((function(undefined$1) {
14 var hex_chr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ];
15 function md5cycle(x, k) {
16 var a = x[0], b = x[1], c = x[2], d = x[3];
17 a += (b & c | ~b & d) + k[0] - 680876936 | 0;
18 a = (a << 7 | a >>> 25) + b | 0;
19 d += (a & b | ~a & c) + k[1] - 389564586 | 0;
20 d = (d << 12 | d >>> 20) + a | 0;
21 c += (d & a | ~d & b) + k[2] + 606105819 | 0;
22 c = (c << 17 | c >>> 15) + d | 0;
23 b += (c & d | ~c & a) + k[3] - 1044525330 | 0;
24 b = (b << 22 | b >>> 10) + c | 0;
25 a += (b & c | ~b & d) + k[4] - 176418897 | 0;
26 a = (a << 7 | a >>> 25) + b | 0;
27 d += (a & b | ~a & c) + k[5] + 1200080426 | 0;
28 d = (d << 12 | d >>> 20) + a | 0;
29 c += (d & a | ~d & b) + k[6] - 1473231341 | 0;
30 c = (c << 17 | c >>> 15) + d | 0;
31 b += (c & d | ~c & a) + k[7] - 45705983 | 0;
32 b = (b << 22 | b >>> 10) + c | 0;
33 a += (b & c | ~b & d) + k[8] + 1770035416 | 0;
34 a = (a << 7 | a >>> 25) + b | 0;
35 d += (a & b | ~a & c) + k[9] - 1958414417 | 0;
36 d = (d << 12 | d >>> 20) + a | 0;
37 c += (d & a | ~d & b) + k[10] - 42063 | 0;
38 c = (c << 17 | c >>> 15) + d | 0;
39 b += (c & d | ~c & a) + k[11] - 1990404162 | 0;
40 b = (b << 22 | b >>> 10) + c | 0;
41 a += (b & c | ~b & d) + k[12] + 1804603682 | 0;
42 a = (a << 7 | a >>> 25) + b | 0;
43 d += (a & b | ~a & c) + k[13] - 40341101 | 0;
44 d = (d << 12 | d >>> 20) + a | 0;
45 c += (d & a | ~d & b) + k[14] - 1502002290 | 0;
46 c = (c << 17 | c >>> 15) + d | 0;
47 b += (c & d | ~c & a) + k[15] + 1236535329 | 0;
48 b = (b << 22 | b >>> 10) + c | 0;
49 a += (b & d | c & ~d) + k[1] - 165796510 | 0;
50 a = (a << 5 | a >>> 27) + b | 0;
51 d += (a & c | b & ~c) + k[6] - 1069501632 | 0;
52 d = (d << 9 | d >>> 23) + a | 0;
53 c += (d & b | a & ~b) + k[11] + 643717713 | 0;
54 c = (c << 14 | c >>> 18) + d | 0;
55 b += (c & a | d & ~a) + k[0] - 373897302 | 0;
56 b = (b << 20 | b >>> 12) + c | 0;
57 a += (b & d | c & ~d) + k[5] - 701558691 | 0;
58 a = (a << 5 | a >>> 27) + b | 0;
59 d += (a & c | b & ~c) + k[10] + 38016083 | 0;
60 d = (d << 9 | d >>> 23) + a | 0;
61 c += (d & b | a & ~b) + k[15] - 660478335 | 0;
62 c = (c << 14 | c >>> 18) + d | 0;
63 b += (c & a | d & ~a) + k[4] - 405537848 | 0;
64 b = (b << 20 | b >>> 12) + c | 0;
65 a += (b & d | c & ~d) + k[9] + 568446438 | 0;
66 a = (a << 5 | a >>> 27) + b | 0;
67 d += (a & c | b & ~c) + k[14] - 1019803690 | 0;
68 d = (d << 9 | d >>> 23) + a | 0;
69 c += (d & b | a & ~b) + k[3] - 187363961 | 0;
70 c = (c << 14 | c >>> 18) + d | 0;
71 b += (c & a | d & ~a) + k[8] + 1163531501 | 0;
72 b = (b << 20 | b >>> 12) + c | 0;
73 a += (b & d | c & ~d) + k[13] - 1444681467 | 0;
74 a = (a << 5 | a >>> 27) + b | 0;
75 d += (a & c | b & ~c) + k[2] - 51403784 | 0;
76 d = (d << 9 | d >>> 23) + a | 0;
77 c += (d & b | a & ~b) + k[7] + 1735328473 | 0;
78 c = (c << 14 | c >>> 18) + d | 0;
79 b += (c & a | d & ~a) + k[12] - 1926607734 | 0;
80 b = (b << 20 | b >>> 12) + c | 0;
81 a += (b ^ c ^ d) + k[5] - 378558 | 0;
82 a = (a << 4 | a >>> 28) + b | 0;
83 d += (a ^ b ^ c) + k[8] - 2022574463 | 0;
84 d = (d << 11 | d >>> 21) + a | 0;
85 c += (d ^ a ^ b) + k[11] + 1839030562 | 0;
86 c = (c << 16 | c >>> 16) + d | 0;
87 b += (c ^ d ^ a) + k[14] - 35309556 | 0;
88 b = (b << 23 | b >>> 9) + c | 0;
89 a += (b ^ c ^ d) + k[1] - 1530992060 | 0;
90 a = (a << 4 | a >>> 28) + b | 0;
91 d += (a ^ b ^ c) + k[4] + 1272893353 | 0;
92 d = (d << 11 | d >>> 21) + a | 0;
93 c += (d ^ a ^ b) + k[7] - 155497632 | 0;
94 c = (c << 16 | c >>> 16) + d | 0;
95 b += (c ^ d ^ a) + k[10] - 1094730640 | 0;
96 b = (b << 23 | b >>> 9) + c | 0;
97 a += (b ^ c ^ d) + k[13] + 681279174 | 0;
98 a = (a << 4 | a >>> 28) + b | 0;
99 d += (a ^ b ^ c) + k[0] - 358537222 | 0;
100 d = (d << 11 | d >>> 21) + a | 0;
101 c += (d ^ a ^ b) + k[3] - 722521979 | 0;
102 c = (c << 16 | c >>> 16) + d | 0;
103 b += (c ^ d ^ a) + k[6] + 76029189 | 0;
104 b = (b << 23 | b >>> 9) + c | 0;
105 a += (b ^ c ^ d) + k[9] - 640364487 | 0;
106 a = (a << 4 | a >>> 28) + b | 0;
107 d += (a ^ b ^ c) + k[12] - 421815835 | 0;
108 d = (d << 11 | d >>> 21) + a | 0;
109 c += (d ^ a ^ b) + k[15] + 530742520 | 0;
110 c = (c << 16 | c >>> 16) + d | 0;
111 b += (c ^ d ^ a) + k[2] - 995338651 | 0;
112 b = (b << 23 | b >>> 9) + c | 0;
113 a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;
114 a = (a << 6 | a >>> 26) + b | 0;
115 d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;
116 d = (d << 10 | d >>> 22) + a | 0;
117 c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;
118 c = (c << 15 | c >>> 17) + d | 0;
119 b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;
120 b = (b << 21 | b >>> 11) + c | 0;
121 a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;
122 a = (a << 6 | a >>> 26) + b | 0;
123 d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;
124 d = (d << 10 | d >>> 22) + a | 0;
125 c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;
126 c = (c << 15 | c >>> 17) + d | 0;
127 b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;
128 b = (b << 21 | b >>> 11) + c | 0;
129 a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;
130 a = (a << 6 | a >>> 26) + b | 0;
131 d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;
132 d = (d << 10 | d >>> 22) + a | 0;
133 c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;
134 c = (c << 15 | c >>> 17) + d | 0;
135 b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;
136 b = (b << 21 | b >>> 11) + c | 0;
137 a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;
138 a = (a << 6 | a >>> 26) + b | 0;
139 d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;
140 d = (d << 10 | d >>> 22) + a | 0;
141 c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;
142 c = (c << 15 | c >>> 17) + d | 0;
143 b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;
144 b = (b << 21 | b >>> 11) + c | 0;
145 x[0] = a + x[0] | 0;
146 x[1] = b + x[1] | 0;
147 x[2] = c + x[2] | 0;
148 x[3] = d + x[3] | 0;
149 }
150 function md5blk(s) {
151 var md5blks = [], i;
152 for (i = 0; i < 64; i += 4) {
153 md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
154 }
155 return md5blks;
156 }
157 function md5blk_array(a) {
158 var md5blks = [], i;
159 for (i = 0; i < 64; i += 4) {
160 md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
161 }
162 return md5blks;
163 }
164 function md51(s) {
165 var n = s.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
166 for (i = 64; i <= n; i += 64) {
167 md5cycle(state, md5blk(s.substring(i - 64, i)));
168 }
169 s = s.substring(i - 64);
170 length = s.length;
171 tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
172 for (i = 0; i < length; i += 1) {
173 tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);
174 }
175 tail[i >> 2] |= 128 << (i % 4 << 3);
176 if (i > 55) {
177 md5cycle(state, tail);
178 for (i = 0; i < 16; i += 1) {
179 tail[i] = 0;
180 }
181 }
182 tmp = n * 8;
183 tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
184 lo = parseInt(tmp[2], 16);
185 hi = parseInt(tmp[1], 16) || 0;
186 tail[14] = lo;
187 tail[15] = hi;
188 md5cycle(state, tail);
189 return state;
190 }
191 function md51_array(a) {
192 var n = a.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
193 for (i = 64; i <= n; i += 64) {
194 md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
195 }
196 a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0);
197 length = a.length;
198 tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
199 for (i = 0; i < length; i += 1) {
200 tail[i >> 2] |= a[i] << (i % 4 << 3);
201 }
202 tail[i >> 2] |= 128 << (i % 4 << 3);
203 if (i > 55) {
204 md5cycle(state, tail);
205 for (i = 0; i < 16; i += 1) {
206 tail[i] = 0;
207 }
208 }
209 tmp = n * 8;
210 tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
211 lo = parseInt(tmp[2], 16);
212 hi = parseInt(tmp[1], 16) || 0;
213 tail[14] = lo;
214 tail[15] = hi;
215 md5cycle(state, tail);
216 return state;
217 }
218 function rhex(n) {
219 var s = "", j;
220 for (j = 0; j < 4; j += 1) {
221 s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15];
222 }
223 return s;
224 }
225 function hex(x) {
226 var i;
227 for (i = 0; i < x.length; i += 1) {
228 x[i] = rhex(x[i]);
229 }
230 return x.join("");
231 }
232 if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ;
233 if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) {
234 (function() {
235 function clamp(val, length) {
236 val = val | 0 || 0;
237 if (val < 0) {
238 return Math.max(val + length, 0);
239 }
240 return Math.min(val, length);
241 }
242 ArrayBuffer.prototype.slice = function(from, to) {
243 var length = this.byteLength, begin = clamp(from, length), end = length, num, target, targetArray, sourceArray;
244 if (to !== undefined$1) {
245 end = clamp(to, length);
246 }
247 if (begin > end) {
248 return new ArrayBuffer(0);
249 }
250 num = end - begin;
251 target = new ArrayBuffer(num);
252 targetArray = new Uint8Array(target);
253 sourceArray = new Uint8Array(this, begin, num);
254 targetArray.set(sourceArray);
255 return target;
256 };
257 })();
258 }
259 function toUtf8(str) {
260 if (/[\u0080-\uFFFF]/.test(str)) {
261 str = unescape(encodeURIComponent(str));
262 }
263 return str;
264 }
265 function utf8Str2ArrayBuffer(str, returnUInt8Array) {
266 var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i;
267 for (i = 0; i < length; i += 1) {
268 arr[i] = str.charCodeAt(i);
269 }
270 return returnUInt8Array ? arr : buff;
271 }
272 function arrayBuffer2Utf8Str(buff) {
273 return String.fromCharCode.apply(null, new Uint8Array(buff));
274 }
275 function concatenateArrayBuffers(first, second, returnUInt8Array) {
276 var result = new Uint8Array(first.byteLength + second.byteLength);
277 result.set(new Uint8Array(first));
278 result.set(new Uint8Array(second), first.byteLength);
279 return returnUInt8Array ? result : result.buffer;
280 }
281 function hexToBinaryString(hex) {
282 var bytes = [], length = hex.length, x;
283 for (x = 0; x < length - 1; x += 2) {
284 bytes.push(parseInt(hex.substr(x, 2), 16));
285 }
286 return String.fromCharCode.apply(String, bytes);
287 }
288 function SparkMD5() {
289 this.reset();
290 }
291 SparkMD5.prototype.append = function(str) {
292 this.appendBinary(toUtf8(str));
293 return this;
294 };
295 SparkMD5.prototype.appendBinary = function(contents) {
296 this._buff += contents;
297 this._length += contents.length;
298 var length = this._buff.length, i;
299 for (i = 64; i <= length; i += 64) {
300 md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)));
301 }
302 this._buff = this._buff.substring(i - 64);
303 return this;
304 };
305 SparkMD5.prototype.end = function(raw) {
306 var buff = this._buff, length = buff.length, i, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], ret;
307 for (i = 0; i < length; i += 1) {
308 tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3);
309 }
310 this._finish(tail, length);
311 ret = hex(this._hash);
312 if (raw) {
313 ret = hexToBinaryString(ret);
314 }
315 this.reset();
316 return ret;
317 };
318 SparkMD5.prototype.reset = function() {
319 this._buff = "";
320 this._length = 0;
321 this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
322 return this;
323 };
324 SparkMD5.prototype.getState = function() {
325 return {
326 buff: this._buff,
327 length: this._length,
328 hash: this._hash.slice()
329 };
330 };
331 SparkMD5.prototype.setState = function(state) {
332 this._buff = state.buff;
333 this._length = state.length;
334 this._hash = state.hash;
335 return this;
336 };
337 SparkMD5.prototype.destroy = function() {
338 delete this._hash;
339 delete this._buff;
340 delete this._length;
341 };
342 SparkMD5.prototype._finish = function(tail, length) {
343 var i = length, tmp, lo, hi;
344 tail[i >> 2] |= 128 << (i % 4 << 3);
345 if (i > 55) {
346 md5cycle(this._hash, tail);
347 for (i = 0; i < 16; i += 1) {
348 tail[i] = 0;
349 }
350 }
351 tmp = this._length * 8;
352 tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
353 lo = parseInt(tmp[2], 16);
354 hi = parseInt(tmp[1], 16) || 0;
355 tail[14] = lo;
356 tail[15] = hi;
357 md5cycle(this._hash, tail);
358 };
359 SparkMD5.hash = function(str, raw) {
360 return SparkMD5.hashBinary(toUtf8(str), raw);
361 };
362 SparkMD5.hashBinary = function(content, raw) {
363 var hash = md51(content), ret = hex(hash);
364 return raw ? hexToBinaryString(ret) : ret;
365 };
366 SparkMD5.ArrayBuffer = function() {
367 this.reset();
368 };
369 SparkMD5.ArrayBuffer.prototype.append = function(arr) {
370 var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), length = buff.length, i;
371 this._length += arr.byteLength;
372 for (i = 64; i <= length; i += 64) {
373 md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)));
374 }
375 this._buff = i - 64 < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0);
376 return this;
377 };
378 SparkMD5.ArrayBuffer.prototype.end = function(raw) {
379 var buff = this._buff, length = buff.length, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], i, ret;
380 for (i = 0; i < length; i += 1) {
381 tail[i >> 2] |= buff[i] << (i % 4 << 3);
382 }
383 this._finish(tail, length);
384 ret = hex(this._hash);
385 if (raw) {
386 ret = hexToBinaryString(ret);
387 }
388 this.reset();
389 return ret;
390 };
391 SparkMD5.ArrayBuffer.prototype.reset = function() {
392 this._buff = new Uint8Array(0);
393 this._length = 0;
394 this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
395 return this;
396 };
397 SparkMD5.ArrayBuffer.prototype.getState = function() {
398 var state = SparkMD5.prototype.getState.call(this);
399 state.buff = arrayBuffer2Utf8Str(state.buff);
400 return state;
401 };
402 SparkMD5.ArrayBuffer.prototype.setState = function(state) {
403 state.buff = utf8Str2ArrayBuffer(state.buff, true);
404 return SparkMD5.prototype.setState.call(this, state);
405 };
406 SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
407 SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
408 SparkMD5.ArrayBuffer.hash = function(arr, raw) {
409 var hash = md51_array(new Uint8Array(arr)), ret = hex(hash);
410 return raw ? hexToBinaryString(ret) : ret;
411 };
412 return SparkMD5;
413 }));
414 })(sparkMd5);
415 var SparkMD5 = sparkMd5.exports;
416 const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
417 class FileChecksum {
418 static create(file, callback) {
419 const instance = new FileChecksum(file);
420 instance.create(callback);
421 }
422 constructor(file) {
423 this.file = file;
424 this.chunkSize = 2097152;
425 this.chunkCount = Math.ceil(this.file.size / this.chunkSize);
426 this.chunkIndex = 0;
427 }
428 create(callback) {
429 this.callback = callback;
430 this.md5Buffer = new SparkMD5.ArrayBuffer;
431 this.fileReader = new FileReader;
432 this.fileReader.addEventListener("load", (event => this.fileReaderDidLoad(event)));
433 this.fileReader.addEventListener("error", (event => this.fileReaderDidError(event)));
434 this.readNextChunk();
435 }
436 fileReaderDidLoad(event) {
437 this.md5Buffer.append(event.target.result);
438 if (!this.readNextChunk()) {
439 const binaryDigest = this.md5Buffer.end(true);
440 const base64digest = btoa(binaryDigest);
441 this.callback(null, base64digest);
442 }
443 }
444 fileReaderDidError(event) {
445 this.callback(`Error reading ${this.file.name}`);
446 }
447 readNextChunk() {
448 if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) {
449 const start = this.chunkIndex * this.chunkSize;
450 const end = Math.min(start + this.chunkSize, this.file.size);
451 const bytes = fileSlice.call(this.file, start, end);
452 this.fileReader.readAsArrayBuffer(bytes);
453 this.chunkIndex++;
454 return true;
455 } else {
456 return false;
457 }
458 }
459 }
460 function getMetaValue(name) {
461 const element = findElement(document.head, `meta[name="${name}"]`);
462 if (element) {
463 return element.getAttribute("content");
464 }
465 }
466 function findElements(root, selector) {
467 if (typeof root == "string") {
468 selector = root;
469 root = document;
470 }
471 const elements = root.querySelectorAll(selector);
472 return toArray(elements);
473 }
474 function findElement(root, selector) {
475 if (typeof root == "string") {
476 selector = root;
477 root = document;
478 }
479 return root.querySelector(selector);
480 }
481 function dispatchEvent(element, type, eventInit = {}) {
482 const {disabled: disabled} = element;
483 const {bubbles: bubbles, cancelable: cancelable, detail: detail} = eventInit;
484 const event = document.createEvent("Event");
485 event.initEvent(type, bubbles || true, cancelable || true);
486 event.detail = detail || {};
487 try {
488 element.disabled = false;
489 element.dispatchEvent(event);
490 } finally {
491 element.disabled = disabled;
492 }
493 return event;
494 }
495 function toArray(value) {
496 if (Array.isArray(value)) {
497 return value;
498 } else if (Array.from) {
499 return Array.from(value);
500 } else {
501 return [].slice.call(value);
502 }
503 }
504 class BlobRecord {
505 constructor(file, checksum, url, customHeaders = {}) {
506 this.file = file;
507 this.attributes = {
508 filename: file.name,
509 content_type: file.type || "application/octet-stream",
510 byte_size: file.size,
511 checksum: checksum
512 };
513 this.xhr = new XMLHttpRequest;
514 this.xhr.open("POST", url, true);
515 this.xhr.responseType = "json";
516 this.xhr.setRequestHeader("Content-Type", "application/json");
517 this.xhr.setRequestHeader("Accept", "application/json");
518 this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
519 Object.keys(customHeaders).forEach((headerKey => {
520 this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]);
521 }));
522 const csrfToken = getMetaValue("csrf-token");
523 if (csrfToken != undefined) {
524 this.xhr.setRequestHeader("X-CSRF-Token", csrfToken);
525 }
526 this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
527 this.xhr.addEventListener("error", (event => this.requestDidError(event)));
528 }
529 get status() {
530 return this.xhr.status;
531 }
532 get response() {
533 const {responseType: responseType, response: response} = this.xhr;
534 if (responseType == "json") {
535 return response;
536 } else {
537 return JSON.parse(response);
538 }
539 }
540 create(callback) {
541 this.callback = callback;
542 this.xhr.send(JSON.stringify({
543 blob: this.attributes
544 }));
545 }
546 requestDidLoad(event) {
547 if (this.status >= 200 && this.status < 300) {
548 const {response: response} = this;
549 const {direct_upload: direct_upload} = response;
550 delete response.direct_upload;
551 this.attributes = response;
552 this.directUploadData = direct_upload;
553 this.callback(null, this.toJSON());
554 } else {
555 this.requestDidError(event);
556 }
557 }
558 requestDidError(event) {
559 this.callback(`Error creating Blob for "${this.file.name}". Status: ${this.status}`);
560 }
561 toJSON() {
562 const result = {};
563 for (const key in this.attributes) {
564 result[key] = this.attributes[key];
565 }
566 return result;
567 }
568 }
569 class BlobUpload {
570 constructor(blob) {
571 this.blob = blob;
572 this.file = blob.file;
573 const {url: url, headers: headers} = blob.directUploadData;
574 this.xhr = new XMLHttpRequest;
575 this.xhr.open("PUT", url, true);
576 this.xhr.responseType = "text";
577 for (const key in headers) {
578 this.xhr.setRequestHeader(key, headers[key]);
579 }
580 this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
581 this.xhr.addEventListener("error", (event => this.requestDidError(event)));
582 }
583 create(callback) {
584 this.callback = callback;
585 this.xhr.send(this.file.slice());
586 }
587 requestDidLoad(event) {
588 const {status: status, response: response} = this.xhr;
589 if (status >= 200 && status < 300) {
590 this.callback(null, response);
591 } else {
592 this.requestDidError(event);
593 }
594 }
595 requestDidError(event) {
596 this.callback(`Error storing "${this.file.name}". Status: ${this.xhr.status}`);
597 }
598 }
599 let id = 0;
600 class DirectUpload {
601 constructor(file, url, delegate, customHeaders = {}) {
602 this.id = ++id;
603 this.file = file;
604 this.url = url;
605 this.delegate = delegate;
606 this.customHeaders = customHeaders;
607 }
608 create(callback) {
609 FileChecksum.create(this.file, ((error, checksum) => {
610 if (error) {
611 callback(error);
612 return;
613 }
614 const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders);
615 notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr);
616 blob.create((error => {
617 if (error) {
618 callback(error);
619 } else {
620 const upload = new BlobUpload(blob);
621 notify(this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr);
622 upload.create((error => {
623 if (error) {
624 callback(error);
625 } else {
626 callback(null, blob.toJSON());
627 }
628 }));
629 }
630 }));
631 }));
632 }
633 }
634 function notify(object, methodName, ...messages) {
635 if (object && typeof object[methodName] == "function") {
636 return object[methodName](...messages);
637 }
638 }
639 class DirectUploadController {
640 constructor(input, file) {
641 this.input = input;
642 this.file = file;
643 this.directUpload = new DirectUpload(this.file, this.url, this);
644 this.dispatch("initialize");
645 }
646 start(callback) {
647 const hiddenInput = document.createElement("input");
648 hiddenInput.type = "hidden";
649 hiddenInput.name = this.input.name;
650 this.input.insertAdjacentElement("beforebegin", hiddenInput);
651 this.dispatch("start");
652 this.directUpload.create(((error, attributes) => {
653 if (error) {
654 hiddenInput.parentNode.removeChild(hiddenInput);
655 this.dispatchError(error);
656 } else {
657 hiddenInput.value = attributes.signed_id;
658 }
659 this.dispatch("end");
660 callback(error);
661 }));
662 }
663 uploadRequestDidProgress(event) {
664 const progress = event.loaded / event.total * 100;
665 if (progress) {
666 this.dispatch("progress", {
667 progress: progress
668 });
669 }
670 }
671 get url() {
672 return this.input.getAttribute("data-direct-upload-url");
673 }
674 dispatch(name, detail = {}) {
675 detail.file = this.file;
676 detail.id = this.directUpload.id;
677 return dispatchEvent(this.input, `direct-upload:${name}`, {
678 detail: detail
679 });
680 }
681 dispatchError(error) {
682 const event = this.dispatch("error", {
683 error: error
684 });
685 if (!event.defaultPrevented) {
686 alert(error);
687 }
688 }
689 directUploadWillCreateBlobWithXHR(xhr) {
690 this.dispatch("before-blob-request", {
691 xhr: xhr
692 });
693 }
694 directUploadWillStoreFileWithXHR(xhr) {
695 this.dispatch("before-storage-request", {
696 xhr: xhr
697 });
698 xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event)));
699 }
700 }
701 const inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])";
702 class DirectUploadsController {
703 constructor(form) {
704 this.form = form;
705 this.inputs = findElements(form, inputSelector).filter((input => input.files.length));
706 }
707 start(callback) {
708 const controllers = this.createDirectUploadControllers();
709 const startNextController = () => {
710 const controller = controllers.shift();
711 if (controller) {
712 controller.start((error => {
713 if (error) {
714 callback(error);
715 this.dispatch("end");
716 } else {
717 startNextController();
718 }
719 }));
720 } else {
721 callback();
722 this.dispatch("end");
723 }
724 };
725 this.dispatch("start");
726 startNextController();
727 }
728 createDirectUploadControllers() {
729 const controllers = [];
730 this.inputs.forEach((input => {
731 toArray(input.files).forEach((file => {
732 const controller = new DirectUploadController(input, file);
733 controllers.push(controller);
734 }));
735 }));
736 return controllers;
737 }
738 dispatch(name, detail = {}) {
739 return dispatchEvent(this.form, `direct-uploads:${name}`, {
740 detail: detail
741 });
742 }
743 }
744 const processingAttribute = "data-direct-uploads-processing";
745 const submitButtonsByForm = new WeakMap;
746 let started = false;
747 function start() {
748 if (!started) {
749 started = true;
750 document.addEventListener("click", didClick, true);
751 document.addEventListener("submit", didSubmitForm, true);
752 document.addEventListener("ajax:before", didSubmitRemoteElement);
753 }
754 }
755 function didClick(event) {
756 const button = event.target.closest("button, input");
757 if (button && button.type === "submit" && button.form) {
758 submitButtonsByForm.set(button.form, button);
759 }
760 }
761 function didSubmitForm(event) {
762 handleFormSubmissionEvent(event);
763 }
764 function didSubmitRemoteElement(event) {
765 if (event.target.tagName == "FORM") {
766 handleFormSubmissionEvent(event);
767 }
768 }
769 function handleFormSubmissionEvent(event) {
770 const form = event.target;
771 if (form.hasAttribute(processingAttribute)) {
772 event.preventDefault();
773 return;
774 }
775 const controller = new DirectUploadsController(form);
776 const {inputs: inputs} = controller;
777 if (inputs.length) {
778 event.preventDefault();
779 form.setAttribute(processingAttribute, "");
780 inputs.forEach(disable);
781 controller.start((error => {
782 form.removeAttribute(processingAttribute);
783 if (error) {
784 inputs.forEach(enable);
785 } else {
786 submitForm(form);
787 }
788 }));
789 }
790 }
791 function submitForm(form) {
792 let button = submitButtonsByForm.get(form) || findElement(form, "input[type=submit], button[type=submit]");
793 if (button) {
794 const {disabled: disabled} = button;
795 button.disabled = false;
796 button.focus();
797 button.click();
798 button.disabled = disabled;
799 } else {
800 button = document.createElement("input");
801 button.type = "submit";
802 button.style.display = "none";
803 form.appendChild(button);
804 button.click();
805 form.removeChild(button);
806 }
807 submitButtonsByForm.delete(form);
808 }
809 function disable(input) {
810 input.disabled = true;
811 }
812 function enable(input) {
813 input.disabled = false;
814 }
815 function autostart() {
816 if (window.ActiveStorage) {
817 start();
818 }
819 }
820 setTimeout(autostart, 1);
821 class AttachmentUpload {
822 constructor(attachment, element) {
823 this.attachment = attachment;
824 this.element = element;
825 this.directUpload = new DirectUpload(attachment.file, this.directUploadUrl, this);
826 }
827 start() {
828 this.directUpload.create(this.directUploadDidComplete.bind(this));
829 }
830 directUploadWillStoreFileWithXHR(xhr) {
831 xhr.upload.addEventListener("progress", (event => {
832 const progress = event.loaded / event.total * 100;
833 this.attachment.setUploadProgress(progress);
834 }));
835 }
836 directUploadDidComplete(error, attributes) {
837 if (error) {
838 throw new Error(`Direct upload failed: ${error}`);
839 }
840 this.attachment.setAttributes({
841 sgid: attributes.attachable_sgid,
842 url: this.createBlobUrl(attributes.signed_id, attributes.filename)
843 });
844 }
845 createBlobUrl(signedId, filename) {
846 return this.blobUrlTemplate.replace(":signed_id", signedId).replace(":filename", encodeURIComponent(filename));
847 }
848 get directUploadUrl() {
849 return this.element.dataset.directUploadUrl;
850 }
851 get blobUrlTemplate() {
852 return this.element.dataset.blobUrlTemplate;
853 }
854 }
855 addEventListener("trix-attachment-add", (event => {
856 const {attachment: attachment, target: target} = event;
857 if (attachment.file) {
858 const upload = new AttachmentUpload(attachment, target);
859 upload.start();
860 }
861 }));
862}));
diff --git a/public/assets/actiontext-338257afa53cc53f94018abf7a897120d1eb3ee71f39e4641b2058442c9c4dc6.js.gz b/public/assets/actiontext-338257afa53cc53f94018abf7a897120d1eb3ee71f39e4641b2058442c9c4dc6.js.gz
new file mode 100644
index 0000000..5053ece
--- /dev/null
+++ b/public/assets/actiontext-338257afa53cc53f94018abf7a897120d1eb3ee71f39e4641b2058442c9c4dc6.js.gz
Binary files differ
diff --git a/public/assets/actiontext.esm-e787c6f528f0a88ee04de7c5ce4e3ab37fcf2691629ed21f0b30ee2db848c8c8.js b/public/assets/actiontext.esm-e787c6f528f0a88ee04de7c5ce4e3ab37fcf2691629ed21f0b30ee2db848c8c8.js
new file mode 100644
index 0000000..2f433b7
--- /dev/null
+++ b/public/assets/actiontext.esm-e787c6f528f0a88ee04de7c5ce4e3ab37fcf2691629ed21f0b30ee2db848c8c8.js
@@ -0,0 +1,889 @@
1var sparkMd5 = {
2 exports: {}
3};
4
5(function(module, exports) {
6 (function(factory) {
7 {
8 module.exports = factory();
9 }
10 })((function(undefined$1) {
11 var hex_chr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ];
12 function md5cycle(x, k) {
13 var a = x[0], b = x[1], c = x[2], d = x[3];
14 a += (b & c | ~b & d) + k[0] - 680876936 | 0;
15 a = (a << 7 | a >>> 25) + b | 0;
16 d += (a & b | ~a & c) + k[1] - 389564586 | 0;
17 d = (d << 12 | d >>> 20) + a | 0;
18 c += (d & a | ~d & b) + k[2] + 606105819 | 0;
19 c = (c << 17 | c >>> 15) + d | 0;
20 b += (c & d | ~c & a) + k[3] - 1044525330 | 0;
21 b = (b << 22 | b >>> 10) + c | 0;
22 a += (b & c | ~b & d) + k[4] - 176418897 | 0;
23 a = (a << 7 | a >>> 25) + b | 0;
24 d += (a & b | ~a & c) + k[5] + 1200080426 | 0;
25 d = (d << 12 | d >>> 20) + a | 0;
26 c += (d & a | ~d & b) + k[6] - 1473231341 | 0;
27 c = (c << 17 | c >>> 15) + d | 0;
28 b += (c & d | ~c & a) + k[7] - 45705983 | 0;
29 b = (b << 22 | b >>> 10) + c | 0;
30 a += (b & c | ~b & d) + k[8] + 1770035416 | 0;
31 a = (a << 7 | a >>> 25) + b | 0;
32 d += (a & b | ~a & c) + k[9] - 1958414417 | 0;
33 d = (d << 12 | d >>> 20) + a | 0;
34 c += (d & a | ~d & b) + k[10] - 42063 | 0;
35 c = (c << 17 | c >>> 15) + d | 0;
36 b += (c & d | ~c & a) + k[11] - 1990404162 | 0;
37 b = (b << 22 | b >>> 10) + c | 0;
38 a += (b & c | ~b & d) + k[12] + 1804603682 | 0;
39 a = (a << 7 | a >>> 25) + b | 0;
40 d += (a & b | ~a & c) + k[13] - 40341101 | 0;
41 d = (d << 12 | d >>> 20) + a | 0;
42 c += (d & a | ~d & b) + k[14] - 1502002290 | 0;
43 c = (c << 17 | c >>> 15) + d | 0;
44 b += (c & d | ~c & a) + k[15] + 1236535329 | 0;
45 b = (b << 22 | b >>> 10) + c | 0;
46 a += (b & d | c & ~d) + k[1] - 165796510 | 0;
47 a = (a << 5 | a >>> 27) + b | 0;
48 d += (a & c | b & ~c) + k[6] - 1069501632 | 0;
49 d = (d << 9 | d >>> 23) + a | 0;
50 c += (d & b | a & ~b) + k[11] + 643717713 | 0;
51 c = (c << 14 | c >>> 18) + d | 0;
52 b += (c & a | d & ~a) + k[0] - 373897302 | 0;
53 b = (b << 20 | b >>> 12) + c | 0;
54 a += (b & d | c & ~d) + k[5] - 701558691 | 0;
55 a = (a << 5 | a >>> 27) + b | 0;
56 d += (a & c | b & ~c) + k[10] + 38016083 | 0;
57 d = (d << 9 | d >>> 23) + a | 0;
58 c += (d & b | a & ~b) + k[15] - 660478335 | 0;
59 c = (c << 14 | c >>> 18) + d | 0;
60 b += (c & a | d & ~a) + k[4] - 405537848 | 0;
61 b = (b << 20 | b >>> 12) + c | 0;
62 a += (b & d | c & ~d) + k[9] + 568446438 | 0;
63 a = (a << 5 | a >>> 27) + b | 0;
64 d += (a & c | b & ~c) + k[14] - 1019803690 | 0;
65 d = (d << 9 | d >>> 23) + a | 0;
66 c += (d & b | a & ~b) + k[3] - 187363961 | 0;
67 c = (c << 14 | c >>> 18) + d | 0;
68 b += (c & a | d & ~a) + k[8] + 1163531501 | 0;
69 b = (b << 20 | b >>> 12) + c | 0;
70 a += (b & d | c & ~d) + k[13] - 1444681467 | 0;
71 a = (a << 5 | a >>> 27) + b | 0;
72 d += (a & c | b & ~c) + k[2] - 51403784 | 0;
73 d = (d << 9 | d >>> 23) + a | 0;
74 c += (d & b | a & ~b) + k[7] + 1735328473 | 0;
75 c = (c << 14 | c >>> 18) + d | 0;
76 b += (c & a | d & ~a) + k[12] - 1926607734 | 0;
77 b = (b << 20 | b >>> 12) + c | 0;
78 a += (b ^ c ^ d) + k[5] - 378558 | 0;
79 a = (a << 4 | a >>> 28) + b | 0;
80 d += (a ^ b ^ c) + k[8] - 2022574463 | 0;
81 d = (d << 11 | d >>> 21) + a | 0;
82 c += (d ^ a ^ b) + k[11] + 1839030562 | 0;
83 c = (c << 16 | c >>> 16) + d | 0;
84 b += (c ^ d ^ a) + k[14] - 35309556 | 0;
85 b = (b << 23 | b >>> 9) + c | 0;
86 a += (b ^ c ^ d) + k[1] - 1530992060 | 0;
87 a = (a << 4 | a >>> 28) + b | 0;
88 d += (a ^ b ^ c) + k[4] + 1272893353 | 0;
89 d = (d << 11 | d >>> 21) + a | 0;
90 c += (d ^ a ^ b) + k[7] - 155497632 | 0;
91 c = (c << 16 | c >>> 16) + d | 0;
92 b += (c ^ d ^ a) + k[10] - 1094730640 | 0;
93 b = (b << 23 | b >>> 9) + c | 0;
94 a += (b ^ c ^ d) + k[13] + 681279174 | 0;
95 a = (a << 4 | a >>> 28) + b | 0;
96 d += (a ^ b ^ c) + k[0] - 358537222 | 0;
97 d = (d << 11 | d >>> 21) + a | 0;
98 c += (d ^ a ^ b) + k[3] - 722521979 | 0;
99 c = (c << 16 | c >>> 16) + d | 0;
100 b += (c ^ d ^ a) + k[6] + 76029189 | 0;
101 b = (b << 23 | b >>> 9) + c | 0;
102 a += (b ^ c ^ d) + k[9] - 640364487 | 0;
103 a = (a << 4 | a >>> 28) + b | 0;
104 d += (a ^ b ^ c) + k[12] - 421815835 | 0;
105 d = (d << 11 | d >>> 21) + a | 0;
106 c += (d ^ a ^ b) + k[15] + 530742520 | 0;
107 c = (c << 16 | c >>> 16) + d | 0;
108 b += (c ^ d ^ a) + k[2] - 995338651 | 0;
109 b = (b << 23 | b >>> 9) + c | 0;
110 a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;
111 a = (a << 6 | a >>> 26) + b | 0;
112 d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;
113 d = (d << 10 | d >>> 22) + a | 0;
114 c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;
115 c = (c << 15 | c >>> 17) + d | 0;
116 b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;
117 b = (b << 21 | b >>> 11) + c | 0;
118 a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;
119 a = (a << 6 | a >>> 26) + b | 0;
120 d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;
121 d = (d << 10 | d >>> 22) + a | 0;
122 c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;
123 c = (c << 15 | c >>> 17) + d | 0;
124 b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;
125 b = (b << 21 | b >>> 11) + c | 0;
126 a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;
127 a = (a << 6 | a >>> 26) + b | 0;
128 d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;
129 d = (d << 10 | d >>> 22) + a | 0;
130 c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;
131 c = (c << 15 | c >>> 17) + d | 0;
132 b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;
133 b = (b << 21 | b >>> 11) + c | 0;
134 a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;
135 a = (a << 6 | a >>> 26) + b | 0;
136 d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;
137 d = (d << 10 | d >>> 22) + a | 0;
138 c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;
139 c = (c << 15 | c >>> 17) + d | 0;
140 b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;
141 b = (b << 21 | b >>> 11) + c | 0;
142 x[0] = a + x[0] | 0;
143 x[1] = b + x[1] | 0;
144 x[2] = c + x[2] | 0;
145 x[3] = d + x[3] | 0;
146 }
147 function md5blk(s) {
148 var md5blks = [], i;
149 for (i = 0; i < 64; i += 4) {
150 md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
151 }
152 return md5blks;
153 }
154 function md5blk_array(a) {
155 var md5blks = [], i;
156 for (i = 0; i < 64; i += 4) {
157 md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
158 }
159 return md5blks;
160 }
161 function md51(s) {
162 var n = s.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
163 for (i = 64; i <= n; i += 64) {
164 md5cycle(state, md5blk(s.substring(i - 64, i)));
165 }
166 s = s.substring(i - 64);
167 length = s.length;
168 tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
169 for (i = 0; i < length; i += 1) {
170 tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);
171 }
172 tail[i >> 2] |= 128 << (i % 4 << 3);
173 if (i > 55) {
174 md5cycle(state, tail);
175 for (i = 0; i < 16; i += 1) {
176 tail[i] = 0;
177 }
178 }
179 tmp = n * 8;
180 tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
181 lo = parseInt(tmp[2], 16);
182 hi = parseInt(tmp[1], 16) || 0;
183 tail[14] = lo;
184 tail[15] = hi;
185 md5cycle(state, tail);
186 return state;
187 }
188 function md51_array(a) {
189 var n = a.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
190 for (i = 64; i <= n; i += 64) {
191 md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
192 }
193 a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0);
194 length = a.length;
195 tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
196 for (i = 0; i < length; i += 1) {
197 tail[i >> 2] |= a[i] << (i % 4 << 3);
198 }
199 tail[i >> 2] |= 128 << (i % 4 << 3);
200 if (i > 55) {
201 md5cycle(state, tail);
202 for (i = 0; i < 16; i += 1) {
203 tail[i] = 0;
204 }
205 }
206 tmp = n * 8;
207 tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
208 lo = parseInt(tmp[2], 16);
209 hi = parseInt(tmp[1], 16) || 0;
210 tail[14] = lo;
211 tail[15] = hi;
212 md5cycle(state, tail);
213 return state;
214 }
215 function rhex(n) {
216 var s = "", j;
217 for (j = 0; j < 4; j += 1) {
218 s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15];
219 }
220 return s;
221 }
222 function hex(x) {
223 var i;
224 for (i = 0; i < x.length; i += 1) {
225 x[i] = rhex(x[i]);
226 }
227 return x.join("");
228 }
229 if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ;
230 if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) {
231 (function() {
232 function clamp(val, length) {
233 val = val | 0 || 0;
234 if (val < 0) {
235 return Math.max(val + length, 0);
236 }
237 return Math.min(val, length);
238 }
239 ArrayBuffer.prototype.slice = function(from, to) {
240 var length = this.byteLength, begin = clamp(from, length), end = length, num, target, targetArray, sourceArray;
241 if (to !== undefined$1) {
242 end = clamp(to, length);
243 }
244 if (begin > end) {
245 return new ArrayBuffer(0);
246 }
247 num = end - begin;
248 target = new ArrayBuffer(num);
249 targetArray = new Uint8Array(target);
250 sourceArray = new Uint8Array(this, begin, num);
251 targetArray.set(sourceArray);
252 return target;
253 };
254 })();
255 }
256 function toUtf8(str) {
257 if (/[\u0080-\uFFFF]/.test(str)) {
258 str = unescape(encodeURIComponent(str));
259 }
260 return str;
261 }
262 function utf8Str2ArrayBuffer(str, returnUInt8Array) {
263 var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i;
264 for (i = 0; i < length; i += 1) {
265 arr[i] = str.charCodeAt(i);
266 }
267 return returnUInt8Array ? arr : buff;
268 }
269 function arrayBuffer2Utf8Str(buff) {
270 return String.fromCharCode.apply(null, new Uint8Array(buff));
271 }
272 function concatenateArrayBuffers(first, second, returnUInt8Array) {
273 var result = new Uint8Array(first.byteLength + second.byteLength);
274 result.set(new Uint8Array(first));
275 result.set(new Uint8Array(second), first.byteLength);
276 return returnUInt8Array ? result : result.buffer;
277 }
278 function hexToBinaryString(hex) {
279 var bytes = [], length = hex.length, x;
280 for (x = 0; x < length - 1; x += 2) {
281 bytes.push(parseInt(hex.substr(x, 2), 16));
282 }
283 return String.fromCharCode.apply(String, bytes);
284 }
285 function SparkMD5() {
286 this.reset();
287 }
288 SparkMD5.prototype.append = function(str) {
289 this.appendBinary(toUtf8(str));
290 return this;
291 };
292 SparkMD5.prototype.appendBinary = function(contents) {
293 this._buff += contents;
294 this._length += contents.length;
295 var length = this._buff.length, i;
296 for (i = 64; i <= length; i += 64) {
297 md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)));
298 }
299 this._buff = this._buff.substring(i - 64);
300 return this;
301 };
302 SparkMD5.prototype.end = function(raw) {
303 var buff = this._buff, length = buff.length, i, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], ret;
304 for (i = 0; i < length; i += 1) {
305 tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3);
306 }
307 this._finish(tail, length);
308 ret = hex(this._hash);
309 if (raw) {
310 ret = hexToBinaryString(ret);
311 }
312 this.reset();
313 return ret;
314 };
315 SparkMD5.prototype.reset = function() {
316 this._buff = "";
317 this._length = 0;
318 this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
319 return this;
320 };
321 SparkMD5.prototype.getState = function() {
322 return {
323 buff: this._buff,
324 length: this._length,
325 hash: this._hash.slice()
326 };
327 };
328 SparkMD5.prototype.setState = function(state) {
329 this._buff = state.buff;
330 this._length = state.length;
331 this._hash = state.hash;
332 return this;
333 };
334 SparkMD5.prototype.destroy = function() {
335 delete this._hash;
336 delete this._buff;
337 delete this._length;
338 };
339 SparkMD5.prototype._finish = function(tail, length) {
340 var i = length, tmp, lo, hi;
341 tail[i >> 2] |= 128 << (i % 4 << 3);
342 if (i > 55) {
343 md5cycle(this._hash, tail);
344 for (i = 0; i < 16; i += 1) {
345 tail[i] = 0;
346 }
347 }
348 tmp = this._length * 8;
349 tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
350 lo = parseInt(tmp[2], 16);
351 hi = parseInt(tmp[1], 16) || 0;
352 tail[14] = lo;
353 tail[15] = hi;
354 md5cycle(this._hash, tail);
355 };
356 SparkMD5.hash = function(str, raw) {
357 return SparkMD5.hashBinary(toUtf8(str), raw);
358 };
359 SparkMD5.hashBinary = function(content, raw) {
360 var hash = md51(content), ret = hex(hash);
361 return raw ? hexToBinaryString(ret) : ret;
362 };
363 SparkMD5.ArrayBuffer = function() {
364 this.reset();
365 };
366 SparkMD5.ArrayBuffer.prototype.append = function(arr) {
367 var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), length = buff.length, i;
368 this._length += arr.byteLength;
369 for (i = 64; i <= length; i += 64) {
370 md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)));
371 }
372 this._buff = i - 64 < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0);
373 return this;
374 };
375 SparkMD5.ArrayBuffer.prototype.end = function(raw) {
376 var buff = this._buff, length = buff.length, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], i, ret;
377 for (i = 0; i < length; i += 1) {
378 tail[i >> 2] |= buff[i] << (i % 4 << 3);
379 }
380 this._finish(tail, length);
381 ret = hex(this._hash);
382 if (raw) {
383 ret = hexToBinaryString(ret);
384 }
385 this.reset();
386 return ret;
387 };
388 SparkMD5.ArrayBuffer.prototype.reset = function() {
389 this._buff = new Uint8Array(0);
390 this._length = 0;
391 this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
392 return this;
393 };
394 SparkMD5.ArrayBuffer.prototype.getState = function() {
395 var state = SparkMD5.prototype.getState.call(this);
396 state.buff = arrayBuffer2Utf8Str(state.buff);
397 return state;
398 };
399 SparkMD5.ArrayBuffer.prototype.setState = function(state) {
400 state.buff = utf8Str2ArrayBuffer(state.buff, true);
401 return SparkMD5.prototype.setState.call(this, state);
402 };
403 SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
404 SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
405 SparkMD5.ArrayBuffer.hash = function(arr, raw) {
406 var hash = md51_array(new Uint8Array(arr)), ret = hex(hash);
407 return raw ? hexToBinaryString(ret) : ret;
408 };
409 return SparkMD5;
410 }));
411})(sparkMd5);
412
413var SparkMD5 = sparkMd5.exports;
414
415const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
416
417class FileChecksum {
418 static create(file, callback) {
419 const instance = new FileChecksum(file);
420 instance.create(callback);
421 }
422 constructor(file) {
423 this.file = file;
424 this.chunkSize = 2097152;
425 this.chunkCount = Math.ceil(this.file.size / this.chunkSize);
426 this.chunkIndex = 0;
427 }
428 create(callback) {
429 this.callback = callback;
430 this.md5Buffer = new SparkMD5.ArrayBuffer;
431 this.fileReader = new FileReader;
432 this.fileReader.addEventListener("load", (event => this.fileReaderDidLoad(event)));
433 this.fileReader.addEventListener("error", (event => this.fileReaderDidError(event)));
434 this.readNextChunk();
435 }
436 fileReaderDidLoad(event) {
437 this.md5Buffer.append(event.target.result);
438 if (!this.readNextChunk()) {
439 const binaryDigest = this.md5Buffer.end(true);
440 const base64digest = btoa(binaryDigest);
441 this.callback(null, base64digest);
442 }
443 }
444 fileReaderDidError(event) {
445 this.callback(`Error reading ${this.file.name}`);
446 }
447 readNextChunk() {
448 if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) {
449 const start = this.chunkIndex * this.chunkSize;
450 const end = Math.min(start + this.chunkSize, this.file.size);
451 const bytes = fileSlice.call(this.file, start, end);
452 this.fileReader.readAsArrayBuffer(bytes);
453 this.chunkIndex++;
454 return true;
455 } else {
456 return false;
457 }
458 }
459}
460
461function getMetaValue(name) {
462 const element = findElement(document.head, `meta[name="${name}"]`);
463 if (element) {
464 return element.getAttribute("content");
465 }
466}
467
468function findElements(root, selector) {
469 if (typeof root == "string") {
470 selector = root;
471 root = document;
472 }
473 const elements = root.querySelectorAll(selector);
474 return toArray(elements);
475}
476
477function findElement(root, selector) {
478 if (typeof root == "string") {
479 selector = root;
480 root = document;
481 }
482 return root.querySelector(selector);
483}
484
485function dispatchEvent(element, type, eventInit = {}) {
486 const {disabled: disabled} = element;
487 const {bubbles: bubbles, cancelable: cancelable, detail: detail} = eventInit;
488 const event = document.createEvent("Event");
489 event.initEvent(type, bubbles || true, cancelable || true);
490 event.detail = detail || {};
491 try {
492 element.disabled = false;
493 element.dispatchEvent(event);
494 } finally {
495 element.disabled = disabled;
496 }
497 return event;
498}
499
500function toArray(value) {
501 if (Array.isArray(value)) {
502 return value;
503 } else if (Array.from) {
504 return Array.from(value);
505 } else {
506 return [].slice.call(value);
507 }
508}
509
510class BlobRecord {
511 constructor(file, checksum, url, customHeaders = {}) {
512 this.file = file;
513 this.attributes = {
514 filename: file.name,
515 content_type: file.type || "application/octet-stream",
516 byte_size: file.size,
517 checksum: checksum
518 };
519 this.xhr = new XMLHttpRequest;
520 this.xhr.open("POST", url, true);
521 this.xhr.responseType = "json";
522 this.xhr.setRequestHeader("Content-Type", "application/json");
523 this.xhr.setRequestHeader("Accept", "application/json");
524 this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
525 Object.keys(customHeaders).forEach((headerKey => {
526 this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]);
527 }));
528 const csrfToken = getMetaValue("csrf-token");
529 if (csrfToken != undefined) {
530 this.xhr.setRequestHeader("X-CSRF-Token", csrfToken);
531 }
532 this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
533 this.xhr.addEventListener("error", (event => this.requestDidError(event)));
534 }
535 get status() {
536 return this.xhr.status;
537 }
538 get response() {
539 const {responseType: responseType, response: response} = this.xhr;
540 if (responseType == "json") {
541 return response;
542 } else {
543 return JSON.parse(response);
544 }
545 }
546 create(callback) {
547 this.callback = callback;
548 this.xhr.send(JSON.stringify({
549 blob: this.attributes
550 }));
551 }
552 requestDidLoad(event) {
553 if (this.status >= 200 && this.status < 300) {
554 const {response: response} = this;
555 const {direct_upload: direct_upload} = response;
556 delete response.direct_upload;
557 this.attributes = response;
558 this.directUploadData = direct_upload;
559 this.callback(null, this.toJSON());
560 } else {
561 this.requestDidError(event);
562 }
563 }
564 requestDidError(event) {
565 this.callback(`Error creating Blob for "${this.file.name}". Status: ${this.status}`);
566 }
567 toJSON() {
568 const result = {};
569 for (const key in this.attributes) {
570 result[key] = this.attributes[key];
571 }
572 return result;
573 }
574}
575
576class BlobUpload {
577 constructor(blob) {
578 this.blob = blob;
579 this.file = blob.file;
580 const {url: url, headers: headers} = blob.directUploadData;
581 this.xhr = new XMLHttpRequest;
582 this.xhr.open("PUT", url, true);
583 this.xhr.responseType = "text";
584 for (const key in headers) {
585 this.xhr.setRequestHeader(key, headers[key]);
586 }
587 this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
588 this.xhr.addEventListener("error", (event => this.requestDidError(event)));
589 }
590 create(callback) {
591 this.callback = callback;
592 this.xhr.send(this.file.slice());
593 }
594 requestDidLoad(event) {
595 const {status: status, response: response} = this.xhr;
596 if (status >= 200 && status < 300) {
597 this.callback(null, response);
598 } else {
599 this.requestDidError(event);
600 }
601 }
602 requestDidError(event) {
603 this.callback(`Error storing "${this.file.name}". Status: ${this.xhr.status}`);
604 }
605}
606
607let id = 0;
608
609class DirectUpload {
610 constructor(file, url, delegate, customHeaders = {}) {
611 this.id = ++id;
612 this.file = file;
613 this.url = url;
614 this.delegate = delegate;
615 this.customHeaders = customHeaders;
616 }
617 create(callback) {
618 FileChecksum.create(this.file, ((error, checksum) => {
619 if (error) {
620 callback(error);
621 return;
622 }
623 const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders);
624 notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr);
625 blob.create((error => {
626 if (error) {
627 callback(error);
628 } else {
629 const upload = new BlobUpload(blob);
630 notify(this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr);
631 upload.create((error => {
632 if (error) {
633 callback(error);
634 } else {
635 callback(null, blob.toJSON());
636 }
637 }));
638 }
639 }));
640 }));
641 }
642}
643
644function notify(object, methodName, ...messages) {
645 if (object && typeof object[methodName] == "function") {
646 return object[methodName](...messages);
647 }
648}
649
650class DirectUploadController {
651 constructor(input, file) {
652 this.input = input;
653 this.file = file;
654 this.directUpload = new DirectUpload(this.file, this.url, this);
655 this.dispatch("initialize");
656 }
657 start(callback) {
658 const hiddenInput = document.createElement("input");
659 hiddenInput.type = "hidden";
660 hiddenInput.name = this.input.name;
661 this.input.insertAdjacentElement("beforebegin", hiddenInput);
662 this.dispatch("start");
663 this.directUpload.create(((error, attributes) => {
664 if (error) {
665 hiddenInput.parentNode.removeChild(hiddenInput);
666 this.dispatchError(error);
667 } else {
668 hiddenInput.value = attributes.signed_id;
669 }
670 this.dispatch("end");
671 callback(error);
672 }));
673 }
674 uploadRequestDidProgress(event) {
675 const progress = event.loaded / event.total * 100;
676 if (progress) {
677 this.dispatch("progress", {
678 progress: progress
679 });
680 }
681 }
682 get url() {
683 return this.input.getAttribute("data-direct-upload-url");
684 }
685 dispatch(name, detail = {}) {
686 detail.file = this.file;
687 detail.id = this.directUpload.id;
688 return dispatchEvent(this.input, `direct-upload:${name}`, {
689 detail: detail
690 });
691 }
692 dispatchError(error) {
693 const event = this.dispatch("error", {
694 error: error
695 });
696 if (!event.defaultPrevented) {
697 alert(error);
698 }
699 }
700 directUploadWillCreateBlobWithXHR(xhr) {
701 this.dispatch("before-blob-request", {
702 xhr: xhr
703 });
704 }
705 directUploadWillStoreFileWithXHR(xhr) {
706 this.dispatch("before-storage-request", {
707 xhr: xhr
708 });
709 xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event)));
710 }
711}
712
713const inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])";
714
715class DirectUploadsController {
716 constructor(form) {
717 this.form = form;
718 this.inputs = findElements(form, inputSelector).filter((input => input.files.length));
719 }
720 start(callback) {
721 const controllers = this.createDirectUploadControllers();
722 const startNextController = () => {
723 const controller = controllers.shift();
724 if (controller) {
725 controller.start((error => {
726 if (error) {
727 callback(error);
728 this.dispatch("end");
729 } else {
730 startNextController();
731 }
732 }));
733 } else {
734 callback();
735 this.dispatch("end");
736 }
737 };
738 this.dispatch("start");
739 startNextController();
740 }
741 createDirectUploadControllers() {
742 const controllers = [];
743 this.inputs.forEach((input => {
744 toArray(input.files).forEach((file => {
745 const controller = new DirectUploadController(input, file);
746 controllers.push(controller);
747 }));
748 }));
749 return controllers;
750 }
751 dispatch(name, detail = {}) {
752 return dispatchEvent(this.form, `direct-uploads:${name}`, {
753 detail: detail
754 });
755 }
756}
757
758const processingAttribute = "data-direct-uploads-processing";
759
760const submitButtonsByForm = new WeakMap;
761
762let started = false;
763
764function start() {
765 if (!started) {
766 started = true;
767 document.addEventListener("click", didClick, true);
768 document.addEventListener("submit", didSubmitForm, true);
769 document.addEventListener("ajax:before", didSubmitRemoteElement);
770 }
771}
772
773function didClick(event) {
774 const button = event.target.closest("button, input");
775 if (button && button.type === "submit" && button.form) {
776 submitButtonsByForm.set(button.form, button);
777 }
778}
779
780function didSubmitForm(event) {
781 handleFormSubmissionEvent(event);
782}
783
784function didSubmitRemoteElement(event) {
785 if (event.target.tagName == "FORM") {
786 handleFormSubmissionEvent(event);
787 }
788}
789
790function handleFormSubmissionEvent(event) {
791 const form = event.target;
792 if (form.hasAttribute(processingAttribute)) {
793 event.preventDefault();
794 return;
795 }
796 const controller = new DirectUploadsController(form);
797 const {inputs: inputs} = controller;
798 if (inputs.length) {
799 event.preventDefault();
800 form.setAttribute(processingAttribute, "");
801 inputs.forEach(disable);
802 controller.start((error => {
803 form.removeAttribute(processingAttribute);
804 if (error) {
805 inputs.forEach(enable);
806 } else {
807 submitForm(form);
808 }
809 }));
810 }
811}
812
813function submitForm(form) {
814 let button = submitButtonsByForm.get(form) || findElement(form, "input[type=submit], button[type=submit]");
815 if (button) {
816 const {disabled: disabled} = button;
817 button.disabled = false;
818 button.focus();
819 button.click();
820 button.disabled = disabled;
821 } else {
822 button = document.createElement("input");
823 button.type = "submit";
824 button.style.display = "none";
825 form.appendChild(button);
826 button.click();
827 form.removeChild(button);
828 }
829 submitButtonsByForm.delete(form);
830}
831
832function disable(input) {
833 input.disabled = true;
834}
835
836function enable(input) {
837 input.disabled = false;
838}
839
840function autostart() {
841 if (window.ActiveStorage) {
842 start();
843 }
844}
845
846setTimeout(autostart, 1);
847
848class AttachmentUpload {
849 constructor(attachment, element) {
850 this.attachment = attachment;
851 this.element = element;
852 this.directUpload = new DirectUpload(attachment.file, this.directUploadUrl, this);
853 }
854 start() {
855 this.directUpload.create(this.directUploadDidComplete.bind(this));
856 }
857 directUploadWillStoreFileWithXHR(xhr) {
858 xhr.upload.addEventListener("progress", (event => {
859 const progress = event.loaded / event.total * 100;
860 this.attachment.setUploadProgress(progress);
861 }));
862 }
863 directUploadDidComplete(error, attributes) {
864 if (error) {
865 throw new Error(`Direct upload failed: ${error}`);
866 }
867 this.attachment.setAttributes({
868 sgid: attributes.attachable_sgid,
869 url: this.createBlobUrl(attributes.signed_id, attributes.filename)
870 });
871 }
872 createBlobUrl(signedId, filename) {
873 return this.blobUrlTemplate.replace(":signed_id", signedId).replace(":filename", encodeURIComponent(filename));
874 }
875 get directUploadUrl() {
876 return this.element.dataset.directUploadUrl;
877 }
878 get blobUrlTemplate() {
879 return this.element.dataset.blobUrlTemplate;
880 }
881}
882
883addEventListener("trix-attachment-add", (event => {
884 const {attachment: attachment, target: target} = event;
885 if (attachment.file) {
886 const upload = new AttachmentUpload(attachment, target);
887 upload.start();
888 }
889}));
diff --git a/public/assets/actiontext.esm-e787c6f528f0a88ee04de7c5ce4e3ab37fcf2691629ed21f0b30ee2db848c8c8.js.gz b/public/assets/actiontext.esm-e787c6f528f0a88ee04de7c5ce4e3ab37fcf2691629ed21f0b30ee2db848c8c8.js.gz
new file mode 100644
index 0000000..be00605
--- /dev/null
+++ b/public/assets/actiontext.esm-e787c6f528f0a88ee04de7c5ce4e3ab37fcf2691629ed21f0b30ee2db848c8c8.js.gz
Binary files differ
diff --git a/public/assets/activestorage-7dbadea816242c6d03cc2f59c58398ab55bb9a70ee859fa962ad4c7ad4c48594.js b/public/assets/activestorage-7dbadea816242c6d03cc2f59c58398ab55bb9a70ee859fa962ad4c7ad4c48594.js
new file mode 100644
index 0000000..a31bf08
--- /dev/null
+++ b/public/assets/activestorage-7dbadea816242c6d03cc2f59c58398ab55bb9a70ee859fa962ad4c7ad4c48594.js
@@ -0,0 +1,829 @@
1(function(global, factory) {
2 typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define([ "exports" ], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self,
3 factory(global.ActiveStorage = {}));
4})(this, (function(exports) {
5 "use strict";
6 var sparkMd5 = {
7 exports: {}
8 };
9 (function(module, exports) {
10 (function(factory) {
11 {
12 module.exports = factory();
13 }
14 })((function(undefined$1) {
15 var hex_chr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ];
16 function md5cycle(x, k) {
17 var a = x[0], b = x[1], c = x[2], d = x[3];
18 a += (b & c | ~b & d) + k[0] - 680876936 | 0;
19 a = (a << 7 | a >>> 25) + b | 0;
20 d += (a & b | ~a & c) + k[1] - 389564586 | 0;
21 d = (d << 12 | d >>> 20) + a | 0;
22 c += (d & a | ~d & b) + k[2] + 606105819 | 0;
23 c = (c << 17 | c >>> 15) + d | 0;
24 b += (c & d | ~c & a) + k[3] - 1044525330 | 0;
25 b = (b << 22 | b >>> 10) + c | 0;
26 a += (b & c | ~b & d) + k[4] - 176418897 | 0;
27 a = (a << 7 | a >>> 25) + b | 0;
28 d += (a & b | ~a & c) + k[5] + 1200080426 | 0;
29 d = (d << 12 | d >>> 20) + a | 0;
30 c += (d & a | ~d & b) + k[6] - 1473231341 | 0;
31 c = (c << 17 | c >>> 15) + d | 0;
32 b += (c & d | ~c & a) + k[7] - 45705983 | 0;
33 b = (b << 22 | b >>> 10) + c | 0;
34 a += (b & c | ~b & d) + k[8] + 1770035416 | 0;
35 a = (a << 7 | a >>> 25) + b | 0;
36 d += (a & b | ~a & c) + k[9] - 1958414417 | 0;
37 d = (d << 12 | d >>> 20) + a | 0;
38 c += (d & a | ~d & b) + k[10] - 42063 | 0;
39 c = (c << 17 | c >>> 15) + d | 0;
40 b += (c & d | ~c & a) + k[11] - 1990404162 | 0;
41 b = (b << 22 | b >>> 10) + c | 0;
42 a += (b & c | ~b & d) + k[12] + 1804603682 | 0;
43 a = (a << 7 | a >>> 25) + b | 0;
44 d += (a & b | ~a & c) + k[13] - 40341101 | 0;
45 d = (d << 12 | d >>> 20) + a | 0;
46 c += (d & a | ~d & b) + k[14] - 1502002290 | 0;
47 c = (c << 17 | c >>> 15) + d | 0;
48 b += (c & d | ~c & a) + k[15] + 1236535329 | 0;
49 b = (b << 22 | b >>> 10) + c | 0;
50 a += (b & d | c & ~d) + k[1] - 165796510 | 0;
51 a = (a << 5 | a >>> 27) + b | 0;
52 d += (a & c | b & ~c) + k[6] - 1069501632 | 0;
53 d = (d << 9 | d >>> 23) + a | 0;
54 c += (d & b | a & ~b) + k[11] + 643717713 | 0;
55 c = (c << 14 | c >>> 18) + d | 0;
56 b += (c & a | d & ~a) + k[0] - 373897302 | 0;
57 b = (b << 20 | b >>> 12) + c | 0;
58 a += (b & d | c & ~d) + k[5] - 701558691 | 0;
59 a = (a << 5 | a >>> 27) + b | 0;
60 d += (a & c | b & ~c) + k[10] + 38016083 | 0;
61 d = (d << 9 | d >>> 23) + a | 0;
62 c += (d & b | a & ~b) + k[15] - 660478335 | 0;
63 c = (c << 14 | c >>> 18) + d | 0;
64 b += (c & a | d & ~a) + k[4] - 405537848 | 0;
65 b = (b << 20 | b >>> 12) + c | 0;
66 a += (b & d | c & ~d) + k[9] + 568446438 | 0;
67 a = (a << 5 | a >>> 27) + b | 0;
68 d += (a & c | b & ~c) + k[14] - 1019803690 | 0;
69 d = (d << 9 | d >>> 23) + a | 0;
70 c += (d & b | a & ~b) + k[3] - 187363961 | 0;
71 c = (c << 14 | c >>> 18) + d | 0;
72 b += (c & a | d & ~a) + k[8] + 1163531501 | 0;
73 b = (b << 20 | b >>> 12) + c | 0;
74 a += (b & d | c & ~d) + k[13] - 1444681467 | 0;
75 a = (a << 5 | a >>> 27) + b | 0;
76 d += (a & c | b & ~c) + k[2] - 51403784 | 0;
77 d = (d << 9 | d >>> 23) + a | 0;
78 c += (d & b | a & ~b) + k[7] + 1735328473 | 0;
79 c = (c << 14 | c >>> 18) + d | 0;
80 b += (c & a | d & ~a) + k[12] - 1926607734 | 0;
81 b = (b << 20 | b >>> 12) + c | 0;
82 a += (b ^ c ^ d) + k[5] - 378558 | 0;
83 a = (a << 4 | a >>> 28) + b | 0;
84 d += (a ^ b ^ c) + k[8] - 2022574463 | 0;
85 d = (d << 11 | d >>> 21) + a | 0;
86 c += (d ^ a ^ b) + k[11] + 1839030562 | 0;
87 c = (c << 16 | c >>> 16) + d | 0;
88 b += (c ^ d ^ a) + k[14] - 35309556 | 0;
89 b = (b << 23 | b >>> 9) + c | 0;
90 a += (b ^ c ^ d) + k[1] - 1530992060 | 0;
91 a = (a << 4 | a >>> 28) + b | 0;
92 d += (a ^ b ^ c) + k[4] + 1272893353 | 0;
93 d = (d << 11 | d >>> 21) + a | 0;
94 c += (d ^ a ^ b) + k[7] - 155497632 | 0;
95 c = (c << 16 | c >>> 16) + d | 0;
96 b += (c ^ d ^ a) + k[10] - 1094730640 | 0;
97 b = (b << 23 | b >>> 9) + c | 0;
98 a += (b ^ c ^ d) + k[13] + 681279174 | 0;
99 a = (a << 4 | a >>> 28) + b | 0;
100 d += (a ^ b ^ c) + k[0] - 358537222 | 0;
101 d = (d << 11 | d >>> 21) + a | 0;
102 c += (d ^ a ^ b) + k[3] - 722521979 | 0;
103 c = (c << 16 | c >>> 16) + d | 0;
104 b += (c ^ d ^ a) + k[6] + 76029189 | 0;
105 b = (b << 23 | b >>> 9) + c | 0;
106 a += (b ^ c ^ d) + k[9] - 640364487 | 0;
107 a = (a << 4 | a >>> 28) + b | 0;
108 d += (a ^ b ^ c) + k[12] - 421815835 | 0;
109 d = (d << 11 | d >>> 21) + a | 0;
110 c += (d ^ a ^ b) + k[15] + 530742520 | 0;
111 c = (c << 16 | c >>> 16) + d | 0;
112 b += (c ^ d ^ a) + k[2] - 995338651 | 0;
113 b = (b << 23 | b >>> 9) + c | 0;
114 a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;
115 a = (a << 6 | a >>> 26) + b | 0;
116 d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;
117 d = (d << 10 | d >>> 22) + a | 0;
118 c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;
119 c = (c << 15 | c >>> 17) + d | 0;
120 b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;
121 b = (b << 21 | b >>> 11) + c | 0;
122 a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;
123 a = (a << 6 | a >>> 26) + b | 0;
124 d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;
125 d = (d << 10 | d >>> 22) + a | 0;
126 c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;
127 c = (c << 15 | c >>> 17) + d | 0;
128 b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;
129 b = (b << 21 | b >>> 11) + c | 0;
130 a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;
131 a = (a << 6 | a >>> 26) + b | 0;
132 d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;
133 d = (d << 10 | d >>> 22) + a | 0;
134 c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;
135 c = (c << 15 | c >>> 17) + d | 0;
136 b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;
137 b = (b << 21 | b >>> 11) + c | 0;
138 a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;
139 a = (a << 6 | a >>> 26) + b | 0;
140 d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;
141 d = (d << 10 | d >>> 22) + a | 0;
142 c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;
143 c = (c << 15 | c >>> 17) + d | 0;
144 b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;
145 b = (b << 21 | b >>> 11) + c | 0;
146 x[0] = a + x[0] | 0;
147 x[1] = b + x[1] | 0;
148 x[2] = c + x[2] | 0;
149 x[3] = d + x[3] | 0;
150 }
151 function md5blk(s) {
152 var md5blks = [], i;
153 for (i = 0; i < 64; i += 4) {
154 md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
155 }
156 return md5blks;
157 }
158 function md5blk_array(a) {
159 var md5blks = [], i;
160 for (i = 0; i < 64; i += 4) {
161 md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
162 }
163 return md5blks;
164 }
165 function md51(s) {
166 var n = s.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
167 for (i = 64; i <= n; i += 64) {
168 md5cycle(state, md5blk(s.substring(i - 64, i)));
169 }
170 s = s.substring(i - 64);
171 length = s.length;
172 tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
173 for (i = 0; i < length; i += 1) {
174 tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);
175 }
176 tail[i >> 2] |= 128 << (i % 4 << 3);
177 if (i > 55) {
178 md5cycle(state, tail);
179 for (i = 0; i < 16; i += 1) {
180 tail[i] = 0;
181 }
182 }
183 tmp = n * 8;
184 tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
185 lo = parseInt(tmp[2], 16);
186 hi = parseInt(tmp[1], 16) || 0;
187 tail[14] = lo;
188 tail[15] = hi;
189 md5cycle(state, tail);
190 return state;
191 }
192 function md51_array(a) {
193 var n = a.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
194 for (i = 64; i <= n; i += 64) {
195 md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
196 }
197 a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0);
198 length = a.length;
199 tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
200 for (i = 0; i < length; i += 1) {
201 tail[i >> 2] |= a[i] << (i % 4 << 3);
202 }
203 tail[i >> 2] |= 128 << (i % 4 << 3);
204 if (i > 55) {
205 md5cycle(state, tail);
206 for (i = 0; i < 16; i += 1) {
207 tail[i] = 0;
208 }
209 }
210 tmp = n * 8;
211 tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
212 lo = parseInt(tmp[2], 16);
213 hi = parseInt(tmp[1], 16) || 0;
214 tail[14] = lo;
215 tail[15] = hi;
216 md5cycle(state, tail);
217 return state;
218 }
219 function rhex(n) {
220 var s = "", j;
221 for (j = 0; j < 4; j += 1) {
222 s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15];
223 }
224 return s;
225 }
226 function hex(x) {
227 var i;
228 for (i = 0; i < x.length; i += 1) {
229 x[i] = rhex(x[i]);
230 }
231 return x.join("");
232 }
233 if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ;
234 if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) {
235 (function() {
236 function clamp(val, length) {
237 val = val | 0 || 0;
238 if (val < 0) {
239 return Math.max(val + length, 0);
240 }
241 return Math.min(val, length);
242 }
243 ArrayBuffer.prototype.slice = function(from, to) {
244 var length = this.byteLength, begin = clamp(from, length), end = length, num, target, targetArray, sourceArray;
245 if (to !== undefined$1) {
246 end = clamp(to, length);
247 }
248 if (begin > end) {
249 return new ArrayBuffer(0);
250 }
251 num = end - begin;
252 target = new ArrayBuffer(num);
253 targetArray = new Uint8Array(target);
254 sourceArray = new Uint8Array(this, begin, num);
255 targetArray.set(sourceArray);
256 return target;
257 };
258 })();
259 }
260 function toUtf8(str) {
261 if (/[\u0080-\uFFFF]/.test(str)) {
262 str = unescape(encodeURIComponent(str));
263 }
264 return str;
265 }
266 function utf8Str2ArrayBuffer(str, returnUInt8Array) {
267 var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i;
268 for (i = 0; i < length; i += 1) {
269 arr[i] = str.charCodeAt(i);
270 }
271 return returnUInt8Array ? arr : buff;
272 }
273 function arrayBuffer2Utf8Str(buff) {
274 return String.fromCharCode.apply(null, new Uint8Array(buff));
275 }
276 function concatenateArrayBuffers(first, second, returnUInt8Array) {
277 var result = new Uint8Array(first.byteLength + second.byteLength);
278 result.set(new Uint8Array(first));
279 result.set(new Uint8Array(second), first.byteLength);
280 return returnUInt8Array ? result : result.buffer;
281 }
282 function hexToBinaryString(hex) {
283 var bytes = [], length = hex.length, x;
284 for (x = 0; x < length - 1; x += 2) {
285 bytes.push(parseInt(hex.substr(x, 2), 16));
286 }
287 return String.fromCharCode.apply(String, bytes);
288 }
289 function SparkMD5() {
290 this.reset();
291 }
292 SparkMD5.prototype.append = function(str) {
293 this.appendBinary(toUtf8(str));
294 return this;
295 };
296 SparkMD5.prototype.appendBinary = function(contents) {
297 this._buff += contents;
298 this._length += contents.length;
299 var length = this._buff.length, i;
300 for (i = 64; i <= length; i += 64) {
301 md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)));
302 }
303 this._buff = this._buff.substring(i - 64);
304 return this;
305 };
306 SparkMD5.prototype.end = function(raw) {
307 var buff = this._buff, length = buff.length, i, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], ret;
308 for (i = 0; i < length; i += 1) {
309 tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3);
310 }
311 this._finish(tail, length);
312 ret = hex(this._hash);
313 if (raw) {
314 ret = hexToBinaryString(ret);
315 }
316 this.reset();
317 return ret;
318 };
319 SparkMD5.prototype.reset = function() {
320 this._buff = "";
321 this._length = 0;
322 this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
323 return this;
324 };
325 SparkMD5.prototype.getState = function() {
326 return {
327 buff: this._buff,
328 length: this._length,
329 hash: this._hash.slice()
330 };
331 };
332 SparkMD5.prototype.setState = function(state) {
333 this._buff = state.buff;
334 this._length = state.length;
335 this._hash = state.hash;
336 return this;
337 };
338 SparkMD5.prototype.destroy = function() {
339 delete this._hash;
340 delete this._buff;
341 delete this._length;
342 };
343 SparkMD5.prototype._finish = function(tail, length) {
344 var i = length, tmp, lo, hi;
345 tail[i >> 2] |= 128 << (i % 4 << 3);
346 if (i > 55) {
347 md5cycle(this._hash, tail);
348 for (i = 0; i < 16; i += 1) {
349 tail[i] = 0;
350 }
351 }
352 tmp = this._length * 8;
353 tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
354 lo = parseInt(tmp[2], 16);
355 hi = parseInt(tmp[1], 16) || 0;
356 tail[14] = lo;
357 tail[15] = hi;
358 md5cycle(this._hash, tail);
359 };
360 SparkMD5.hash = function(str, raw) {
361 return SparkMD5.hashBinary(toUtf8(str), raw);
362 };
363 SparkMD5.hashBinary = function(content, raw) {
364 var hash = md51(content), ret = hex(hash);
365 return raw ? hexToBinaryString(ret) : ret;
366 };
367 SparkMD5.ArrayBuffer = function() {
368 this.reset();
369 };
370 SparkMD5.ArrayBuffer.prototype.append = function(arr) {
371 var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), length = buff.length, i;
372 this._length += arr.byteLength;
373 for (i = 64; i <= length; i += 64) {
374 md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)));
375 }
376 this._buff = i - 64 < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0);
377 return this;
378 };
379 SparkMD5.ArrayBuffer.prototype.end = function(raw) {
380 var buff = this._buff, length = buff.length, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], i, ret;
381 for (i = 0; i < length; i += 1) {
382 tail[i >> 2] |= buff[i] << (i % 4 << 3);
383 }
384 this._finish(tail, length);
385 ret = hex(this._hash);
386 if (raw) {
387 ret = hexToBinaryString(ret);
388 }
389 this.reset();
390 return ret;
391 };
392 SparkMD5.ArrayBuffer.prototype.reset = function() {
393 this._buff = new Uint8Array(0);
394 this._length = 0;
395 this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
396 return this;
397 };
398 SparkMD5.ArrayBuffer.prototype.getState = function() {
399 var state = SparkMD5.prototype.getState.call(this);
400 state.buff = arrayBuffer2Utf8Str(state.buff);
401 return state;
402 };
403 SparkMD5.ArrayBuffer.prototype.setState = function(state) {
404 state.buff = utf8Str2ArrayBuffer(state.buff, true);
405 return SparkMD5.prototype.setState.call(this, state);
406 };
407 SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
408 SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
409 SparkMD5.ArrayBuffer.hash = function(arr, raw) {
410 var hash = md51_array(new Uint8Array(arr)), ret = hex(hash);
411 return raw ? hexToBinaryString(ret) : ret;
412 };
413 return SparkMD5;
414 }));
415 })(sparkMd5);
416 var SparkMD5 = sparkMd5.exports;
417 const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
418 class FileChecksum {
419 static create(file, callback) {
420 const instance = new FileChecksum(file);
421 instance.create(callback);
422 }
423 constructor(file) {
424 this.file = file;
425 this.chunkSize = 2097152;
426 this.chunkCount = Math.ceil(this.file.size / this.chunkSize);
427 this.chunkIndex = 0;
428 }
429 create(callback) {
430 this.callback = callback;
431 this.md5Buffer = new SparkMD5.ArrayBuffer;
432 this.fileReader = new FileReader;
433 this.fileReader.addEventListener("load", (event => this.fileReaderDidLoad(event)));
434 this.fileReader.addEventListener("error", (event => this.fileReaderDidError(event)));
435 this.readNextChunk();
436 }
437 fileReaderDidLoad(event) {
438 this.md5Buffer.append(event.target.result);
439 if (!this.readNextChunk()) {
440 const binaryDigest = this.md5Buffer.end(true);
441 const base64digest = btoa(binaryDigest);
442 this.callback(null, base64digest);
443 }
444 }
445 fileReaderDidError(event) {
446 this.callback(`Error reading ${this.file.name}`);
447 }
448 readNextChunk() {
449 if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) {
450 const start = this.chunkIndex * this.chunkSize;
451 const end = Math.min(start + this.chunkSize, this.file.size);
452 const bytes = fileSlice.call(this.file, start, end);
453 this.fileReader.readAsArrayBuffer(bytes);
454 this.chunkIndex++;
455 return true;
456 } else {
457 return false;
458 }
459 }
460 }
461 function getMetaValue(name) {
462 const element = findElement(document.head, `meta[name="${name}"]`);
463 if (element) {
464 return element.getAttribute("content");
465 }
466 }
467 function findElements(root, selector) {
468 if (typeof root == "string") {
469 selector = root;
470 root = document;
471 }
472 const elements = root.querySelectorAll(selector);
473 return toArray(elements);
474 }
475 function findElement(root, selector) {
476 if (typeof root == "string") {
477 selector = root;
478 root = document;
479 }
480 return root.querySelector(selector);
481 }
482 function dispatchEvent(element, type, eventInit = {}) {
483 const {disabled: disabled} = element;
484 const {bubbles: bubbles, cancelable: cancelable, detail: detail} = eventInit;
485 const event = document.createEvent("Event");
486 event.initEvent(type, bubbles || true, cancelable || true);
487 event.detail = detail || {};
488 try {
489 element.disabled = false;
490 element.dispatchEvent(event);
491 } finally {
492 element.disabled = disabled;
493 }
494 return event;
495 }
496 function toArray(value) {
497 if (Array.isArray(value)) {
498 return value;
499 } else if (Array.from) {
500 return Array.from(value);
501 } else {
502 return [].slice.call(value);
503 }
504 }
505 class BlobRecord {
506 constructor(file, checksum, url, customHeaders = {}) {
507 this.file = file;
508 this.attributes = {
509 filename: file.name,
510 content_type: file.type || "application/octet-stream",
511 byte_size: file.size,
512 checksum: checksum
513 };
514 this.xhr = new XMLHttpRequest;
515 this.xhr.open("POST", url, true);
516 this.xhr.responseType = "json";
517 this.xhr.setRequestHeader("Content-Type", "application/json");
518 this.xhr.setRequestHeader("Accept", "application/json");
519 this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
520 Object.keys(customHeaders).forEach((headerKey => {
521 this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]);
522 }));
523 const csrfToken = getMetaValue("csrf-token");
524 if (csrfToken != undefined) {
525 this.xhr.setRequestHeader("X-CSRF-Token", csrfToken);
526 }
527 this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
528 this.xhr.addEventListener("error", (event => this.requestDidError(event)));
529 }
530 get status() {
531 return this.xhr.status;
532 }
533 get response() {
534 const {responseType: responseType, response: response} = this.xhr;
535 if (responseType == "json") {
536 return response;
537 } else {
538 return JSON.parse(response);
539 }
540 }
541 create(callback) {
542 this.callback = callback;
543 this.xhr.send(JSON.stringify({
544 blob: this.attributes
545 }));
546 }
547 requestDidLoad(event) {
548 if (this.status >= 200 && this.status < 300) {
549 const {response: response} = this;
550 const {direct_upload: direct_upload} = response;
551 delete response.direct_upload;
552 this.attributes = response;
553 this.directUploadData = direct_upload;
554 this.callback(null, this.toJSON());
555 } else {
556 this.requestDidError(event);
557 }
558 }
559 requestDidError(event) {
560 this.callback(`Error creating Blob for "${this.file.name}". Status: ${this.status}`);
561 }
562 toJSON() {
563 const result = {};
564 for (const key in this.attributes) {
565 result[key] = this.attributes[key];
566 }
567 return result;
568 }
569 }
570 class BlobUpload {
571 constructor(blob) {
572 this.blob = blob;
573 this.file = blob.file;
574 const {url: url, headers: headers} = blob.directUploadData;
575 this.xhr = new XMLHttpRequest;
576 this.xhr.open("PUT", url, true);
577 this.xhr.responseType = "text";
578 for (const key in headers) {
579 this.xhr.setRequestHeader(key, headers[key]);
580 }
581 this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
582 this.xhr.addEventListener("error", (event => this.requestDidError(event)));
583 }
584 create(callback) {
585 this.callback = callback;
586 this.xhr.send(this.file.slice());
587 }
588 requestDidLoad(event) {
589 const {status: status, response: response} = this.xhr;
590 if (status >= 200 && status < 300) {
591 this.callback(null, response);
592 } else {
593 this.requestDidError(event);
594 }
595 }
596 requestDidError(event) {
597 this.callback(`Error storing "${this.file.name}". Status: ${this.xhr.status}`);
598 }
599 }
600 let id = 0;
601 class DirectUpload {
602 constructor(file, url, delegate, customHeaders = {}) {
603 this.id = ++id;
604 this.file = file;
605 this.url = url;
606 this.delegate = delegate;
607 this.customHeaders = customHeaders;
608 }
609 create(callback) {
610 FileChecksum.create(this.file, ((error, checksum) => {
611 if (error) {
612 callback(error);
613 return;
614 }
615 const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders);
616 notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr);
617 blob.create((error => {
618 if (error) {
619 callback(error);
620 } else {
621 const upload = new BlobUpload(blob);
622 notify(this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr);
623 upload.create((error => {
624 if (error) {
625 callback(error);
626 } else {
627 callback(null, blob.toJSON());
628 }
629 }));
630 }
631 }));
632 }));
633 }
634 }
635 function notify(object, methodName, ...messages) {
636 if (object && typeof object[methodName] == "function") {
637 return object[methodName](...messages);
638 }
639 }
640 class DirectUploadController {
641 constructor(input, file) {
642 this.input = input;
643 this.file = file;
644 this.directUpload = new DirectUpload(this.file, this.url, this);
645 this.dispatch("initialize");
646 }
647 start(callback) {
648 const hiddenInput = document.createElement("input");
649 hiddenInput.type = "hidden";
650 hiddenInput.name = this.input.name;
651 this.input.insertAdjacentElement("beforebegin", hiddenInput);
652 this.dispatch("start");
653 this.directUpload.create(((error, attributes) => {
654 if (error) {
655 hiddenInput.parentNode.removeChild(hiddenInput);
656 this.dispatchError(error);
657 } else {
658 hiddenInput.value = attributes.signed_id;
659 }
660 this.dispatch("end");
661 callback(error);
662 }));
663 }
664 uploadRequestDidProgress(event) {
665 const progress = event.loaded / event.total * 100;
666 if (progress) {
667 this.dispatch("progress", {
668 progress: progress
669 });
670 }
671 }
672 get url() {
673 return this.input.getAttribute("data-direct-upload-url");
674 }
675 dispatch(name, detail = {}) {
676 detail.file = this.file;
677 detail.id = this.directUpload.id;
678 return dispatchEvent(this.input, `direct-upload:${name}`, {
679 detail: detail
680 });
681 }
682 dispatchError(error) {
683 const event = this.dispatch("error", {
684 error: error
685 });
686 if (!event.defaultPrevented) {
687 alert(error);
688 }
689 }
690 directUploadWillCreateBlobWithXHR(xhr) {
691 this.dispatch("before-blob-request", {
692 xhr: xhr
693 });
694 }
695 directUploadWillStoreFileWithXHR(xhr) {
696 this.dispatch("before-storage-request", {
697 xhr: xhr
698 });
699 xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event)));
700 }
701 }
702 const inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])";
703 class DirectUploadsController {
704 constructor(form) {
705 this.form = form;
706 this.inputs = findElements(form, inputSelector).filter((input => input.files.length));
707 }
708 start(callback) {
709 const controllers = this.createDirectUploadControllers();
710 const startNextController = () => {
711 const controller = controllers.shift();
712 if (controller) {
713 controller.start((error => {
714 if (error) {
715 callback(error);
716 this.dispatch("end");
717 } else {
718 startNextController();
719 }
720 }));
721 } else {
722 callback();
723 this.dispatch("end");
724 }
725 };
726 this.dispatch("start");
727 startNextController();
728 }
729 createDirectUploadControllers() {
730 const controllers = [];
731 this.inputs.forEach((input => {
732 toArray(input.files).forEach((file => {
733 const controller = new DirectUploadController(input, file);
734 controllers.push(controller);
735 }));
736 }));
737 return controllers;
738 }
739 dispatch(name, detail = {}) {
740 return dispatchEvent(this.form, `direct-uploads:${name}`, {
741 detail: detail
742 });
743 }
744 }
745 const processingAttribute = "data-direct-uploads-processing";
746 const submitButtonsByForm = new WeakMap;
747 let started = false;
748 function start() {
749 if (!started) {
750 started = true;
751 document.addEventListener("click", didClick, true);
752 document.addEventListener("submit", didSubmitForm, true);
753 document.addEventListener("ajax:before", didSubmitRemoteElement);
754 }
755 }
756 function didClick(event) {
757 const button = event.target.closest("button, input");
758 if (button && button.type === "submit" && button.form) {
759 submitButtonsByForm.set(button.form, button);
760 }
761 }
762 function didSubmitForm(event) {
763 handleFormSubmissionEvent(event);
764 }
765 function didSubmitRemoteElement(event) {
766 if (event.target.tagName == "FORM") {
767 handleFormSubmissionEvent(event);
768 }
769 }
770 function handleFormSubmissionEvent(event) {
771 const form = event.target;
772 if (form.hasAttribute(processingAttribute)) {
773 event.preventDefault();
774 return;
775 }
776 const controller = new DirectUploadsController(form);
777 const {inputs: inputs} = controller;
778 if (inputs.length) {
779 event.preventDefault();
780 form.setAttribute(processingAttribute, "");
781 inputs.forEach(disable);
782 controller.start((error => {
783 form.removeAttribute(processingAttribute);
784 if (error) {
785 inputs.forEach(enable);
786 } else {
787 submitForm(form);
788 }
789 }));
790 }
791 }
792 function submitForm(form) {
793 let button = submitButtonsByForm.get(form) || findElement(form, "input[type=submit], button[type=submit]");
794 if (button) {
795 const {disabled: disabled} = button;
796 button.disabled = false;
797 button.focus();
798 button.click();
799 button.disabled = disabled;
800 } else {
801 button = document.createElement("input");
802 button.type = "submit";
803 button.style.display = "none";
804 form.appendChild(button);
805 button.click();
806 form.removeChild(button);
807 }
808 submitButtonsByForm.delete(form);
809 }
810 function disable(input) {
811 input.disabled = true;
812 }
813 function enable(input) {
814 input.disabled = false;
815 }
816 function autostart() {
817 if (window.ActiveStorage) {
818 start();
819 }
820 }
821 setTimeout(autostart, 1);
822 exports.DirectUpload = DirectUpload;
823 exports.DirectUploadController = DirectUploadController;
824 exports.DirectUploadsController = DirectUploadsController;
825 exports.start = start;
826 Object.defineProperty(exports, "__esModule", {
827 value: true
828 });
829}));
diff --git a/public/assets/activestorage-7dbadea816242c6d03cc2f59c58398ab55bb9a70ee859fa962ad4c7ad4c48594.js.gz b/public/assets/activestorage-7dbadea816242c6d03cc2f59c58398ab55bb9a70ee859fa962ad4c7ad4c48594.js.gz
new file mode 100644
index 0000000..c268d42
--- /dev/null
+++ b/public/assets/activestorage-7dbadea816242c6d03cc2f59c58398ab55bb9a70ee859fa962ad4c7ad4c48594.js.gz
Binary files differ
diff --git a/public/assets/activestorage.esm-b2d9aa45888a540d7e6969e484dbdb0a0a501ff56542ce737db6599b311e3385.js b/public/assets/activestorage.esm-b2d9aa45888a540d7e6969e484dbdb0a0a501ff56542ce737db6599b311e3385.js
new file mode 100644
index 0000000..e6d60e6
--- /dev/null
+++ b/public/assets/activestorage.esm-b2d9aa45888a540d7e6969e484dbdb0a0a501ff56542ce737db6599b311e3385.js
@@ -0,0 +1,848 @@
1var sparkMd5 = {
2 exports: {}
3};
4
5(function(module, exports) {
6 (function(factory) {
7 {
8 module.exports = factory();
9 }
10 })((function(undefined$1) {
11 var hex_chr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ];
12 function md5cycle(x, k) {
13 var a = x[0], b = x[1], c = x[2], d = x[3];
14 a += (b & c | ~b & d) + k[0] - 680876936 | 0;
15 a = (a << 7 | a >>> 25) + b | 0;
16 d += (a & b | ~a & c) + k[1] - 389564586 | 0;
17 d = (d << 12 | d >>> 20) + a | 0;
18 c += (d & a | ~d & b) + k[2] + 606105819 | 0;
19 c = (c << 17 | c >>> 15) + d | 0;
20 b += (c & d | ~c & a) + k[3] - 1044525330 | 0;
21 b = (b << 22 | b >>> 10) + c | 0;
22 a += (b & c | ~b & d) + k[4] - 176418897 | 0;
23 a = (a << 7 | a >>> 25) + b | 0;
24 d += (a & b | ~a & c) + k[5] + 1200080426 | 0;
25 d = (d << 12 | d >>> 20) + a | 0;
26 c += (d & a | ~d & b) + k[6] - 1473231341 | 0;
27 c = (c << 17 | c >>> 15) + d | 0;
28 b += (c & d | ~c & a) + k[7] - 45705983 | 0;
29 b = (b << 22 | b >>> 10) + c | 0;
30 a += (b & c | ~b & d) + k[8] + 1770035416 | 0;
31 a = (a << 7 | a >>> 25) + b | 0;
32 d += (a & b | ~a & c) + k[9] - 1958414417 | 0;
33 d = (d << 12 | d >>> 20) + a | 0;
34 c += (d & a | ~d & b) + k[10] - 42063 | 0;
35 c = (c << 17 | c >>> 15) + d | 0;
36 b += (c & d | ~c & a) + k[11] - 1990404162 | 0;
37 b = (b << 22 | b >>> 10) + c | 0;
38 a += (b & c | ~b & d) + k[12] + 1804603682 | 0;
39 a = (a << 7 | a >>> 25) + b | 0;
40 d += (a & b | ~a & c) + k[13] - 40341101 | 0;
41 d = (d << 12 | d >>> 20) + a | 0;
42 c += (d & a | ~d & b) + k[14] - 1502002290 | 0;
43 c = (c << 17 | c >>> 15) + d | 0;
44 b += (c & d | ~c & a) + k[15] + 1236535329 | 0;
45 b = (b << 22 | b >>> 10) + c | 0;
46 a += (b & d | c & ~d) + k[1] - 165796510 | 0;
47 a = (a << 5 | a >>> 27) + b | 0;
48 d += (a & c | b & ~c) + k[6] - 1069501632 | 0;
49 d = (d << 9 | d >>> 23) + a | 0;
50 c += (d & b | a & ~b) + k[11] + 643717713 | 0;
51 c = (c << 14 | c >>> 18) + d | 0;
52 b += (c & a | d & ~a) + k[0] - 373897302 | 0;
53 b = (b << 20 | b >>> 12) + c | 0;
54 a += (b & d | c & ~d) + k[5] - 701558691 | 0;
55 a = (a << 5 | a >>> 27) + b | 0;
56 d += (a & c | b & ~c) + k[10] + 38016083 | 0;
57 d = (d << 9 | d >>> 23) + a | 0;
58 c += (d & b | a & ~b) + k[15] - 660478335 | 0;
59 c = (c << 14 | c >>> 18) + d | 0;
60 b += (c & a | d & ~a) + k[4] - 405537848 | 0;
61 b = (b << 20 | b >>> 12) + c | 0;
62 a += (b & d | c & ~d) + k[9] + 568446438 | 0;
63 a = (a << 5 | a >>> 27) + b | 0;
64 d += (a & c | b & ~c) + k[14] - 1019803690 | 0;
65 d = (d << 9 | d >>> 23) + a | 0;
66 c += (d & b | a & ~b) + k[3] - 187363961 | 0;
67 c = (c << 14 | c >>> 18) + d | 0;
68 b += (c & a | d & ~a) + k[8] + 1163531501 | 0;
69 b = (b << 20 | b >>> 12) + c | 0;
70 a += (b & d | c & ~d) + k[13] - 1444681467 | 0;
71 a = (a << 5 | a >>> 27) + b | 0;
72 d += (a & c | b & ~c) + k[2] - 51403784 | 0;
73 d = (d << 9 | d >>> 23) + a | 0;
74 c += (d & b | a & ~b) + k[7] + 1735328473 | 0;
75 c = (c << 14 | c >>> 18) + d | 0;
76 b += (c & a | d & ~a) + k[12] - 1926607734 | 0;
77 b = (b << 20 | b >>> 12) + c | 0;
78 a += (b ^ c ^ d) + k[5] - 378558 | 0;
79 a = (a << 4 | a >>> 28) + b | 0;
80 d += (a ^ b ^ c) + k[8] - 2022574463 | 0;
81 d = (d << 11 | d >>> 21) + a | 0;
82 c += (d ^ a ^ b) + k[11] + 1839030562 | 0;
83 c = (c << 16 | c >>> 16) + d | 0;
84 b += (c ^ d ^ a) + k[14] - 35309556 | 0;
85 b = (b << 23 | b >>> 9) + c | 0;
86 a += (b ^ c ^ d) + k[1] - 1530992060 | 0;
87 a = (a << 4 | a >>> 28) + b | 0;
88 d += (a ^ b ^ c) + k[4] + 1272893353 | 0;
89 d = (d << 11 | d >>> 21) + a | 0;
90 c += (d ^ a ^ b) + k[7] - 155497632 | 0;
91 c = (c << 16 | c >>> 16) + d | 0;
92 b += (c ^ d ^ a) + k[10] - 1094730640 | 0;
93 b = (b << 23 | b >>> 9) + c | 0;
94 a += (b ^ c ^ d) + k[13] + 681279174 | 0;
95 a = (a << 4 | a >>> 28) + b | 0;
96 d += (a ^ b ^ c) + k[0] - 358537222 | 0;
97 d = (d << 11 | d >>> 21) + a | 0;
98 c += (d ^ a ^ b) + k[3] - 722521979 | 0;
99 c = (c << 16 | c >>> 16) + d | 0;
100 b += (c ^ d ^ a) + k[6] + 76029189 | 0;
101 b = (b << 23 | b >>> 9) + c | 0;
102 a += (b ^ c ^ d) + k[9] - 640364487 | 0;
103 a = (a << 4 | a >>> 28) + b | 0;
104 d += (a ^ b ^ c) + k[12] - 421815835 | 0;
105 d = (d << 11 | d >>> 21) + a | 0;
106 c += (d ^ a ^ b) + k[15] + 530742520 | 0;
107 c = (c << 16 | c >>> 16) + d | 0;
108 b += (c ^ d ^ a) + k[2] - 995338651 | 0;
109 b = (b << 23 | b >>> 9) + c | 0;
110 a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;
111 a = (a << 6 | a >>> 26) + b | 0;
112 d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;
113 d = (d << 10 | d >>> 22) + a | 0;
114 c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;
115 c = (c << 15 | c >>> 17) + d | 0;
116 b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;
117 b = (b << 21 | b >>> 11) + c | 0;
118 a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;
119 a = (a << 6 | a >>> 26) + b | 0;
120 d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;
121 d = (d << 10 | d >>> 22) + a | 0;
122 c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;
123 c = (c << 15 | c >>> 17) + d | 0;
124 b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;
125 b = (b << 21 | b >>> 11) + c | 0;
126 a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;
127 a = (a << 6 | a >>> 26) + b | 0;
128 d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;
129 d = (d << 10 | d >>> 22) + a | 0;
130 c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;
131 c = (c << 15 | c >>> 17) + d | 0;
132 b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;
133 b = (b << 21 | b >>> 11) + c | 0;
134 a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;
135 a = (a << 6 | a >>> 26) + b | 0;
136 d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;
137 d = (d << 10 | d >>> 22) + a | 0;
138 c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;
139 c = (c << 15 | c >>> 17) + d | 0;
140 b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;
141 b = (b << 21 | b >>> 11) + c | 0;
142 x[0] = a + x[0] | 0;
143 x[1] = b + x[1] | 0;
144 x[2] = c + x[2] | 0;
145 x[3] = d + x[3] | 0;
146 }
147 function md5blk(s) {
148 var md5blks = [], i;
149 for (i = 0; i < 64; i += 4) {
150 md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
151 }
152 return md5blks;
153 }
154 function md5blk_array(a) {
155 var md5blks = [], i;
156 for (i = 0; i < 64; i += 4) {
157 md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
158 }
159 return md5blks;
160 }
161 function md51(s) {
162 var n = s.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
163 for (i = 64; i <= n; i += 64) {
164 md5cycle(state, md5blk(s.substring(i - 64, i)));
165 }
166 s = s.substring(i - 64);
167 length = s.length;
168 tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
169 for (i = 0; i < length; i += 1) {
170 tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);
171 }
172 tail[i >> 2] |= 128 << (i % 4 << 3);
173 if (i > 55) {
174 md5cycle(state, tail);
175 for (i = 0; i < 16; i += 1) {
176 tail[i] = 0;
177 }
178 }
179 tmp = n * 8;
180 tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
181 lo = parseInt(tmp[2], 16);
182 hi = parseInt(tmp[1], 16) || 0;
183 tail[14] = lo;
184 tail[15] = hi;
185 md5cycle(state, tail);
186 return state;
187 }
188 function md51_array(a) {
189 var n = a.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
190 for (i = 64; i <= n; i += 64) {
191 md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
192 }
193 a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0);
194 length = a.length;
195 tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
196 for (i = 0; i < length; i += 1) {
197 tail[i >> 2] |= a[i] << (i % 4 << 3);
198 }
199 tail[i >> 2] |= 128 << (i % 4 << 3);
200 if (i > 55) {
201 md5cycle(state, tail);
202 for (i = 0; i < 16; i += 1) {
203 tail[i] = 0;
204 }
205 }
206 tmp = n * 8;
207 tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
208 lo = parseInt(tmp[2], 16);
209 hi = parseInt(tmp[1], 16) || 0;
210 tail[14] = lo;
211 tail[15] = hi;
212 md5cycle(state, tail);
213 return state;
214 }
215 function rhex(n) {
216 var s = "", j;
217 for (j = 0; j < 4; j += 1) {
218 s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15];
219 }
220 return s;
221 }
222 function hex(x) {
223 var i;
224 for (i = 0; i < x.length; i += 1) {
225 x[i] = rhex(x[i]);
226 }
227 return x.join("");
228 }
229 if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ;
230 if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) {
231 (function() {
232 function clamp(val, length) {
233 val = val | 0 || 0;
234 if (val < 0) {
235 return Math.max(val + length, 0);
236 }
237 return Math.min(val, length);
238 }
239 ArrayBuffer.prototype.slice = function(from, to) {
240 var length = this.byteLength, begin = clamp(from, length), end = length, num, target, targetArray, sourceArray;
241 if (to !== undefined$1) {
242 end = clamp(to, length);
243 }
244 if (begin > end) {
245 return new ArrayBuffer(0);
246 }
247 num = end - begin;
248 target = new ArrayBuffer(num);
249 targetArray = new Uint8Array(target);
250 sourceArray = new Uint8Array(this, begin, num);
251 targetArray.set(sourceArray);
252 return target;
253 };
254 })();
255 }
256 function toUtf8(str) {
257 if (/[\u0080-\uFFFF]/.test(str)) {
258 str = unescape(encodeURIComponent(str));
259 }
260 return str;
261 }
262 function utf8Str2ArrayBuffer(str, returnUInt8Array) {
263 var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i;
264 for (i = 0; i < length; i += 1) {
265 arr[i] = str.charCodeAt(i);
266 }
267 return returnUInt8Array ? arr : buff;
268 }
269 function arrayBuffer2Utf8Str(buff) {
270 return String.fromCharCode.apply(null, new Uint8Array(buff));
271 }
272 function concatenateArrayBuffers(first, second, returnUInt8Array) {
273 var result = new Uint8Array(first.byteLength + second.byteLength);
274 result.set(new Uint8Array(first));
275 result.set(new Uint8Array(second), first.byteLength);
276 return returnUInt8Array ? result : result.buffer;
277 }
278 function hexToBinaryString(hex) {
279 var bytes = [], length = hex.length, x;
280 for (x = 0; x < length - 1; x += 2) {
281 bytes.push(parseInt(hex.substr(x, 2), 16));
282 }
283 return String.fromCharCode.apply(String, bytes);
284 }
285 function SparkMD5() {
286 this.reset();
287 }
288 SparkMD5.prototype.append = function(str) {
289 this.appendBinary(toUtf8(str));
290 return this;
291 };
292 SparkMD5.prototype.appendBinary = function(contents) {
293 this._buff += contents;
294 this._length += contents.length;
295 var length = this._buff.length, i;
296 for (i = 64; i <= length; i += 64) {
297 md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)));
298 }
299 this._buff = this._buff.substring(i - 64);
300 return this;
301 };
302 SparkMD5.prototype.end = function(raw) {
303 var buff = this._buff, length = buff.length, i, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], ret;
304 for (i = 0; i < length; i += 1) {
305 tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3);
306 }
307 this._finish(tail, length);
308 ret = hex(this._hash);
309 if (raw) {
310 ret = hexToBinaryString(ret);
311 }
312 this.reset();
313 return ret;
314 };
315 SparkMD5.prototype.reset = function() {
316 this._buff = "";
317 this._length = 0;
318 this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
319 return this;
320 };
321 SparkMD5.prototype.getState = function() {
322 return {
323 buff: this._buff,
324 length: this._length,
325 hash: this._hash.slice()
326 };
327 };
328 SparkMD5.prototype.setState = function(state) {
329 this._buff = state.buff;
330 this._length = state.length;
331 this._hash = state.hash;
332 return this;
333 };
334 SparkMD5.prototype.destroy = function() {
335 delete this._hash;
336 delete this._buff;
337 delete this._length;
338 };
339 SparkMD5.prototype._finish = function(tail, length) {
340 var i = length, tmp, lo, hi;
341 tail[i >> 2] |= 128 << (i % 4 << 3);
342 if (i > 55) {
343 md5cycle(this._hash, tail);
344 for (i = 0; i < 16; i += 1) {
345 tail[i] = 0;
346 }
347 }
348 tmp = this._length * 8;
349 tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
350 lo = parseInt(tmp[2], 16);
351 hi = parseInt(tmp[1], 16) || 0;
352 tail[14] = lo;
353 tail[15] = hi;
354 md5cycle(this._hash, tail);
355 };
356 SparkMD5.hash = function(str, raw) {
357 return SparkMD5.hashBinary(toUtf8(str), raw);
358 };
359 SparkMD5.hashBinary = function(content, raw) {
360 var hash = md51(content), ret = hex(hash);
361 return raw ? hexToBinaryString(ret) : ret;
362 };
363 SparkMD5.ArrayBuffer = function() {
364 this.reset();
365 };
366 SparkMD5.ArrayBuffer.prototype.append = function(arr) {
367 var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), length = buff.length, i;
368 this._length += arr.byteLength;
369 for (i = 64; i <= length; i += 64) {
370 md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)));
371 }
372 this._buff = i - 64 < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0);
373 return this;
374 };
375 SparkMD5.ArrayBuffer.prototype.end = function(raw) {
376 var buff = this._buff, length = buff.length, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], i, ret;
377 for (i = 0; i < length; i += 1) {
378 tail[i >> 2] |= buff[i] << (i % 4 << 3);
379 }
380 this._finish(tail, length);
381 ret = hex(this._hash);
382 if (raw) {
383 ret = hexToBinaryString(ret);
384 }
385 this.reset();
386 return ret;
387 };
388 SparkMD5.ArrayBuffer.prototype.reset = function() {
389 this._buff = new Uint8Array(0);
390 this._length = 0;
391 this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
392 return this;
393 };
394 SparkMD5.ArrayBuffer.prototype.getState = function() {
395 var state = SparkMD5.prototype.getState.call(this);
396 state.buff = arrayBuffer2Utf8Str(state.buff);
397 return state;
398 };
399 SparkMD5.ArrayBuffer.prototype.setState = function(state) {
400 state.buff = utf8Str2ArrayBuffer(state.buff, true);
401 return SparkMD5.prototype.setState.call(this, state);
402 };
403 SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
404 SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
405 SparkMD5.ArrayBuffer.hash = function(arr, raw) {
406 var hash = md51_array(new Uint8Array(arr)), ret = hex(hash);
407 return raw ? hexToBinaryString(ret) : ret;
408 };
409 return SparkMD5;
410 }));
411})(sparkMd5);
412
413var SparkMD5 = sparkMd5.exports;
414
415const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
416
417class FileChecksum {
418 static create(file, callback) {
419 const instance = new FileChecksum(file);
420 instance.create(callback);
421 }
422 constructor(file) {
423 this.file = file;
424 this.chunkSize = 2097152;
425 this.chunkCount = Math.ceil(this.file.size / this.chunkSize);
426 this.chunkIndex = 0;
427 }
428 create(callback) {
429 this.callback = callback;
430 this.md5Buffer = new SparkMD5.ArrayBuffer;
431 this.fileReader = new FileReader;
432 this.fileReader.addEventListener("load", (event => this.fileReaderDidLoad(event)));
433 this.fileReader.addEventListener("error", (event => this.fileReaderDidError(event)));
434 this.readNextChunk();
435 }
436 fileReaderDidLoad(event) {
437 this.md5Buffer.append(event.target.result);
438 if (!this.readNextChunk()) {
439 const binaryDigest = this.md5Buffer.end(true);
440 const base64digest = btoa(binaryDigest);
441 this.callback(null, base64digest);
442 }
443 }
444 fileReaderDidError(event) {
445 this.callback(`Error reading ${this.file.name}`);
446 }
447 readNextChunk() {
448 if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) {
449 const start = this.chunkIndex * this.chunkSize;
450 const end = Math.min(start + this.chunkSize, this.file.size);
451 const bytes = fileSlice.call(this.file, start, end);
452 this.fileReader.readAsArrayBuffer(bytes);
453 this.chunkIndex++;
454 return true;
455 } else {
456 return false;
457 }
458 }
459}
460
461function getMetaValue(name) {
462 const element = findElement(document.head, `meta[name="${name}"]`);
463 if (element) {
464 return element.getAttribute("content");
465 }
466}
467
468function findElements(root, selector) {
469 if (typeof root == "string") {
470 selector = root;
471 root = document;
472 }
473 const elements = root.querySelectorAll(selector);
474 return toArray(elements);
475}
476
477function findElement(root, selector) {
478 if (typeof root == "string") {
479 selector = root;
480 root = document;
481 }
482 return root.querySelector(selector);
483}
484
485function dispatchEvent(element, type, eventInit = {}) {
486 const {disabled: disabled} = element;
487 const {bubbles: bubbles, cancelable: cancelable, detail: detail} = eventInit;
488 const event = document.createEvent("Event");
489 event.initEvent(type, bubbles || true, cancelable || true);
490 event.detail = detail || {};
491 try {
492 element.disabled = false;
493 element.dispatchEvent(event);
494 } finally {
495 element.disabled = disabled;
496 }
497 return event;
498}
499
500function toArray(value) {
501 if (Array.isArray(value)) {
502 return value;
503 } else if (Array.from) {
504 return Array.from(value);
505 } else {
506 return [].slice.call(value);
507 }
508}
509
510class BlobRecord {
511 constructor(file, checksum, url, customHeaders = {}) {
512 this.file = file;
513 this.attributes = {
514 filename: file.name,
515 content_type: file.type || "application/octet-stream",
516 byte_size: file.size,
517 checksum: checksum
518 };
519 this.xhr = new XMLHttpRequest;
520 this.xhr.open("POST", url, true);
521 this.xhr.responseType = "json";
522 this.xhr.setRequestHeader("Content-Type", "application/json");
523 this.xhr.setRequestHeader("Accept", "application/json");
524 this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
525 Object.keys(customHeaders).forEach((headerKey => {
526 this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]);
527 }));
528 const csrfToken = getMetaValue("csrf-token");
529 if (csrfToken != undefined) {
530 this.xhr.setRequestHeader("X-CSRF-Token", csrfToken);
531 }
532 this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
533 this.xhr.addEventListener("error", (event => this.requestDidError(event)));
534 }
535 get status() {
536 return this.xhr.status;
537 }
538 get response() {
539 const {responseType: responseType, response: response} = this.xhr;
540 if (responseType == "json") {
541 return response;
542 } else {
543 return JSON.parse(response);
544 }
545 }
546 create(callback) {
547 this.callback = callback;
548 this.xhr.send(JSON.stringify({
549 blob: this.attributes
550 }));
551 }
552 requestDidLoad(event) {
553 if (this.status >= 200 && this.status < 300) {
554 const {response: response} = this;
555 const {direct_upload: direct_upload} = response;
556 delete response.direct_upload;
557 this.attributes = response;
558 this.directUploadData = direct_upload;
559 this.callback(null, this.toJSON());
560 } else {
561 this.requestDidError(event);
562 }
563 }
564 requestDidError(event) {
565 this.callback(`Error creating Blob for "${this.file.name}". Status: ${this.status}`);
566 }
567 toJSON() {
568 const result = {};
569 for (const key in this.attributes) {
570 result[key] = this.attributes[key];
571 }
572 return result;
573 }
574}
575
576class BlobUpload {
577 constructor(blob) {
578 this.blob = blob;
579 this.file = blob.file;
580 const {url: url, headers: headers} = blob.directUploadData;
581 this.xhr = new XMLHttpRequest;
582 this.xhr.open("PUT", url, true);
583 this.xhr.responseType = "text";
584 for (const key in headers) {
585 this.xhr.setRequestHeader(key, headers[key]);
586 }
587 this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
588 this.xhr.addEventListener("error", (event => this.requestDidError(event)));
589 }
590 create(callback) {
591 this.callback = callback;
592 this.xhr.send(this.file.slice());
593 }
594 requestDidLoad(event) {
595 const {status: status, response: response} = this.xhr;
596 if (status >= 200 && status < 300) {
597 this.callback(null, response);
598 } else {
599 this.requestDidError(event);
600 }
601 }
602 requestDidError(event) {
603 this.callback(`Error storing "${this.file.name}". Status: ${this.xhr.status}`);
604 }
605}
606
607let id = 0;
608
609class DirectUpload {
610 constructor(file, url, delegate, customHeaders = {}) {
611 this.id = ++id;
612 this.file = file;
613 this.url = url;
614 this.delegate = delegate;
615 this.customHeaders = customHeaders;
616 }
617 create(callback) {
618 FileChecksum.create(this.file, ((error, checksum) => {
619 if (error) {
620 callback(error);
621 return;
622 }
623 const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders);
624 notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr);
625 blob.create((error => {
626 if (error) {
627 callback(error);
628 } else {
629 const upload = new BlobUpload(blob);
630 notify(this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr);
631 upload.create((error => {
632 if (error) {
633 callback(error);
634 } else {
635 callback(null, blob.toJSON());
636 }
637 }));
638 }
639 }));
640 }));
641 }
642}
643
644function notify(object, methodName, ...messages) {
645 if (object && typeof object[methodName] == "function") {
646 return object[methodName](...messages);
647 }
648}
649
650class DirectUploadController {
651 constructor(input, file) {
652 this.input = input;
653 this.file = file;
654 this.directUpload = new DirectUpload(this.file, this.url, this);
655 this.dispatch("initialize");
656 }
657 start(callback) {
658 const hiddenInput = document.createElement("input");
659 hiddenInput.type = "hidden";
660 hiddenInput.name = this.input.name;
661 this.input.insertAdjacentElement("beforebegin", hiddenInput);
662 this.dispatch("start");
663 this.directUpload.create(((error, attributes) => {
664 if (error) {
665 hiddenInput.parentNode.removeChild(hiddenInput);
666 this.dispatchError(error);
667 } else {
668 hiddenInput.value = attributes.signed_id;
669 }
670 this.dispatch("end");
671 callback(error);
672 }));
673 }
674 uploadRequestDidProgress(event) {
675 const progress = event.loaded / event.total * 100;
676 if (progress) {
677 this.dispatch("progress", {
678 progress: progress
679 });
680 }
681 }
682 get url() {
683 return this.input.getAttribute("data-direct-upload-url");
684 }
685 dispatch(name, detail = {}) {
686 detail.file = this.file;
687 detail.id = this.directUpload.id;
688 return dispatchEvent(this.input, `direct-upload:${name}`, {
689 detail: detail
690 });
691 }
692 dispatchError(error) {
693 const event = this.dispatch("error", {
694 error: error
695 });
696 if (!event.defaultPrevented) {
697 alert(error);
698 }
699 }
700 directUploadWillCreateBlobWithXHR(xhr) {
701 this.dispatch("before-blob-request", {
702 xhr: xhr
703 });
704 }
705 directUploadWillStoreFileWithXHR(xhr) {
706 this.dispatch("before-storage-request", {
707 xhr: xhr
708 });
709 xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event)));
710 }
711}
712
713const inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])";
714
715class DirectUploadsController {
716 constructor(form) {
717 this.form = form;
718 this.inputs = findElements(form, inputSelector).filter((input => input.files.length));
719 }
720 start(callback) {
721 const controllers = this.createDirectUploadControllers();
722 const startNextController = () => {
723 const controller = controllers.shift();
724 if (controller) {
725 controller.start((error => {
726 if (error) {
727 callback(error);
728 this.dispatch("end");
729 } else {
730 startNextController();
731 }
732 }));
733 } else {
734 callback();
735 this.dispatch("end");
736 }
737 };
738 this.dispatch("start");
739 startNextController();
740 }
741 createDirectUploadControllers() {
742 const controllers = [];
743 this.inputs.forEach((input => {
744 toArray(input.files).forEach((file => {
745 const controller = new DirectUploadController(input, file);
746 controllers.push(controller);
747 }));
748 }));
749 return controllers;
750 }
751 dispatch(name, detail = {}) {
752 return dispatchEvent(this.form, `direct-uploads:${name}`, {
753 detail: detail
754 });
755 }
756}
757
758const processingAttribute = "data-direct-uploads-processing";
759
760const submitButtonsByForm = new WeakMap;
761
762let started = false;
763
764function start() {
765 if (!started) {
766 started = true;
767 document.addEventListener("click", didClick, true);
768 document.addEventListener("submit", didSubmitForm, true);
769 document.addEventListener("ajax:before", didSubmitRemoteElement);
770 }
771}
772
773function didClick(event) {
774 const button = event.target.closest("button, input");
775 if (button && button.type === "submit" && button.form) {
776 submitButtonsByForm.set(button.form, button);
777 }
778}
779
780function didSubmitForm(event) {
781 handleFormSubmissionEvent(event);
782}
783
784function didSubmitRemoteElement(event) {
785 if (event.target.tagName == "FORM") {
786 handleFormSubmissionEvent(event);
787 }
788}
789
790function handleFormSubmissionEvent(event) {
791 const form = event.target;
792 if (form.hasAttribute(processingAttribute)) {
793 event.preventDefault();
794 return;
795 }
796 const controller = new DirectUploadsController(form);
797 const {inputs: inputs} = controller;
798 if (inputs.length) {
799 event.preventDefault();
800 form.setAttribute(processingAttribute, "");
801 inputs.forEach(disable);
802 controller.start((error => {
803 form.removeAttribute(processingAttribute);
804 if (error) {
805 inputs.forEach(enable);
806 } else {
807 submitForm(form);
808 }
809 }));
810 }
811}
812
813function submitForm(form) {
814 let button = submitButtonsByForm.get(form) || findElement(form, "input[type=submit], button[type=submit]");
815 if (button) {
816 const {disabled: disabled} = button;
817 button.disabled = false;
818 button.focus();
819 button.click();
820 button.disabled = disabled;
821 } else {
822 button = document.createElement("input");
823 button.type = "submit";
824 button.style.display = "none";
825 form.appendChild(button);
826 button.click();
827 form.removeChild(button);
828 }
829 submitButtonsByForm.delete(form);
830}
831
832function disable(input) {
833 input.disabled = true;
834}
835
836function enable(input) {
837 input.disabled = false;
838}
839
840function autostart() {
841 if (window.ActiveStorage) {
842 start();
843 }
844}
845
846setTimeout(autostart, 1);
847
848export { DirectUpload, DirectUploadController, DirectUploadsController, start };
diff --git a/public/assets/activestorage.esm-b2d9aa45888a540d7e6969e484dbdb0a0a501ff56542ce737db6599b311e3385.js.gz b/public/assets/activestorage.esm-b2d9aa45888a540d7e6969e484dbdb0a0a501ff56542ce737db6599b311e3385.js.gz
new file mode 100644
index 0000000..8549f9c
--- /dev/null
+++ b/public/assets/activestorage.esm-b2d9aa45888a540d7e6969e484dbdb0a0a501ff56542ce737db6599b311e3385.js.gz
Binary files differ
diff --git a/public/assets/admin_bundle-e15d8265faa7d827f0b57416f9aeec7a730d7f47ede994b76014444669fb2081.js b/public/assets/admin_bundle-e15d8265faa7d827f0b57416f9aeec7a730d7f47ede994b76014444669fb2081.js
new file mode 100644
index 0000000..68bb979
--- /dev/null
+++ b/public/assets/admin_bundle-e15d8265faa7d827f0b57416f9aeec7a730d7f47ede994b76014444669fb2081.js
@@ -0,0 +1,31775 @@
1/*!
2 * jQuery JavaScript Library v1.12.4
3 * http://jquery.com/
4 *
5 * Includes Sizzle.js
6 * http://sizzlejs.com/
7 *
8 * Copyright jQuery Foundation and other contributors
9 * Released under the MIT license
10 * http://jquery.org/license
11 *
12 * Date: 2016-05-20T17:17Z
13 */
14
15(function( global, factory ) {
16
17 if ( typeof module === "object" && typeof module.exports === "object" ) {
18 // For CommonJS and CommonJS-like environments where a proper `window`
19 // is present, execute the factory and get jQuery.
20 // For environments that do not have a `window` with a `document`
21 // (such as Node.js), expose a factory as module.exports.
22 // This accentuates the need for the creation of a real `window`.
23 // e.g. var jQuery = require("jquery")(window);
24 // See ticket #14549 for more info.
25 module.exports = global.document ?
26 factory( global, true ) :
27 function( w ) {
28 if ( !w.document ) {
29 throw new Error( "jQuery requires a window with a document" );
30 }
31 return factory( w );
32 };
33 } else {
34 factory( global );
35 }
36
37// Pass this if window is not defined yet
38}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
39
40// Support: Firefox 18+
41// Can't be in strict mode, several libs including ASP.NET trace
42// the stack via arguments.caller.callee and Firefox dies if
43// you try to trace through "use strict" call chains. (#13335)
44//"use strict";
45var deletedIds = [];
46
47var document = window.document;
48
49var slice = deletedIds.slice;
50
51var concat = deletedIds.concat;
52
53var push = deletedIds.push;
54
55var indexOf = deletedIds.indexOf;
56
57var class2type = {};
58
59var toString = class2type.toString;
60
61var hasOwn = class2type.hasOwnProperty;
62
63var support = {};
64
65
66
67var
68 version = "1.12.4",
69
70 // Define a local copy of jQuery
71 jQuery = function( selector, context ) {
72
73 // The jQuery object is actually just the init constructor 'enhanced'
74 // Need init if jQuery is called (just allow error to be thrown if not included)
75 return new jQuery.fn.init( selector, context );
76 },
77
78 // Support: Android<4.1, IE<9
79 // Make sure we trim BOM and NBSP
80 rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
81
82 // Matches dashed string for camelizing
83 rmsPrefix = /^-ms-/,
84 rdashAlpha = /-([\da-z])/gi,
85
86 // Used by jQuery.camelCase as callback to replace()
87 fcamelCase = function( all, letter ) {
88 return letter.toUpperCase();
89 };
90
91jQuery.fn = jQuery.prototype = {
92
93 // The current version of jQuery being used
94 jquery: version,
95
96 constructor: jQuery,
97
98 // Start with an empty selector
99 selector: "",
100
101 // The default length of a jQuery object is 0
102 length: 0,
103
104 toArray: function() {
105 return slice.call( this );
106 },
107
108 // Get the Nth element in the matched element set OR
109 // Get the whole matched element set as a clean array
110 get: function( num ) {
111 return num != null ?
112
113 // Return just the one element from the set
114 ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
115
116 // Return all the elements in a clean array
117 slice.call( this );
118 },
119
120 // Take an array of elements and push it onto the stack
121 // (returning the new matched element set)
122 pushStack: function( elems ) {
123
124 // Build a new jQuery matched element set
125 var ret = jQuery.merge( this.constructor(), elems );
126
127 // Add the old object onto the stack (as a reference)
128 ret.prevObject = this;
129 ret.context = this.context;
130
131 // Return the newly-formed element set
132 return ret;
133 },
134
135 // Execute a callback for every element in the matched set.
136 each: function( callback ) {
137 return jQuery.each( this, callback );
138 },
139
140 map: function( callback ) {
141 return this.pushStack( jQuery.map( this, function( elem, i ) {
142 return callback.call( elem, i, elem );
143 } ) );
144 },
145
146 slice: function() {
147 return this.pushStack( slice.apply( this, arguments ) );
148 },
149
150 first: function() {
151 return this.eq( 0 );
152 },
153
154 last: function() {
155 return this.eq( -1 );
156 },
157
158 eq: function( i ) {
159 var len = this.length,
160 j = +i + ( i < 0 ? len : 0 );
161 return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
162 },
163
164 end: function() {
165 return this.prevObject || this.constructor();
166 },
167
168 // For internal use only.
169 // Behaves like an Array's method, not like a jQuery method.
170 push: push,
171 sort: deletedIds.sort,
172 splice: deletedIds.splice
173};
174
175jQuery.extend = jQuery.fn.extend = function() {
176 var src, copyIsArray, copy, name, options, clone,
177 target = arguments[ 0 ] || {},
178 i = 1,
179 length = arguments.length,
180 deep = false;
181
182 // Handle a deep copy situation
183 if ( typeof target === "boolean" ) {
184 deep = target;
185
186 // skip the boolean and the target
187 target = arguments[ i ] || {};
188 i++;
189 }
190
191 // Handle case when target is a string or something (possible in deep copy)
192 if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
193 target = {};
194 }
195
196 // extend jQuery itself if only one argument is passed
197 if ( i === length ) {
198 target = this;
199 i--;
200 }
201
202 for ( ; i < length; i++ ) {
203
204 // Only deal with non-null/undefined values
205 if ( ( options = arguments[ i ] ) != null ) {
206
207 // Extend the base object
208 for ( name in options ) {
209 src = target[ name ];
210 copy = options[ name ];
211
212 // Prevent never-ending loop
213 if ( target === copy ) {
214 continue;
215 }
216
217 // Recurse if we're merging plain objects or arrays
218 if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
219 ( copyIsArray = jQuery.isArray( copy ) ) ) ) {
220
221 if ( copyIsArray ) {
222 copyIsArray = false;
223 clone = src && jQuery.isArray( src ) ? src : [];
224
225 } else {
226 clone = src && jQuery.isPlainObject( src ) ? src : {};
227 }
228
229 // Never move original objects, clone them
230 target[ name ] = jQuery.extend( deep, clone, copy );
231
232 // Don't bring in undefined values
233 } else if ( copy !== undefined ) {
234 target[ name ] = copy;
235 }
236 }
237 }
238 }
239
240 // Return the modified object
241 return target;
242};
243
244jQuery.extend( {
245
246 // Unique for each copy of jQuery on the page
247 expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
248
249 // Assume jQuery is ready without the ready module
250 isReady: true,
251
252 error: function( msg ) {
253 throw new Error( msg );
254 },
255
256 noop: function() {},
257
258 // See test/unit/core.js for details concerning isFunction.
259 // Since version 1.3, DOM methods and functions like alert
260 // aren't supported. They return false on IE (#2968).
261 isFunction: function( obj ) {
262 return jQuery.type( obj ) === "function";
263 },
264
265 isArray: Array.isArray || function( obj ) {
266 return jQuery.type( obj ) === "array";
267 },
268
269 isWindow: function( obj ) {
270 /* jshint eqeqeq: false */
271 return obj != null && obj == obj.window;
272 },
273
274 isNumeric: function( obj ) {
275
276 // parseFloat NaNs numeric-cast false positives (null|true|false|"")
277 // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
278 // subtraction forces infinities to NaN
279 // adding 1 corrects loss of precision from parseFloat (#15100)
280 var realStringObj = obj && obj.toString();
281 return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0;
282 },
283
284 isEmptyObject: function( obj ) {
285 var name;
286 for ( name in obj ) {
287 return false;
288 }
289 return true;
290 },
291
292 isPlainObject: function( obj ) {
293 var key;
294
295 // Must be an Object.
296 // Because of IE, we also have to check the presence of the constructor property.
297 // Make sure that DOM nodes and window objects don't pass through, as well
298 if ( !obj || jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
299 return false;
300 }
301
302 try {
303
304 // Not own constructor property must be Object
305 if ( obj.constructor &&
306 !hasOwn.call( obj, "constructor" ) &&
307 !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
308 return false;
309 }
310 } catch ( e ) {
311
312 // IE8,9 Will throw exceptions on certain host objects #9897
313 return false;
314 }
315
316 // Support: IE<9
317 // Handle iteration over inherited properties before own properties.
318 if ( !support.ownFirst ) {
319 for ( key in obj ) {
320 return hasOwn.call( obj, key );
321 }
322 }
323
324 // Own properties are enumerated firstly, so to speed up,
325 // if last one is own, then all properties are own.
326 for ( key in obj ) {}
327
328 return key === undefined || hasOwn.call( obj, key );
329 },
330
331 type: function( obj ) {
332 if ( obj == null ) {
333 return obj + "";
334 }
335 return typeof obj === "object" || typeof obj === "function" ?
336 class2type[ toString.call( obj ) ] || "object" :
337 typeof obj;
338 },
339
340 // Workarounds based on findings by Jim Driscoll
341 // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
342 globalEval: function( data ) {
343 if ( data && jQuery.trim( data ) ) {
344
345 // We use execScript on Internet Explorer
346 // We use an anonymous function so that context is window
347 // rather than jQuery in Firefox
348 ( window.execScript || function( data ) {
349 window[ "eval" ].call( window, data ); // jscs:ignore requireDotNotation
350 } )( data );
351 }
352 },
353
354 // Convert dashed to camelCase; used by the css and data modules
355 // Microsoft forgot to hump their vendor prefix (#9572)
356 camelCase: function( string ) {
357 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
358 },
359
360 nodeName: function( elem, name ) {
361 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
362 },
363
364 each: function( obj, callback ) {
365 var length, i = 0;
366
367 if ( isArrayLike( obj ) ) {
368 length = obj.length;
369 for ( ; i < length; i++ ) {
370 if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
371 break;
372 }
373 }
374 } else {
375 for ( i in obj ) {
376 if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
377 break;
378 }
379 }
380 }
381
382 return obj;
383 },
384
385 // Support: Android<4.1, IE<9
386 trim: function( text ) {
387 return text == null ?
388 "" :
389 ( text + "" ).replace( rtrim, "" );
390 },
391
392 // results is for internal usage only
393 makeArray: function( arr, results ) {
394 var ret = results || [];
395
396 if ( arr != null ) {
397 if ( isArrayLike( Object( arr ) ) ) {
398 jQuery.merge( ret,
399 typeof arr === "string" ?
400 [ arr ] : arr
401 );
402 } else {
403 push.call( ret, arr );
404 }
405 }
406
407 return ret;
408 },
409
410 inArray: function( elem, arr, i ) {
411 var len;
412
413 if ( arr ) {
414 if ( indexOf ) {
415 return indexOf.call( arr, elem, i );
416 }
417
418 len = arr.length;
419 i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
420
421 for ( ; i < len; i++ ) {
422
423 // Skip accessing in sparse arrays
424 if ( i in arr && arr[ i ] === elem ) {
425 return i;
426 }
427 }
428 }
429
430 return -1;
431 },
432
433 merge: function( first, second ) {
434 var len = +second.length,
435 j = 0,
436 i = first.length;
437
438 while ( j < len ) {
439 first[ i++ ] = second[ j++ ];
440 }
441
442 // Support: IE<9
443 // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
444 if ( len !== len ) {
445 while ( second[ j ] !== undefined ) {
446 first[ i++ ] = second[ j++ ];
447 }
448 }
449
450 first.length = i;
451
452 return first;
453 },
454
455 grep: function( elems, callback, invert ) {
456 var callbackInverse,
457 matches = [],
458 i = 0,
459 length = elems.length,
460 callbackExpect = !invert;
461
462 // Go through the array, only saving the items
463 // that pass the validator function
464 for ( ; i < length; i++ ) {
465 callbackInverse = !callback( elems[ i ], i );
466 if ( callbackInverse !== callbackExpect ) {
467 matches.push( elems[ i ] );
468 }
469 }
470
471 return matches;
472 },
473
474 // arg is for internal usage only
475 map: function( elems, callback, arg ) {
476 var length, value,
477 i = 0,
478 ret = [];
479
480 // Go through the array, translating each of the items to their new values
481 if ( isArrayLike( elems ) ) {
482 length = elems.length;
483 for ( ; i < length; i++ ) {
484 value = callback( elems[ i ], i, arg );
485
486 if ( value != null ) {
487 ret.push( value );
488 }
489 }
490
491 // Go through every key on the object,
492 } else {
493 for ( i in elems ) {
494 value = callback( elems[ i ], i, arg );
495
496 if ( value != null ) {
497 ret.push( value );
498 }
499 }
500 }
501
502 // Flatten any nested arrays
503 return concat.apply( [], ret );
504 },
505
506 // A global GUID counter for objects
507 guid: 1,
508
509 // Bind a function to a context, optionally partially applying any
510 // arguments.
511 proxy: function( fn, context ) {
512 var args, proxy, tmp;
513
514 if ( typeof context === "string" ) {
515 tmp = fn[ context ];
516 context = fn;
517 fn = tmp;
518 }
519
520 // Quick check to determine if target is callable, in the spec
521 // this throws a TypeError, but we will just return undefined.
522 if ( !jQuery.isFunction( fn ) ) {
523 return undefined;
524 }
525
526 // Simulated bind
527 args = slice.call( arguments, 2 );
528 proxy = function() {
529 return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
530 };
531
532 // Set the guid of unique handler to the same of original handler, so it can be removed
533 proxy.guid = fn.guid = fn.guid || jQuery.guid++;
534
535 return proxy;
536 },
537
538 now: function() {
539 return +( new Date() );
540 },
541
542 // jQuery.support is not used in Core but other projects attach their
543 // properties to it so it needs to exist.
544 support: support
545} );
546
547// JSHint would error on this code due to the Symbol not being defined in ES5.
548// Defining this global in .jshintrc would create a danger of using the global
549// unguarded in another place, it seems safer to just disable JSHint for these
550// three lines.
551/* jshint ignore: start */
552if ( typeof Symbol === "function" ) {
553 jQuery.fn[ Symbol.iterator ] = deletedIds[ Symbol.iterator ];
554}
555/* jshint ignore: end */
556
557// Populate the class2type map
558jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
559function( i, name ) {
560 class2type[ "[object " + name + "]" ] = name.toLowerCase();
561} );
562
563function isArrayLike( obj ) {
564
565 // Support: iOS 8.2 (not reproducible in simulator)
566 // `in` check used to prevent JIT error (gh-2145)
567 // hasOwn isn't used here due to false negatives
568 // regarding Nodelist length in IE
569 var length = !!obj && "length" in obj && obj.length,
570 type = jQuery.type( obj );
571
572 if ( type === "function" || jQuery.isWindow( obj ) ) {
573 return false;
574 }
575
576 return type === "array" || length === 0 ||
577 typeof length === "number" && length > 0 && ( length - 1 ) in obj;
578}
579var Sizzle =
580/*!
581 * Sizzle CSS Selector Engine v2.2.1
582 * http://sizzlejs.com/
583 *
584 * Copyright jQuery Foundation and other contributors
585 * Released under the MIT license
586 * http://jquery.org/license
587 *
588 * Date: 2015-10-17
589 */
590(function( window ) {
591
592var i,
593 support,
594 Expr,
595 getText,
596 isXML,
597 tokenize,
598 compile,
599 select,
600 outermostContext,
601 sortInput,
602 hasDuplicate,
603
604 // Local document vars
605 setDocument,
606 document,
607 docElem,
608 documentIsHTML,
609 rbuggyQSA,
610 rbuggyMatches,
611 matches,
612 contains,
613
614 // Instance-specific data
615 expando = "sizzle" + 1 * new Date(),
616 preferredDoc = window.document,
617 dirruns = 0,
618 done = 0,
619 classCache = createCache(),
620 tokenCache = createCache(),
621 compilerCache = createCache(),
622 sortOrder = function( a, b ) {
623 if ( a === b ) {
624 hasDuplicate = true;
625 }
626 return 0;
627 },
628
629 // General-purpose constants
630 MAX_NEGATIVE = 1 << 31,
631
632 // Instance methods
633 hasOwn = ({}).hasOwnProperty,
634 arr = [],
635 pop = arr.pop,
636 push_native = arr.push,
637 push = arr.push,
638 slice = arr.slice,
639 // Use a stripped-down indexOf as it's faster than native
640 // http://jsperf.com/thor-indexof-vs-for/5
641 indexOf = function( list, elem ) {
642 var i = 0,
643 len = list.length;
644 for ( ; i < len; i++ ) {
645 if ( list[i] === elem ) {
646 return i;
647 }
648 }
649 return -1;
650 },
651
652 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
653
654 // Regular expressions
655
656 // http://www.w3.org/TR/css3-selectors/#whitespace
657 whitespace = "[\\x20\\t\\r\\n\\f]",
658
659 // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
660 identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
661
662 // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
663 attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
664 // Operator (capture 2)
665 "*([*^$|!~]?=)" + whitespace +
666 // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
667 "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
668 "*\\]",
669
670 pseudos = ":(" + identifier + ")(?:\\((" +
671 // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
672 // 1. quoted (capture 3; capture 4 or capture 5)
673 "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
674 // 2. simple (capture 6)
675 "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
676 // 3. anything else (capture 2)
677 ".*" +
678 ")\\)|)",
679
680 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
681 rwhitespace = new RegExp( whitespace + "+", "g" ),
682 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
683
684 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
685 rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
686
687 rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
688
689 rpseudo = new RegExp( pseudos ),
690 ridentifier = new RegExp( "^" + identifier + "$" ),
691
692 matchExpr = {
693 "ID": new RegExp( "^#(" + identifier + ")" ),
694 "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
695 "TAG": new RegExp( "^(" + identifier + "|[*])" ),
696 "ATTR": new RegExp( "^" + attributes ),
697 "PSEUDO": new RegExp( "^" + pseudos ),
698 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
699 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
700 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
701 "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
702 // For use in libraries implementing .is()
703 // We use this for POS matching in `select`
704 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
705 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
706 },
707
708 rinputs = /^(?:input|select|textarea|button)$/i,
709 rheader = /^h\d$/i,
710
711 rnative = /^[^{]+\{\s*\[native \w/,
712
713 // Easily-parseable/retrievable ID or TAG or CLASS selectors
714 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
715
716 rsibling = /[+~]/,
717 rescape = /'|\\/g,
718
719 // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
720 runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
721 funescape = function( _, escaped, escapedWhitespace ) {
722 var high = "0x" + escaped - 0x10000;
723 // NaN means non-codepoint
724 // Support: Firefox<24
725 // Workaround erroneous numeric interpretation of +"0x"
726 return high !== high || escapedWhitespace ?
727 escaped :
728 high < 0 ?
729 // BMP codepoint
730 String.fromCharCode( high + 0x10000 ) :
731 // Supplemental Plane codepoint (surrogate pair)
732 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
733 },
734
735 // Used for iframes
736 // See setDocument()
737 // Removing the function wrapper causes a "Permission Denied"
738 // error in IE
739 unloadHandler = function() {
740 setDocument();
741 };
742
743// Optimize for push.apply( _, NodeList )
744try {
745 push.apply(
746 (arr = slice.call( preferredDoc.childNodes )),
747 preferredDoc.childNodes
748 );
749 // Support: Android<4.0
750 // Detect silently failing push.apply
751 arr[ preferredDoc.childNodes.length ].nodeType;
752} catch ( e ) {
753 push = { apply: arr.length ?
754
755 // Leverage slice if possible
756 function( target, els ) {
757 push_native.apply( target, slice.call(els) );
758 } :
759
760 // Support: IE<9
761 // Otherwise append directly
762 function( target, els ) {
763 var j = target.length,
764 i = 0;
765 // Can't trust NodeList.length
766 while ( (target[j++] = els[i++]) ) {}
767 target.length = j - 1;
768 }
769 };
770}
771
772function Sizzle( selector, context, results, seed ) {
773 var m, i, elem, nid, nidselect, match, groups, newSelector,
774 newContext = context && context.ownerDocument,
775
776 // nodeType defaults to 9, since context defaults to document
777 nodeType = context ? context.nodeType : 9;
778
779 results = results || [];
780
781 // Return early from calls with invalid selector or context
782 if ( typeof selector !== "string" || !selector ||
783 nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
784
785 return results;
786 }
787
788 // Try to shortcut find operations (as opposed to filters) in HTML documents
789 if ( !seed ) {
790
791 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
792 setDocument( context );
793 }
794 context = context || document;
795
796 if ( documentIsHTML ) {
797
798 // If the selector is sufficiently simple, try using a "get*By*" DOM method
799 // (excepting DocumentFragment context, where the methods don't exist)
800 if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
801
802 // ID selector
803 if ( (m = match[1]) ) {
804
805 // Document context
806 if ( nodeType === 9 ) {
807 if ( (elem = context.getElementById( m )) ) {
808
809 // Support: IE, Opera, Webkit
810 // TODO: identify versions
811 // getElementById can match elements by name instead of ID
812 if ( elem.id === m ) {
813 results.push( elem );
814 return results;
815 }
816 } else {
817 return results;
818 }
819
820 // Element context
821 } else {
822
823 // Support: IE, Opera, Webkit
824 // TODO: identify versions
825 // getElementById can match elements by name instead of ID
826 if ( newContext && (elem = newContext.getElementById( m )) &&
827 contains( context, elem ) &&
828 elem.id === m ) {
829
830 results.push( elem );
831 return results;
832 }
833 }
834
835 // Type selector
836 } else if ( match[2] ) {
837 push.apply( results, context.getElementsByTagName( selector ) );
838 return results;
839
840 // Class selector
841 } else if ( (m = match[3]) && support.getElementsByClassName &&
842 context.getElementsByClassName ) {
843
844 push.apply( results, context.getElementsByClassName( m ) );
845 return results;
846 }
847 }
848
849 // Take advantage of querySelectorAll
850 if ( support.qsa &&
851 !compilerCache[ selector + " " ] &&
852 (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
853
854 if ( nodeType !== 1 ) {
855 newContext = context;
856 newSelector = selector;
857
858 // qSA looks outside Element context, which is not what we want
859 // Thanks to Andrew Dupont for this workaround technique
860 // Support: IE <=8
861 // Exclude object elements
862 } else if ( context.nodeName.toLowerCase() !== "object" ) {
863
864 // Capture the context ID, setting it first if necessary
865 if ( (nid = context.getAttribute( "id" )) ) {
866 nid = nid.replace( rescape, "\\$&" );
867 } else {
868 context.setAttribute( "id", (nid = expando) );
869 }
870
871 // Prefix every selector in the list
872 groups = tokenize( selector );
873 i = groups.length;
874 nidselect = ridentifier.test( nid ) ? "#" + nid : "[id='" + nid + "']";
875 while ( i-- ) {
876 groups[i] = nidselect + " " + toSelector( groups[i] );
877 }
878 newSelector = groups.join( "," );
879
880 // Expand context for sibling selectors
881 newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
882 context;
883 }
884
885 if ( newSelector ) {
886 try {
887 push.apply( results,
888 newContext.querySelectorAll( newSelector )
889 );
890 return results;
891 } catch ( qsaError ) {
892 } finally {
893 if ( nid === expando ) {
894 context.removeAttribute( "id" );
895 }
896 }
897 }
898 }
899 }
900 }
901
902 // All others
903 return select( selector.replace( rtrim, "$1" ), context, results, seed );
904}
905
906/**
907 * Create key-value caches of limited size
908 * @returns {function(string, object)} Returns the Object data after storing it on itself with
909 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
910 * deleting the oldest entry
911 */
912function createCache() {
913 var keys = [];
914
915 function cache( key, value ) {
916 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
917 if ( keys.push( key + " " ) > Expr.cacheLength ) {
918 // Only keep the most recent entries
919 delete cache[ keys.shift() ];
920 }
921 return (cache[ key + " " ] = value);
922 }
923 return cache;
924}
925
926/**
927 * Mark a function for special use by Sizzle
928 * @param {Function} fn The function to mark
929 */
930function markFunction( fn ) {
931 fn[ expando ] = true;
932 return fn;
933}
934
935/**
936 * Support testing using an element
937 * @param {Function} fn Passed the created div and expects a boolean result
938 */
939function assert( fn ) {
940 var div = document.createElement("div");
941
942 try {
943 return !!fn( div );
944 } catch (e) {
945 return false;
946 } finally {
947 // Remove from its parent by default
948 if ( div.parentNode ) {
949 div.parentNode.removeChild( div );
950 }
951 // release memory in IE
952 div = null;
953 }
954}
955
956/**
957 * Adds the same handler for all of the specified attrs
958 * @param {String} attrs Pipe-separated list of attributes
959 * @param {Function} handler The method that will be applied
960 */
961function addHandle( attrs, handler ) {
962 var arr = attrs.split("|"),
963 i = arr.length;
964
965 while ( i-- ) {
966 Expr.attrHandle[ arr[i] ] = handler;
967 }
968}
969
970/**
971 * Checks document order of two siblings
972 * @param {Element} a
973 * @param {Element} b
974 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
975 */
976function siblingCheck( a, b ) {
977 var cur = b && a,
978 diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
979 ( ~b.sourceIndex || MAX_NEGATIVE ) -
980 ( ~a.sourceIndex || MAX_NEGATIVE );
981
982 // Use IE sourceIndex if available on both nodes
983 if ( diff ) {
984 return diff;
985 }
986
987 // Check if b follows a
988 if ( cur ) {
989 while ( (cur = cur.nextSibling) ) {
990 if ( cur === b ) {
991 return -1;
992 }
993 }
994 }
995
996 return a ? 1 : -1;
997}
998
999/**
1000 * Returns a function to use in pseudos for input types
1001 * @param {String} type
1002 */
1003function createInputPseudo( type ) {
1004 return function( elem ) {
1005 var name = elem.nodeName.toLowerCase();
1006 return name === "input" && elem.type === type;
1007 };
1008}
1009
1010/**
1011 * Returns a function to use in pseudos for buttons
1012 * @param {String} type
1013 */
1014function createButtonPseudo( type ) {
1015 return function( elem ) {
1016 var name = elem.nodeName.toLowerCase();
1017 return (name === "input" || name === "button") && elem.type === type;
1018 };
1019}
1020
1021/**
1022 * Returns a function to use in pseudos for positionals
1023 * @param {Function} fn
1024 */
1025function createPositionalPseudo( fn ) {
1026 return markFunction(function( argument ) {
1027 argument = +argument;
1028 return markFunction(function( seed, matches ) {
1029 var j,
1030 matchIndexes = fn( [], seed.length, argument ),
1031 i = matchIndexes.length;
1032
1033 // Match elements found at the specified indexes
1034 while ( i-- ) {
1035 if ( seed[ (j = matchIndexes[i]) ] ) {
1036 seed[j] = !(matches[j] = seed[j]);
1037 }
1038 }
1039 });
1040 });
1041}
1042
1043/**
1044 * Checks a node for validity as a Sizzle context
1045 * @param {Element|Object=} context
1046 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
1047 */
1048function testContext( context ) {
1049 return context && typeof context.getElementsByTagName !== "undefined" && context;
1050}
1051
1052// Expose support vars for convenience
1053support = Sizzle.support = {};
1054
1055/**
1056 * Detects XML nodes
1057 * @param {Element|Object} elem An element or a document
1058 * @returns {Boolean} True iff elem is a non-HTML XML node
1059 */
1060isXML = Sizzle.isXML = function( elem ) {
1061 // documentElement is verified for cases where it doesn't yet exist
1062 // (such as loading iframes in IE - #4833)
1063 var documentElement = elem && (elem.ownerDocument || elem).documentElement;
1064 return documentElement ? documentElement.nodeName !== "HTML" : false;
1065};
1066
1067/**
1068 * Sets document-related variables once based on the current document
1069 * @param {Element|Object} [doc] An element or document object to use to set the document
1070 * @returns {Object} Returns the current document
1071 */
1072setDocument = Sizzle.setDocument = function( node ) {
1073 var hasCompare, parent,
1074 doc = node ? node.ownerDocument || node : preferredDoc;
1075
1076 // Return early if doc is invalid or already selected
1077 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
1078 return document;
1079 }
1080
1081 // Update global variables
1082 document = doc;
1083 docElem = document.documentElement;
1084 documentIsHTML = !isXML( document );
1085
1086 // Support: IE 9-11, Edge
1087 // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
1088 if ( (parent = document.defaultView) && parent.top !== parent ) {
1089 // Support: IE 11
1090 if ( parent.addEventListener ) {
1091 parent.addEventListener( "unload", unloadHandler, false );
1092
1093 // Support: IE 9 - 10 only
1094 } else if ( parent.attachEvent ) {
1095 parent.attachEvent( "onunload", unloadHandler );
1096 }
1097 }
1098
1099 /* Attributes
1100 ---------------------------------------------------------------------- */
1101
1102 // Support: IE<8
1103 // Verify that getAttribute really returns attributes and not properties
1104 // (excepting IE8 booleans)
1105 support.attributes = assert(function( div ) {
1106 div.className = "i";
1107 return !div.getAttribute("className");
1108 });
1109
1110 /* getElement(s)By*
1111 ---------------------------------------------------------------------- */
1112
1113 // Check if getElementsByTagName("*") returns only elements
1114 support.getElementsByTagName = assert(function( div ) {
1115 div.appendChild( document.createComment("") );
1116 return !div.getElementsByTagName("*").length;
1117 });
1118
1119 // Support: IE<9
1120 support.getElementsByClassName = rnative.test( document.getElementsByClassName );
1121
1122 // Support: IE<10
1123 // Check if getElementById returns elements by name
1124 // The broken getElementById methods don't pick up programatically-set names,
1125 // so use a roundabout getElementsByName test
1126 support.getById = assert(function( div ) {
1127 docElem.appendChild( div ).id = expando;
1128 return !document.getElementsByName || !document.getElementsByName( expando ).length;
1129 });
1130
1131 // ID find and filter
1132 if ( support.getById ) {
1133 Expr.find["ID"] = function( id, context ) {
1134 if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
1135 var m = context.getElementById( id );
1136 return m ? [ m ] : [];
1137 }
1138 };
1139 Expr.filter["ID"] = function( id ) {
1140 var attrId = id.replace( runescape, funescape );
1141 return function( elem ) {
1142 return elem.getAttribute("id") === attrId;
1143 };
1144 };
1145 } else {
1146 // Support: IE6/7
1147 // getElementById is not reliable as a find shortcut
1148 delete Expr.find["ID"];
1149
1150 Expr.filter["ID"] = function( id ) {
1151 var attrId = id.replace( runescape, funescape );
1152 return function( elem ) {
1153 var node = typeof elem.getAttributeNode !== "undefined" &&
1154 elem.getAttributeNode("id");
1155 return node && node.value === attrId;
1156 };
1157 };
1158 }
1159
1160 // Tag
1161 Expr.find["TAG"] = support.getElementsByTagName ?
1162 function( tag, context ) {
1163 if ( typeof context.getElementsByTagName !== "undefined" ) {
1164 return context.getElementsByTagName( tag );
1165
1166 // DocumentFragment nodes don't have gEBTN
1167 } else if ( support.qsa ) {
1168 return context.querySelectorAll( tag );
1169 }
1170 } :
1171
1172 function( tag, context ) {
1173 var elem,
1174 tmp = [],
1175 i = 0,
1176 // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
1177 results = context.getElementsByTagName( tag );
1178
1179 // Filter out possible comments
1180 if ( tag === "*" ) {
1181 while ( (elem = results[i++]) ) {
1182 if ( elem.nodeType === 1 ) {
1183 tmp.push( elem );
1184 }
1185 }
1186
1187 return tmp;
1188 }
1189 return results;
1190 };
1191
1192 // Class
1193 Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
1194 if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
1195 return context.getElementsByClassName( className );
1196 }
1197 };
1198
1199 /* QSA/matchesSelector
1200 ---------------------------------------------------------------------- */
1201
1202 // QSA and matchesSelector support
1203
1204 // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
1205 rbuggyMatches = [];
1206
1207 // qSa(:focus) reports false when true (Chrome 21)
1208 // We allow this because of a bug in IE8/9 that throws an error
1209 // whenever `document.activeElement` is accessed on an iframe
1210 // So, we allow :focus to pass through QSA all the time to avoid the IE error
1211 // See http://bugs.jquery.com/ticket/13378
1212 rbuggyQSA = [];
1213
1214 if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
1215 // Build QSA regex
1216 // Regex strategy adopted from Diego Perini
1217 assert(function( div ) {
1218 // Select is set to empty string on purpose
1219 // This is to test IE's treatment of not explicitly
1220 // setting a boolean content attribute,
1221 // since its presence should be enough
1222 // http://bugs.jquery.com/ticket/12359
1223 docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
1224 "<select id='" + expando + "-\r\\' msallowcapture=''>" +
1225 "<option selected=''></option></select>";
1226
1227 // Support: IE8, Opera 11-12.16
1228 // Nothing should be selected when empty strings follow ^= or $= or *=
1229 // The test attribute must be unknown in Opera but "safe" for WinRT
1230 // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
1231 if ( div.querySelectorAll("[msallowcapture^='']").length ) {
1232 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
1233 }
1234
1235 // Support: IE8
1236 // Boolean attributes and "value" are not treated correctly
1237 if ( !div.querySelectorAll("[selected]").length ) {
1238 rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
1239 }
1240
1241 // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
1242 if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
1243 rbuggyQSA.push("~=");
1244 }
1245
1246 // Webkit/Opera - :checked should return selected option elements
1247 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1248 // IE8 throws error here and will not see later tests
1249 if ( !div.querySelectorAll(":checked").length ) {
1250 rbuggyQSA.push(":checked");
1251 }
1252
1253 // Support: Safari 8+, iOS 8+
1254 // https://bugs.webkit.org/show_bug.cgi?id=136851
1255 // In-page `selector#id sibing-combinator selector` fails
1256 if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
1257 rbuggyQSA.push(".#.+[+~]");
1258 }
1259 });
1260
1261 assert(function( div ) {
1262 // Support: Windows 8 Native Apps
1263 // The type and name attributes are restricted during .innerHTML assignment
1264 var input = document.createElement("input");
1265 input.setAttribute( "type", "hidden" );
1266 div.appendChild( input ).setAttribute( "name", "D" );
1267
1268 // Support: IE8
1269 // Enforce case-sensitivity of name attribute
1270 if ( div.querySelectorAll("[name=d]").length ) {
1271 rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
1272 }
1273
1274 // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
1275 // IE8 throws error here and will not see later tests
1276 if ( !div.querySelectorAll(":enabled").length ) {
1277 rbuggyQSA.push( ":enabled", ":disabled" );
1278 }
1279
1280 // Opera 10-11 does not throw on post-comma invalid pseudos
1281 div.querySelectorAll("*,:x");
1282 rbuggyQSA.push(",.*:");
1283 });
1284 }
1285
1286 if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
1287 docElem.webkitMatchesSelector ||
1288 docElem.mozMatchesSelector ||
1289 docElem.oMatchesSelector ||
1290 docElem.msMatchesSelector) )) ) {
1291
1292 assert(function( div ) {
1293 // Check to see if it's possible to do matchesSelector
1294 // on a disconnected node (IE 9)
1295 support.disconnectedMatch = matches.call( div, "div" );
1296
1297 // This should fail with an exception
1298 // Gecko does not error, returns false instead
1299 matches.call( div, "[s!='']:x" );
1300 rbuggyMatches.push( "!=", pseudos );
1301 });
1302 }
1303
1304 rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
1305 rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
1306
1307 /* Contains
1308 ---------------------------------------------------------------------- */
1309 hasCompare = rnative.test( docElem.compareDocumentPosition );
1310
1311 // Element contains another
1312 // Purposefully self-exclusive
1313 // As in, an element does not contain itself
1314 contains = hasCompare || rnative.test( docElem.contains ) ?
1315 function( a, b ) {
1316 var adown = a.nodeType === 9 ? a.documentElement : a,
1317 bup = b && b.parentNode;
1318 return a === bup || !!( bup && bup.nodeType === 1 && (
1319 adown.contains ?
1320 adown.contains( bup ) :
1321 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
1322 ));
1323 } :
1324 function( a, b ) {
1325 if ( b ) {
1326 while ( (b = b.parentNode) ) {
1327 if ( b === a ) {
1328 return true;
1329 }
1330 }
1331 }
1332 return false;
1333 };
1334
1335 /* Sorting
1336 ---------------------------------------------------------------------- */
1337
1338 // Document order sorting
1339 sortOrder = hasCompare ?
1340 function( a, b ) {
1341
1342 // Flag for duplicate removal
1343 if ( a === b ) {
1344 hasDuplicate = true;
1345 return 0;
1346 }
1347
1348 // Sort on method existence if only one input has compareDocumentPosition
1349 var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
1350 if ( compare ) {
1351 return compare;
1352 }
1353
1354 // Calculate position if both inputs belong to the same document
1355 compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
1356 a.compareDocumentPosition( b ) :
1357
1358 // Otherwise we know they are disconnected
1359 1;
1360
1361 // Disconnected nodes
1362 if ( compare & 1 ||
1363 (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
1364
1365 // Choose the first element that is related to our preferred document
1366 if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
1367 return -1;
1368 }
1369 if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
1370 return 1;
1371 }
1372
1373 // Maintain original order
1374 return sortInput ?
1375 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1376 0;
1377 }
1378
1379 return compare & 4 ? -1 : 1;
1380 } :
1381 function( a, b ) {
1382 // Exit early if the nodes are identical
1383 if ( a === b ) {
1384 hasDuplicate = true;
1385 return 0;
1386 }
1387
1388 var cur,
1389 i = 0,
1390 aup = a.parentNode,
1391 bup = b.parentNode,
1392 ap = [ a ],
1393 bp = [ b ];
1394
1395 // Parentless nodes are either documents or disconnected
1396 if ( !aup || !bup ) {
1397 return a === document ? -1 :
1398 b === document ? 1 :
1399 aup ? -1 :
1400 bup ? 1 :
1401 sortInput ?
1402 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1403 0;
1404
1405 // If the nodes are siblings, we can do a quick check
1406 } else if ( aup === bup ) {
1407 return siblingCheck( a, b );
1408 }
1409
1410 // Otherwise we need full lists of their ancestors for comparison
1411 cur = a;
1412 while ( (cur = cur.parentNode) ) {
1413 ap.unshift( cur );
1414 }
1415 cur = b;
1416 while ( (cur = cur.parentNode) ) {
1417 bp.unshift( cur );
1418 }
1419
1420 // Walk down the tree looking for a discrepancy
1421 while ( ap[i] === bp[i] ) {
1422 i++;
1423 }
1424
1425 return i ?
1426 // Do a sibling check if the nodes have a common ancestor
1427 siblingCheck( ap[i], bp[i] ) :
1428
1429 // Otherwise nodes in our document sort first
1430 ap[i] === preferredDoc ? -1 :
1431 bp[i] === preferredDoc ? 1 :
1432 0;
1433 };
1434
1435 return document;
1436};
1437
1438Sizzle.matches = function( expr, elements ) {
1439 return Sizzle( expr, null, null, elements );
1440};
1441
1442Sizzle.matchesSelector = function( elem, expr ) {
1443 // Set document vars if needed
1444 if ( ( elem.ownerDocument || elem ) !== document ) {
1445 setDocument( elem );
1446 }
1447
1448 // Make sure that attribute selectors are quoted
1449 expr = expr.replace( rattributeQuotes, "='$1']" );
1450
1451 if ( support.matchesSelector && documentIsHTML &&
1452 !compilerCache[ expr + " " ] &&
1453 ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
1454 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
1455
1456 try {
1457 var ret = matches.call( elem, expr );
1458
1459 // IE 9's matchesSelector returns false on disconnected nodes
1460 if ( ret || support.disconnectedMatch ||
1461 // As well, disconnected nodes are said to be in a document
1462 // fragment in IE 9
1463 elem.document && elem.document.nodeType !== 11 ) {
1464 return ret;
1465 }
1466 } catch (e) {}
1467 }
1468
1469 return Sizzle( expr, document, null, [ elem ] ).length > 0;
1470};
1471
1472Sizzle.contains = function( context, elem ) {
1473 // Set document vars if needed
1474 if ( ( context.ownerDocument || context ) !== document ) {
1475 setDocument( context );
1476 }
1477 return contains( context, elem );
1478};
1479
1480Sizzle.attr = function( elem, name ) {
1481 // Set document vars if needed
1482 if ( ( elem.ownerDocument || elem ) !== document ) {
1483 setDocument( elem );
1484 }
1485
1486 var fn = Expr.attrHandle[ name.toLowerCase() ],
1487 // Don't get fooled by Object.prototype properties (jQuery #13807)
1488 val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
1489 fn( elem, name, !documentIsHTML ) :
1490 undefined;
1491
1492 return val !== undefined ?
1493 val :
1494 support.attributes || !documentIsHTML ?
1495 elem.getAttribute( name ) :
1496 (val = elem.getAttributeNode(name)) && val.specified ?
1497 val.value :
1498 null;
1499};
1500
1501Sizzle.error = function( msg ) {
1502 throw new Error( "Syntax error, unrecognized expression: " + msg );
1503};
1504
1505/**
1506 * Document sorting and removing duplicates
1507 * @param {ArrayLike} results
1508 */
1509Sizzle.uniqueSort = function( results ) {
1510 var elem,
1511 duplicates = [],
1512 j = 0,
1513 i = 0;
1514
1515 // Unless we *know* we can detect duplicates, assume their presence
1516 hasDuplicate = !support.detectDuplicates;
1517 sortInput = !support.sortStable && results.slice( 0 );
1518 results.sort( sortOrder );
1519
1520 if ( hasDuplicate ) {
1521 while ( (elem = results[i++]) ) {
1522 if ( elem === results[ i ] ) {
1523 j = duplicates.push( i );
1524 }
1525 }
1526 while ( j-- ) {
1527 results.splice( duplicates[ j ], 1 );
1528 }
1529 }
1530
1531 // Clear input after sorting to release objects
1532 // See https://github.com/jquery/sizzle/pull/225
1533 sortInput = null;
1534
1535 return results;
1536};
1537
1538/**
1539 * Utility function for retrieving the text value of an array of DOM nodes
1540 * @param {Array|Element} elem
1541 */
1542getText = Sizzle.getText = function( elem ) {
1543 var node,
1544 ret = "",
1545 i = 0,
1546 nodeType = elem.nodeType;
1547
1548 if ( !nodeType ) {
1549 // If no nodeType, this is expected to be an array
1550 while ( (node = elem[i++]) ) {
1551 // Do not traverse comment nodes
1552 ret += getText( node );
1553 }
1554 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
1555 // Use textContent for elements
1556 // innerText usage removed for consistency of new lines (jQuery #11153)
1557 if ( typeof elem.textContent === "string" ) {
1558 return elem.textContent;
1559 } else {
1560 // Traverse its children
1561 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1562 ret += getText( elem );
1563 }
1564 }
1565 } else if ( nodeType === 3 || nodeType === 4 ) {
1566 return elem.nodeValue;
1567 }
1568 // Do not include comment or processing instruction nodes
1569
1570 return ret;
1571};
1572
1573Expr = Sizzle.selectors = {
1574
1575 // Can be adjusted by the user
1576 cacheLength: 50,
1577
1578 createPseudo: markFunction,
1579
1580 match: matchExpr,
1581
1582 attrHandle: {},
1583
1584 find: {},
1585
1586 relative: {
1587 ">": { dir: "parentNode", first: true },
1588 " ": { dir: "parentNode" },
1589 "+": { dir: "previousSibling", first: true },
1590 "~": { dir: "previousSibling" }
1591 },
1592
1593 preFilter: {
1594 "ATTR": function( match ) {
1595 match[1] = match[1].replace( runescape, funescape );
1596
1597 // Move the given value to match[3] whether quoted or unquoted
1598 match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
1599
1600 if ( match[2] === "~=" ) {
1601 match[3] = " " + match[3] + " ";
1602 }
1603
1604 return match.slice( 0, 4 );
1605 },
1606
1607 "CHILD": function( match ) {
1608 /* matches from matchExpr["CHILD"]
1609 1 type (only|nth|...)
1610 2 what (child|of-type)
1611 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
1612 4 xn-component of xn+y argument ([+-]?\d*n|)
1613 5 sign of xn-component
1614 6 x of xn-component
1615 7 sign of y-component
1616 8 y of y-component
1617 */
1618 match[1] = match[1].toLowerCase();
1619
1620 if ( match[1].slice( 0, 3 ) === "nth" ) {
1621 // nth-* requires argument
1622 if ( !match[3] ) {
1623 Sizzle.error( match[0] );
1624 }
1625
1626 // numeric x and y parameters for Expr.filter.CHILD
1627 // remember that false/true cast respectively to 0/1
1628 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
1629 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
1630
1631 // other types prohibit arguments
1632 } else if ( match[3] ) {
1633 Sizzle.error( match[0] );
1634 }
1635
1636 return match;
1637 },
1638
1639 "PSEUDO": function( match ) {
1640 var excess,
1641 unquoted = !match[6] && match[2];
1642
1643 if ( matchExpr["CHILD"].test( match[0] ) ) {
1644 return null;
1645 }
1646
1647 // Accept quoted arguments as-is
1648 if ( match[3] ) {
1649 match[2] = match[4] || match[5] || "";
1650
1651 // Strip excess characters from unquoted arguments
1652 } else if ( unquoted && rpseudo.test( unquoted ) &&
1653 // Get excess from tokenize (recursively)
1654 (excess = tokenize( unquoted, true )) &&
1655 // advance to the next closing parenthesis
1656 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
1657
1658 // excess is a negative index
1659 match[0] = match[0].slice( 0, excess );
1660 match[2] = unquoted.slice( 0, excess );
1661 }
1662
1663 // Return only captures needed by the pseudo filter method (type and argument)
1664 return match.slice( 0, 3 );
1665 }
1666 },
1667
1668 filter: {
1669
1670 "TAG": function( nodeNameSelector ) {
1671 var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
1672 return nodeNameSelector === "*" ?
1673 function() { return true; } :
1674 function( elem ) {
1675 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
1676 };
1677 },
1678
1679 "CLASS": function( className ) {
1680 var pattern = classCache[ className + " " ];
1681
1682 return pattern ||
1683 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
1684 classCache( className, function( elem ) {
1685 return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
1686 });
1687 },
1688
1689 "ATTR": function( name, operator, check ) {
1690 return function( elem ) {
1691 var result = Sizzle.attr( elem, name );
1692
1693 if ( result == null ) {
1694 return operator === "!=";
1695 }
1696 if ( !operator ) {
1697 return true;
1698 }
1699
1700 result += "";
1701
1702 return operator === "=" ? result === check :
1703 operator === "!=" ? result !== check :
1704 operator === "^=" ? check && result.indexOf( check ) === 0 :
1705 operator === "*=" ? check && result.indexOf( check ) > -1 :
1706 operator === "$=" ? check && result.slice( -check.length ) === check :
1707 operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
1708 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
1709 false;
1710 };
1711 },
1712
1713 "CHILD": function( type, what, argument, first, last ) {
1714 var simple = type.slice( 0, 3 ) !== "nth",
1715 forward = type.slice( -4 ) !== "last",
1716 ofType = what === "of-type";
1717
1718 return first === 1 && last === 0 ?
1719
1720 // Shortcut for :nth-*(n)
1721 function( elem ) {
1722 return !!elem.parentNode;
1723 } :
1724
1725 function( elem, context, xml ) {
1726 var cache, uniqueCache, outerCache, node, nodeIndex, start,
1727 dir = simple !== forward ? "nextSibling" : "previousSibling",
1728 parent = elem.parentNode,
1729 name = ofType && elem.nodeName.toLowerCase(),
1730 useCache = !xml && !ofType,
1731 diff = false;
1732
1733 if ( parent ) {
1734
1735 // :(first|last|only)-(child|of-type)
1736 if ( simple ) {
1737 while ( dir ) {
1738 node = elem;
1739 while ( (node = node[ dir ]) ) {
1740 if ( ofType ?
1741 node.nodeName.toLowerCase() === name :
1742 node.nodeType === 1 ) {
1743
1744 return false;
1745 }
1746 }
1747 // Reverse direction for :only-* (if we haven't yet done so)
1748 start = dir = type === "only" && !start && "nextSibling";
1749 }
1750 return true;
1751 }
1752
1753 start = [ forward ? parent.firstChild : parent.lastChild ];
1754
1755 // non-xml :nth-child(...) stores cache data on `parent`
1756 if ( forward && useCache ) {
1757
1758 // Seek `elem` from a previously-cached index
1759
1760 // ...in a gzip-friendly way
1761 node = parent;
1762 outerCache = node[ expando ] || (node[ expando ] = {});
1763
1764 // Support: IE <9 only
1765 // Defend against cloned attroperties (jQuery gh-1709)
1766 uniqueCache = outerCache[ node.uniqueID ] ||
1767 (outerCache[ node.uniqueID ] = {});
1768
1769 cache = uniqueCache[ type ] || [];
1770 nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
1771 diff = nodeIndex && cache[ 2 ];
1772 node = nodeIndex && parent.childNodes[ nodeIndex ];
1773
1774 while ( (node = ++nodeIndex && node && node[ dir ] ||
1775
1776 // Fallback to seeking `elem` from the start
1777 (diff = nodeIndex = 0) || start.pop()) ) {
1778
1779 // When found, cache indexes on `parent` and break
1780 if ( node.nodeType === 1 && ++diff && node === elem ) {
1781 uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
1782 break;
1783 }
1784 }
1785
1786 } else {
1787 // Use previously-cached element index if available
1788 if ( useCache ) {
1789 // ...in a gzip-friendly way
1790 node = elem;
1791 outerCache = node[ expando ] || (node[ expando ] = {});
1792
1793 // Support: IE <9 only
1794 // Defend against cloned attroperties (jQuery gh-1709)
1795 uniqueCache = outerCache[ node.uniqueID ] ||
1796 (outerCache[ node.uniqueID ] = {});
1797
1798 cache = uniqueCache[ type ] || [];
1799 nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
1800 diff = nodeIndex;
1801 }
1802
1803 // xml :nth-child(...)
1804 // or :nth-last-child(...) or :nth(-last)?-of-type(...)
1805 if ( diff === false ) {
1806 // Use the same loop as above to seek `elem` from the start
1807 while ( (node = ++nodeIndex && node && node[ dir ] ||
1808 (diff = nodeIndex = 0) || start.pop()) ) {
1809
1810 if ( ( ofType ?
1811 node.nodeName.toLowerCase() === name :
1812 node.nodeType === 1 ) &&
1813 ++diff ) {
1814
1815 // Cache the index of each encountered element
1816 if ( useCache ) {
1817 outerCache = node[ expando ] || (node[ expando ] = {});
1818
1819 // Support: IE <9 only
1820 // Defend against cloned attroperties (jQuery gh-1709)
1821 uniqueCache = outerCache[ node.uniqueID ] ||
1822 (outerCache[ node.uniqueID ] = {});
1823
1824 uniqueCache[ type ] = [ dirruns, diff ];
1825 }
1826
1827 if ( node === elem ) {
1828 break;
1829 }
1830 }
1831 }
1832 }
1833 }
1834
1835 // Incorporate the offset, then check against cycle size
1836 diff -= last;
1837 return diff === first || ( diff % first === 0 && diff / first >= 0 );
1838 }
1839 };
1840 },
1841
1842 "PSEUDO": function( pseudo, argument ) {
1843 // pseudo-class names are case-insensitive
1844 // http://www.w3.org/TR/selectors/#pseudo-classes
1845 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
1846 // Remember that setFilters inherits from pseudos
1847 var args,
1848 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
1849 Sizzle.error( "unsupported pseudo: " + pseudo );
1850
1851 // The user may use createPseudo to indicate that
1852 // arguments are needed to create the filter function
1853 // just as Sizzle does
1854 if ( fn[ expando ] ) {
1855 return fn( argument );
1856 }
1857
1858 // But maintain support for old signatures
1859 if ( fn.length > 1 ) {
1860 args = [ pseudo, pseudo, "", argument ];
1861 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
1862 markFunction(function( seed, matches ) {
1863 var idx,
1864 matched = fn( seed, argument ),
1865 i = matched.length;
1866 while ( i-- ) {
1867 idx = indexOf( seed, matched[i] );
1868 seed[ idx ] = !( matches[ idx ] = matched[i] );
1869 }
1870 }) :
1871 function( elem ) {
1872 return fn( elem, 0, args );
1873 };
1874 }
1875
1876 return fn;
1877 }
1878 },
1879
1880 pseudos: {
1881 // Potentially complex pseudos
1882 "not": markFunction(function( selector ) {
1883 // Trim the selector passed to compile
1884 // to avoid treating leading and trailing
1885 // spaces as combinators
1886 var input = [],
1887 results = [],
1888 matcher = compile( selector.replace( rtrim, "$1" ) );
1889
1890 return matcher[ expando ] ?
1891 markFunction(function( seed, matches, context, xml ) {
1892 var elem,
1893 unmatched = matcher( seed, null, xml, [] ),
1894 i = seed.length;
1895
1896 // Match elements unmatched by `matcher`
1897 while ( i-- ) {
1898 if ( (elem = unmatched[i]) ) {
1899 seed[i] = !(matches[i] = elem);
1900 }
1901 }
1902 }) :
1903 function( elem, context, xml ) {
1904 input[0] = elem;
1905 matcher( input, null, xml, results );
1906 // Don't keep the element (issue #299)
1907 input[0] = null;
1908 return !results.pop();
1909 };
1910 }),
1911
1912 "has": markFunction(function( selector ) {
1913 return function( elem ) {
1914 return Sizzle( selector, elem ).length > 0;
1915 };
1916 }),
1917
1918 "contains": markFunction(function( text ) {
1919 text = text.replace( runescape, funescape );
1920 return function( elem ) {
1921 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
1922 };
1923 }),
1924
1925 // "Whether an element is represented by a :lang() selector
1926 // is based solely on the element's language value
1927 // being equal to the identifier C,
1928 // or beginning with the identifier C immediately followed by "-".
1929 // The matching of C against the element's language value is performed case-insensitively.
1930 // The identifier C does not have to be a valid language name."
1931 // http://www.w3.org/TR/selectors/#lang-pseudo
1932 "lang": markFunction( function( lang ) {
1933 // lang value must be a valid identifier
1934 if ( !ridentifier.test(lang || "") ) {
1935 Sizzle.error( "unsupported lang: " + lang );
1936 }
1937 lang = lang.replace( runescape, funescape ).toLowerCase();
1938 return function( elem ) {
1939 var elemLang;
1940 do {
1941 if ( (elemLang = documentIsHTML ?
1942 elem.lang :
1943 elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
1944
1945 elemLang = elemLang.toLowerCase();
1946 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
1947 }
1948 } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
1949 return false;
1950 };
1951 }),
1952
1953 // Miscellaneous
1954 "target": function( elem ) {
1955 var hash = window.location && window.location.hash;
1956 return hash && hash.slice( 1 ) === elem.id;
1957 },
1958
1959 "root": function( elem ) {
1960 return elem === docElem;
1961 },
1962
1963 "focus": function( elem ) {
1964 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
1965 },
1966
1967 // Boolean properties
1968 "enabled": function( elem ) {
1969 return elem.disabled === false;
1970 },
1971
1972 "disabled": function( elem ) {
1973 return elem.disabled === true;
1974 },
1975
1976 "checked": function( elem ) {
1977 // In CSS3, :checked should return both checked and selected elements
1978 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1979 var nodeName = elem.nodeName.toLowerCase();
1980 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
1981 },
1982
1983 "selected": function( elem ) {
1984 // Accessing this property makes selected-by-default
1985 // options in Safari work properly
1986 if ( elem.parentNode ) {
1987 elem.parentNode.selectedIndex;
1988 }
1989
1990 return elem.selected === true;
1991 },
1992
1993 // Contents
1994 "empty": function( elem ) {
1995 // http://www.w3.org/TR/selectors/#empty-pseudo
1996 // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
1997 // but not by others (comment: 8; processing instruction: 7; etc.)
1998 // nodeType < 6 works because attributes (2) do not appear as children
1999 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
2000 if ( elem.nodeType < 6 ) {
2001 return false;
2002 }
2003 }
2004 return true;
2005 },
2006
2007 "parent": function( elem ) {
2008 return !Expr.pseudos["empty"]( elem );
2009 },
2010
2011 // Element/input types
2012 "header": function( elem ) {
2013 return rheader.test( elem.nodeName );
2014 },
2015
2016 "input": function( elem ) {
2017 return rinputs.test( elem.nodeName );
2018 },
2019
2020 "button": function( elem ) {
2021 var name = elem.nodeName.toLowerCase();
2022 return name === "input" && elem.type === "button" || name === "button";
2023 },
2024
2025 "text": function( elem ) {
2026 var attr;
2027 return elem.nodeName.toLowerCase() === "input" &&
2028 elem.type === "text" &&
2029
2030 // Support: IE<8
2031 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
2032 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
2033 },
2034
2035 // Position-in-collection
2036 "first": createPositionalPseudo(function() {
2037 return [ 0 ];
2038 }),
2039
2040 "last": createPositionalPseudo(function( matchIndexes, length ) {
2041 return [ length - 1 ];
2042 }),
2043
2044 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
2045 return [ argument < 0 ? argument + length : argument ];
2046 }),
2047
2048 "even": createPositionalPseudo(function( matchIndexes, length ) {
2049 var i = 0;
2050 for ( ; i < length; i += 2 ) {
2051 matchIndexes.push( i );
2052 }
2053 return matchIndexes;
2054 }),
2055
2056 "odd": createPositionalPseudo(function( matchIndexes, length ) {
2057 var i = 1;
2058 for ( ; i < length; i += 2 ) {
2059 matchIndexes.push( i );
2060 }
2061 return matchIndexes;
2062 }),
2063
2064 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2065 var i = argument < 0 ? argument + length : argument;
2066 for ( ; --i >= 0; ) {
2067 matchIndexes.push( i );
2068 }
2069 return matchIndexes;
2070 }),
2071
2072 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2073 var i = argument < 0 ? argument + length : argument;
2074 for ( ; ++i < length; ) {
2075 matchIndexes.push( i );
2076 }
2077 return matchIndexes;
2078 })
2079 }
2080};
2081
2082Expr.pseudos["nth"] = Expr.pseudos["eq"];
2083
2084// Add button/input type pseudos
2085for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
2086 Expr.pseudos[ i ] = createInputPseudo( i );
2087}
2088for ( i in { submit: true, reset: true } ) {
2089 Expr.pseudos[ i ] = createButtonPseudo( i );
2090}
2091
2092// Easy API for creating new setFilters
2093function setFilters() {}
2094setFilters.prototype = Expr.filters = Expr.pseudos;
2095Expr.setFilters = new setFilters();
2096
2097tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
2098 var matched, match, tokens, type,
2099 soFar, groups, preFilters,
2100 cached = tokenCache[ selector + " " ];
2101
2102 if ( cached ) {
2103 return parseOnly ? 0 : cached.slice( 0 );
2104 }
2105
2106 soFar = selector;
2107 groups = [];
2108 preFilters = Expr.preFilter;
2109
2110 while ( soFar ) {
2111
2112 // Comma and first run
2113 if ( !matched || (match = rcomma.exec( soFar )) ) {
2114 if ( match ) {
2115 // Don't consume trailing commas as valid
2116 soFar = soFar.slice( match[0].length ) || soFar;
2117 }
2118 groups.push( (tokens = []) );
2119 }
2120
2121 matched = false;
2122
2123 // Combinators
2124 if ( (match = rcombinators.exec( soFar )) ) {
2125 matched = match.shift();
2126 tokens.push({
2127 value: matched,
2128 // Cast descendant combinators to space
2129 type: match[0].replace( rtrim, " " )
2130 });
2131 soFar = soFar.slice( matched.length );
2132 }
2133
2134 // Filters
2135 for ( type in Expr.filter ) {
2136 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
2137 (match = preFilters[ type ]( match ))) ) {
2138 matched = match.shift();
2139 tokens.push({
2140 value: matched,
2141 type: type,
2142 matches: match
2143 });
2144 soFar = soFar.slice( matched.length );
2145 }
2146 }
2147
2148 if ( !matched ) {
2149 break;
2150 }
2151 }
2152
2153 // Return the length of the invalid excess
2154 // if we're just parsing
2155 // Otherwise, throw an error or return tokens
2156 return parseOnly ?
2157 soFar.length :
2158 soFar ?
2159 Sizzle.error( selector ) :
2160 // Cache the tokens
2161 tokenCache( selector, groups ).slice( 0 );
2162};
2163
2164function toSelector( tokens ) {
2165 var i = 0,
2166 len = tokens.length,
2167 selector = "";
2168 for ( ; i < len; i++ ) {
2169 selector += tokens[i].value;
2170 }
2171 return selector;
2172}
2173
2174function addCombinator( matcher, combinator, base ) {
2175 var dir = combinator.dir,
2176 checkNonElements = base && dir === "parentNode",
2177 doneName = done++;
2178
2179 return combinator.first ?
2180 // Check against closest ancestor/preceding element
2181 function( elem, context, xml ) {
2182 while ( (elem = elem[ dir ]) ) {
2183 if ( elem.nodeType === 1 || checkNonElements ) {
2184 return matcher( elem, context, xml );
2185 }
2186 }
2187 } :
2188
2189 // Check against all ancestor/preceding elements
2190 function( elem, context, xml ) {
2191 var oldCache, uniqueCache, outerCache,
2192 newCache = [ dirruns, doneName ];
2193
2194 // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
2195 if ( xml ) {
2196 while ( (elem = elem[ dir ]) ) {
2197 if ( elem.nodeType === 1 || checkNonElements ) {
2198 if ( matcher( elem, context, xml ) ) {
2199 return true;
2200 }
2201 }
2202 }
2203 } else {
2204 while ( (elem = elem[ dir ]) ) {
2205 if ( elem.nodeType === 1 || checkNonElements ) {
2206 outerCache = elem[ expando ] || (elem[ expando ] = {});
2207
2208 // Support: IE <9 only
2209 // Defend against cloned attroperties (jQuery gh-1709)
2210 uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
2211
2212 if ( (oldCache = uniqueCache[ dir ]) &&
2213 oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
2214
2215 // Assign to newCache so results back-propagate to previous elements
2216 return (newCache[ 2 ] = oldCache[ 2 ]);
2217 } else {
2218 // Reuse newcache so results back-propagate to previous elements
2219 uniqueCache[ dir ] = newCache;
2220
2221 // A match means we're done; a fail means we have to keep checking
2222 if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
2223 return true;
2224 }
2225 }
2226 }
2227 }
2228 }
2229 };
2230}
2231
2232function elementMatcher( matchers ) {
2233 return matchers.length > 1 ?
2234 function( elem, context, xml ) {
2235 var i = matchers.length;
2236 while ( i-- ) {
2237 if ( !matchers[i]( elem, context, xml ) ) {
2238 return false;
2239 }
2240 }
2241 return true;
2242 } :
2243 matchers[0];
2244}
2245
2246function multipleContexts( selector, contexts, results ) {
2247 var i = 0,
2248 len = contexts.length;
2249 for ( ; i < len; i++ ) {
2250 Sizzle( selector, contexts[i], results );
2251 }
2252 return results;
2253}
2254
2255function condense( unmatched, map, filter, context, xml ) {
2256 var elem,
2257 newUnmatched = [],
2258 i = 0,
2259 len = unmatched.length,
2260 mapped = map != null;
2261
2262 for ( ; i < len; i++ ) {
2263 if ( (elem = unmatched[i]) ) {
2264 if ( !filter || filter( elem, context, xml ) ) {
2265 newUnmatched.push( elem );
2266 if ( mapped ) {
2267 map.push( i );
2268 }
2269 }
2270 }
2271 }
2272
2273 return newUnmatched;
2274}
2275
2276function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
2277 if ( postFilter && !postFilter[ expando ] ) {
2278 postFilter = setMatcher( postFilter );
2279 }
2280 if ( postFinder && !postFinder[ expando ] ) {
2281 postFinder = setMatcher( postFinder, postSelector );
2282 }
2283 return markFunction(function( seed, results, context, xml ) {
2284 var temp, i, elem,
2285 preMap = [],
2286 postMap = [],
2287 preexisting = results.length,
2288
2289 // Get initial elements from seed or context
2290 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
2291
2292 // Prefilter to get matcher input, preserving a map for seed-results synchronization
2293 matcherIn = preFilter && ( seed || !selector ) ?
2294 condense( elems, preMap, preFilter, context, xml ) :
2295 elems,
2296
2297 matcherOut = matcher ?
2298 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
2299 postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
2300
2301 // ...intermediate processing is necessary
2302 [] :
2303
2304 // ...otherwise use results directly
2305 results :
2306 matcherIn;
2307
2308 // Find primary matches
2309 if ( matcher ) {
2310 matcher( matcherIn, matcherOut, context, xml );
2311 }
2312
2313 // Apply postFilter
2314 if ( postFilter ) {
2315 temp = condense( matcherOut, postMap );
2316 postFilter( temp, [], context, xml );
2317
2318 // Un-match failing elements by moving them back to matcherIn
2319 i = temp.length;
2320 while ( i-- ) {
2321 if ( (elem = temp[i]) ) {
2322 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
2323 }
2324 }
2325 }
2326
2327 if ( seed ) {
2328 if ( postFinder || preFilter ) {
2329 if ( postFinder ) {
2330 // Get the final matcherOut by condensing this intermediate into postFinder contexts
2331 temp = [];
2332 i = matcherOut.length;
2333 while ( i-- ) {
2334 if ( (elem = matcherOut[i]) ) {
2335 // Restore matcherIn since elem is not yet a final match
2336 temp.push( (matcherIn[i] = elem) );
2337 }
2338 }
2339 postFinder( null, (matcherOut = []), temp, xml );
2340 }
2341
2342 // Move matched elements from seed to results to keep them synchronized
2343 i = matcherOut.length;
2344 while ( i-- ) {
2345 if ( (elem = matcherOut[i]) &&
2346 (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
2347
2348 seed[temp] = !(results[temp] = elem);
2349 }
2350 }
2351 }
2352
2353 // Add elements to results, through postFinder if defined
2354 } else {
2355 matcherOut = condense(
2356 matcherOut === results ?
2357 matcherOut.splice( preexisting, matcherOut.length ) :
2358 matcherOut
2359 );
2360 if ( postFinder ) {
2361 postFinder( null, results, matcherOut, xml );
2362 } else {
2363 push.apply( results, matcherOut );
2364 }
2365 }
2366 });
2367}
2368
2369function matcherFromTokens( tokens ) {
2370 var checkContext, matcher, j,
2371 len = tokens.length,
2372 leadingRelative = Expr.relative[ tokens[0].type ],
2373 implicitRelative = leadingRelative || Expr.relative[" "],
2374 i = leadingRelative ? 1 : 0,
2375
2376 // The foundational matcher ensures that elements are reachable from top-level context(s)
2377 matchContext = addCombinator( function( elem ) {
2378 return elem === checkContext;
2379 }, implicitRelative, true ),
2380 matchAnyContext = addCombinator( function( elem ) {
2381 return indexOf( checkContext, elem ) > -1;
2382 }, implicitRelative, true ),
2383 matchers = [ function( elem, context, xml ) {
2384 var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
2385 (checkContext = context).nodeType ?
2386 matchContext( elem, context, xml ) :
2387 matchAnyContext( elem, context, xml ) );
2388 // Avoid hanging onto element (issue #299)
2389 checkContext = null;
2390 return ret;
2391 } ];
2392
2393 for ( ; i < len; i++ ) {
2394 if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
2395 matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
2396 } else {
2397 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
2398
2399 // Return special upon seeing a positional matcher
2400 if ( matcher[ expando ] ) {
2401 // Find the next relative operator (if any) for proper handling
2402 j = ++i;
2403 for ( ; j < len; j++ ) {
2404 if ( Expr.relative[ tokens[j].type ] ) {
2405 break;
2406 }
2407 }
2408 return setMatcher(
2409 i > 1 && elementMatcher( matchers ),
2410 i > 1 && toSelector(
2411 // If the preceding token was a descendant combinator, insert an implicit any-element `*`
2412 tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
2413 ).replace( rtrim, "$1" ),
2414 matcher,
2415 i < j && matcherFromTokens( tokens.slice( i, j ) ),
2416 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
2417 j < len && toSelector( tokens )
2418 );
2419 }
2420 matchers.push( matcher );
2421 }
2422 }
2423
2424 return elementMatcher( matchers );
2425}
2426
2427function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2428 var bySet = setMatchers.length > 0,
2429 byElement = elementMatchers.length > 0,
2430 superMatcher = function( seed, context, xml, results, outermost ) {
2431 var elem, j, matcher,
2432 matchedCount = 0,
2433 i = "0",
2434 unmatched = seed && [],
2435 setMatched = [],
2436 contextBackup = outermostContext,
2437 // We must always have either seed elements or outermost context
2438 elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
2439 // Use integer dirruns iff this is the outermost matcher
2440 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
2441 len = elems.length;
2442
2443 if ( outermost ) {
2444 outermostContext = context === document || context || outermost;
2445 }
2446
2447 // Add elements passing elementMatchers directly to results
2448 // Support: IE<9, Safari
2449 // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
2450 for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
2451 if ( byElement && elem ) {
2452 j = 0;
2453 if ( !context && elem.ownerDocument !== document ) {
2454 setDocument( elem );
2455 xml = !documentIsHTML;
2456 }
2457 while ( (matcher = elementMatchers[j++]) ) {
2458 if ( matcher( elem, context || document, xml) ) {
2459 results.push( elem );
2460 break;
2461 }
2462 }
2463 if ( outermost ) {
2464 dirruns = dirrunsUnique;
2465 }
2466 }
2467
2468 // Track unmatched elements for set filters
2469 if ( bySet ) {
2470 // They will have gone through all possible matchers
2471 if ( (elem = !matcher && elem) ) {
2472 matchedCount--;
2473 }
2474
2475 // Lengthen the array for every element, matched or not
2476 if ( seed ) {
2477 unmatched.push( elem );
2478 }
2479 }
2480 }
2481
2482 // `i` is now the count of elements visited above, and adding it to `matchedCount`
2483 // makes the latter nonnegative.
2484 matchedCount += i;
2485
2486 // Apply set filters to unmatched elements
2487 // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
2488 // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
2489 // no element matchers and no seed.
2490 // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
2491 // case, which will result in a "00" `matchedCount` that differs from `i` but is also
2492 // numerically zero.
2493 if ( bySet && i !== matchedCount ) {
2494 j = 0;
2495 while ( (matcher = setMatchers[j++]) ) {
2496 matcher( unmatched, setMatched, context, xml );
2497 }
2498
2499 if ( seed ) {
2500 // Reintegrate element matches to eliminate the need for sorting
2501 if ( matchedCount > 0 ) {
2502 while ( i-- ) {
2503 if ( !(unmatched[i] || setMatched[i]) ) {
2504 setMatched[i] = pop.call( results );
2505 }
2506 }
2507 }
2508
2509 // Discard index placeholder values to get only actual matches
2510 setMatched = condense( setMatched );
2511 }
2512
2513 // Add matches to results
2514 push.apply( results, setMatched );
2515
2516 // Seedless set matches succeeding multiple successful matchers stipulate sorting
2517 if ( outermost && !seed && setMatched.length > 0 &&
2518 ( matchedCount + setMatchers.length ) > 1 ) {
2519
2520 Sizzle.uniqueSort( results );
2521 }
2522 }
2523
2524 // Override manipulation of globals by nested matchers
2525 if ( outermost ) {
2526 dirruns = dirrunsUnique;
2527 outermostContext = contextBackup;
2528 }
2529
2530 return unmatched;
2531 };
2532
2533 return bySet ?
2534 markFunction( superMatcher ) :
2535 superMatcher;
2536}
2537
2538compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
2539 var i,
2540 setMatchers = [],
2541 elementMatchers = [],
2542 cached = compilerCache[ selector + " " ];
2543
2544 if ( !cached ) {
2545 // Generate a function of recursive functions that can be used to check each element
2546 if ( !match ) {
2547 match = tokenize( selector );
2548 }
2549 i = match.length;
2550 while ( i-- ) {
2551 cached = matcherFromTokens( match[i] );
2552 if ( cached[ expando ] ) {
2553 setMatchers.push( cached );
2554 } else {
2555 elementMatchers.push( cached );
2556 }
2557 }
2558
2559 // Cache the compiled function
2560 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
2561
2562 // Save selector and tokenization
2563 cached.selector = selector;
2564 }
2565 return cached;
2566};
2567
2568/**
2569 * A low-level selection function that works with Sizzle's compiled
2570 * selector functions
2571 * @param {String|Function} selector A selector or a pre-compiled
2572 * selector function built with Sizzle.compile
2573 * @param {Element} context
2574 * @param {Array} [results]
2575 * @param {Array} [seed] A set of elements to match against
2576 */
2577select = Sizzle.select = function( selector, context, results, seed ) {
2578 var i, tokens, token, type, find,
2579 compiled = typeof selector === "function" && selector,
2580 match = !seed && tokenize( (selector = compiled.selector || selector) );
2581
2582 results = results || [];
2583
2584 // Try to minimize operations if there is only one selector in the list and no seed
2585 // (the latter of which guarantees us context)
2586 if ( match.length === 1 ) {
2587
2588 // Reduce context if the leading compound selector is an ID
2589 tokens = match[0] = match[0].slice( 0 );
2590 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
2591 support.getById && context.nodeType === 9 && documentIsHTML &&
2592 Expr.relative[ tokens[1].type ] ) {
2593
2594 context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
2595 if ( !context ) {
2596 return results;
2597
2598 // Precompiled matchers will still verify ancestry, so step up a level
2599 } else if ( compiled ) {
2600 context = context.parentNode;
2601 }
2602
2603 selector = selector.slice( tokens.shift().value.length );
2604 }
2605
2606 // Fetch a seed set for right-to-left matching
2607 i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
2608 while ( i-- ) {
2609 token = tokens[i];
2610
2611 // Abort if we hit a combinator
2612 if ( Expr.relative[ (type = token.type) ] ) {
2613 break;
2614 }
2615 if ( (find = Expr.find[ type ]) ) {
2616 // Search, expanding context for leading sibling combinators
2617 if ( (seed = find(
2618 token.matches[0].replace( runescape, funescape ),
2619 rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
2620 )) ) {
2621
2622 // If seed is empty or no tokens remain, we can return early
2623 tokens.splice( i, 1 );
2624 selector = seed.length && toSelector( tokens );
2625 if ( !selector ) {
2626 push.apply( results, seed );
2627 return results;
2628 }
2629
2630 break;
2631 }
2632 }
2633 }
2634 }
2635
2636 // Compile and execute a filtering function if one is not provided
2637 // Provide `match` to avoid retokenization if we modified the selector above
2638 ( compiled || compile( selector, match ) )(
2639 seed,
2640 context,
2641 !documentIsHTML,
2642 results,
2643 !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
2644 );
2645 return results;
2646};
2647
2648// One-time assignments
2649
2650// Sort stability
2651support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
2652
2653// Support: Chrome 14-35+
2654// Always assume duplicates if they aren't passed to the comparison function
2655support.detectDuplicates = !!hasDuplicate;
2656
2657// Initialize against the default document
2658setDocument();
2659
2660// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
2661// Detached nodes confoundingly follow *each other*
2662support.sortDetached = assert(function( div1 ) {
2663 // Should return 1, but returns 4 (following)
2664 return div1.compareDocumentPosition( document.createElement("div") ) & 1;
2665});
2666
2667// Support: IE<8
2668// Prevent attribute/property "interpolation"
2669// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
2670if ( !assert(function( div ) {
2671 div.innerHTML = "<a href='#'></a>";
2672 return div.firstChild.getAttribute("href") === "#" ;
2673}) ) {
2674 addHandle( "type|href|height|width", function( elem, name, isXML ) {
2675 if ( !isXML ) {
2676 return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
2677 }
2678 });
2679}
2680
2681// Support: IE<9
2682// Use defaultValue in place of getAttribute("value")
2683if ( !support.attributes || !assert(function( div ) {
2684 div.innerHTML = "<input/>";
2685 div.firstChild.setAttribute( "value", "" );
2686 return div.firstChild.getAttribute( "value" ) === "";
2687}) ) {
2688 addHandle( "value", function( elem, name, isXML ) {
2689 if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
2690 return elem.defaultValue;
2691 }
2692 });
2693}
2694
2695// Support: IE<9
2696// Use getAttributeNode to fetch booleans when getAttribute lies
2697if ( !assert(function( div ) {
2698 return div.getAttribute("disabled") == null;
2699}) ) {
2700 addHandle( booleans, function( elem, name, isXML ) {
2701 var val;
2702 if ( !isXML ) {
2703 return elem[ name ] === true ? name.toLowerCase() :
2704 (val = elem.getAttributeNode( name )) && val.specified ?
2705 val.value :
2706 null;
2707 }
2708 });
2709}
2710
2711return Sizzle;
2712
2713})( window );
2714
2715
2716
2717jQuery.find = Sizzle;
2718jQuery.expr = Sizzle.selectors;
2719jQuery.expr[ ":" ] = jQuery.expr.pseudos;
2720jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
2721jQuery.text = Sizzle.getText;
2722jQuery.isXMLDoc = Sizzle.isXML;
2723jQuery.contains = Sizzle.contains;
2724
2725
2726
2727var dir = function( elem, dir, until ) {
2728 var matched = [],
2729 truncate = until !== undefined;
2730
2731 while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
2732 if ( elem.nodeType === 1 ) {
2733 if ( truncate && jQuery( elem ).is( until ) ) {
2734 break;
2735 }
2736 matched.push( elem );
2737 }
2738 }
2739 return matched;
2740};
2741
2742
2743var siblings = function( n, elem ) {
2744 var matched = [];
2745
2746 for ( ; n; n = n.nextSibling ) {
2747 if ( n.nodeType === 1 && n !== elem ) {
2748 matched.push( n );
2749 }
2750 }
2751
2752 return matched;
2753};
2754
2755
2756var rneedsContext = jQuery.expr.match.needsContext;
2757
2758var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ );
2759
2760
2761
2762var risSimple = /^.[^:#\[\.,]*$/;
2763
2764// Implement the identical functionality for filter and not
2765function winnow( elements, qualifier, not ) {
2766 if ( jQuery.isFunction( qualifier ) ) {
2767 return jQuery.grep( elements, function( elem, i ) {
2768 /* jshint -W018 */
2769 return !!qualifier.call( elem, i, elem ) !== not;
2770 } );
2771
2772 }
2773
2774 if ( qualifier.nodeType ) {
2775 return jQuery.grep( elements, function( elem ) {
2776 return ( elem === qualifier ) !== not;
2777 } );
2778
2779 }
2780
2781 if ( typeof qualifier === "string" ) {
2782 if ( risSimple.test( qualifier ) ) {
2783 return jQuery.filter( qualifier, elements, not );
2784 }
2785
2786 qualifier = jQuery.filter( qualifier, elements );
2787 }
2788
2789 return jQuery.grep( elements, function( elem ) {
2790 return ( jQuery.inArray( elem, qualifier ) > -1 ) !== not;
2791 } );
2792}
2793
2794jQuery.filter = function( expr, elems, not ) {
2795 var elem = elems[ 0 ];
2796
2797 if ( not ) {
2798 expr = ":not(" + expr + ")";
2799 }
2800
2801 return elems.length === 1 && elem.nodeType === 1 ?
2802 jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
2803 jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
2804 return elem.nodeType === 1;
2805 } ) );
2806};
2807
2808jQuery.fn.extend( {
2809 find: function( selector ) {
2810 var i,
2811 ret = [],
2812 self = this,
2813 len = self.length;
2814
2815 if ( typeof selector !== "string" ) {
2816 return this.pushStack( jQuery( selector ).filter( function() {
2817 for ( i = 0; i < len; i++ ) {
2818 if ( jQuery.contains( self[ i ], this ) ) {
2819 return true;
2820 }
2821 }
2822 } ) );
2823 }
2824
2825 for ( i = 0; i < len; i++ ) {
2826 jQuery.find( selector, self[ i ], ret );
2827 }
2828
2829 // Needed because $( selector, context ) becomes $( context ).find( selector )
2830 ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
2831 ret.selector = this.selector ? this.selector + " " + selector : selector;
2832 return ret;
2833 },
2834 filter: function( selector ) {
2835 return this.pushStack( winnow( this, selector || [], false ) );
2836 },
2837 not: function( selector ) {
2838 return this.pushStack( winnow( this, selector || [], true ) );
2839 },
2840 is: function( selector ) {
2841 return !!winnow(
2842 this,
2843
2844 // If this is a positional/relative selector, check membership in the returned set
2845 // so $("p:first").is("p:last") won't return true for a doc with two "p".
2846 typeof selector === "string" && rneedsContext.test( selector ) ?
2847 jQuery( selector ) :
2848 selector || [],
2849 false
2850 ).length;
2851 }
2852} );
2853
2854
2855// Initialize a jQuery object
2856
2857
2858// A central reference to the root jQuery(document)
2859var rootjQuery,
2860
2861 // A simple way to check for HTML strings
2862 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
2863 // Strict HTML recognition (#11290: must start with <)
2864 rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
2865
2866 init = jQuery.fn.init = function( selector, context, root ) {
2867 var match, elem;
2868
2869 // HANDLE: $(""), $(null), $(undefined), $(false)
2870 if ( !selector ) {
2871 return this;
2872 }
2873
2874 // init accepts an alternate rootjQuery
2875 // so migrate can support jQuery.sub (gh-2101)
2876 root = root || rootjQuery;
2877
2878 // Handle HTML strings
2879 if ( typeof selector === "string" ) {
2880 if ( selector.charAt( 0 ) === "<" &&
2881 selector.charAt( selector.length - 1 ) === ">" &&
2882 selector.length >= 3 ) {
2883
2884 // Assume that strings that start and end with <> are HTML and skip the regex check
2885 match = [ null, selector, null ];
2886
2887 } else {
2888 match = rquickExpr.exec( selector );
2889 }
2890
2891 // Match html or make sure no context is specified for #id
2892 if ( match && ( match[ 1 ] || !context ) ) {
2893
2894 // HANDLE: $(html) -> $(array)
2895 if ( match[ 1 ] ) {
2896 context = context instanceof jQuery ? context[ 0 ] : context;
2897
2898 // scripts is true for back-compat
2899 // Intentionally let the error be thrown if parseHTML is not present
2900 jQuery.merge( this, jQuery.parseHTML(
2901 match[ 1 ],
2902 context && context.nodeType ? context.ownerDocument || context : document,
2903 true
2904 ) );
2905
2906 // HANDLE: $(html, props)
2907 if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
2908 for ( match in context ) {
2909
2910 // Properties of context are called as methods if possible
2911 if ( jQuery.isFunction( this[ match ] ) ) {
2912 this[ match ]( context[ match ] );
2913
2914 // ...and otherwise set as attributes
2915 } else {
2916 this.attr( match, context[ match ] );
2917 }
2918 }
2919 }
2920
2921 return this;
2922
2923 // HANDLE: $(#id)
2924 } else {
2925 elem = document.getElementById( match[ 2 ] );
2926
2927 // Check parentNode to catch when Blackberry 4.6 returns
2928 // nodes that are no longer in the document #6963
2929 if ( elem && elem.parentNode ) {
2930
2931 // Handle the case where IE and Opera return items
2932 // by name instead of ID
2933 if ( elem.id !== match[ 2 ] ) {
2934 return rootjQuery.find( selector );
2935 }
2936
2937 // Otherwise, we inject the element directly into the jQuery object
2938 this.length = 1;
2939 this[ 0 ] = elem;
2940 }
2941
2942 this.context = document;
2943 this.selector = selector;
2944 return this;
2945 }
2946
2947 // HANDLE: $(expr, $(...))
2948 } else if ( !context || context.jquery ) {
2949 return ( context || root ).find( selector );
2950
2951 // HANDLE: $(expr, context)
2952 // (which is just equivalent to: $(context).find(expr)
2953 } else {
2954 return this.constructor( context ).find( selector );
2955 }
2956
2957 // HANDLE: $(DOMElement)
2958 } else if ( selector.nodeType ) {
2959 this.context = this[ 0 ] = selector;
2960 this.length = 1;
2961 return this;
2962
2963 // HANDLE: $(function)
2964 // Shortcut for document ready
2965 } else if ( jQuery.isFunction( selector ) ) {
2966 return typeof root.ready !== "undefined" ?
2967 root.ready( selector ) :
2968
2969 // Execute immediately if ready is not present
2970 selector( jQuery );
2971 }
2972
2973 if ( selector.selector !== undefined ) {
2974 this.selector = selector.selector;
2975 this.context = selector.context;
2976 }
2977
2978 return jQuery.makeArray( selector, this );
2979 };
2980
2981// Give the init function the jQuery prototype for later instantiation
2982init.prototype = jQuery.fn;
2983
2984// Initialize central reference
2985rootjQuery = jQuery( document );
2986
2987
2988var rparentsprev = /^(?:parents|prev(?:Until|All))/,
2989
2990 // methods guaranteed to produce a unique set when starting from a unique set
2991 guaranteedUnique = {
2992 children: true,
2993 contents: true,
2994 next: true,
2995 prev: true
2996 };
2997
2998jQuery.fn.extend( {
2999 has: function( target ) {
3000 var i,
3001 targets = jQuery( target, this ),
3002 len = targets.length;
3003
3004 return this.filter( function() {
3005 for ( i = 0; i < len; i++ ) {
3006 if ( jQuery.contains( this, targets[ i ] ) ) {
3007 return true;
3008 }
3009 }
3010 } );
3011 },
3012
3013 closest: function( selectors, context ) {
3014 var cur,
3015 i = 0,
3016 l = this.length,
3017 matched = [],
3018 pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
3019 jQuery( selectors, context || this.context ) :
3020 0;
3021
3022 for ( ; i < l; i++ ) {
3023 for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
3024
3025 // Always skip document fragments
3026 if ( cur.nodeType < 11 && ( pos ?
3027 pos.index( cur ) > -1 :
3028
3029 // Don't pass non-elements to Sizzle
3030 cur.nodeType === 1 &&
3031 jQuery.find.matchesSelector( cur, selectors ) ) ) {
3032
3033 matched.push( cur );
3034 break;
3035 }
3036 }
3037 }
3038
3039 return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
3040 },
3041
3042 // Determine the position of an element within
3043 // the matched set of elements
3044 index: function( elem ) {
3045
3046 // No argument, return index in parent
3047 if ( !elem ) {
3048 return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
3049 }
3050
3051 // index in selector
3052 if ( typeof elem === "string" ) {
3053 return jQuery.inArray( this[ 0 ], jQuery( elem ) );
3054 }
3055
3056 // Locate the position of the desired element
3057 return jQuery.inArray(
3058
3059 // If it receives a jQuery object, the first element is used
3060 elem.jquery ? elem[ 0 ] : elem, this );
3061 },
3062
3063 add: function( selector, context ) {
3064 return this.pushStack(
3065 jQuery.uniqueSort(
3066 jQuery.merge( this.get(), jQuery( selector, context ) )
3067 )
3068 );
3069 },
3070
3071 addBack: function( selector ) {
3072 return this.add( selector == null ?
3073 this.prevObject : this.prevObject.filter( selector )
3074 );
3075 }
3076} );
3077
3078function sibling( cur, dir ) {
3079 do {
3080 cur = cur[ dir ];
3081 } while ( cur && cur.nodeType !== 1 );
3082
3083 return cur;
3084}
3085
3086jQuery.each( {
3087 parent: function( elem ) {
3088 var parent = elem.parentNode;
3089 return parent && parent.nodeType !== 11 ? parent : null;
3090 },
3091 parents: function( elem ) {
3092 return dir( elem, "parentNode" );
3093 },
3094 parentsUntil: function( elem, i, until ) {
3095 return dir( elem, "parentNode", until );
3096 },
3097 next: function( elem ) {
3098 return sibling( elem, "nextSibling" );
3099 },
3100 prev: function( elem ) {
3101 return sibling( elem, "previousSibling" );
3102 },
3103 nextAll: function( elem ) {
3104 return dir( elem, "nextSibling" );
3105 },
3106 prevAll: function( elem ) {
3107 return dir( elem, "previousSibling" );
3108 },
3109 nextUntil: function( elem, i, until ) {
3110 return dir( elem, "nextSibling", until );
3111 },
3112 prevUntil: function( elem, i, until ) {
3113 return dir( elem, "previousSibling", until );
3114 },
3115 siblings: function( elem ) {
3116 return siblings( ( elem.parentNode || {} ).firstChild, elem );
3117 },
3118 children: function( elem ) {
3119 return siblings( elem.firstChild );
3120 },
3121 contents: function( elem ) {
3122 return jQuery.nodeName( elem, "iframe" ) ?
3123 elem.contentDocument || elem.contentWindow.document :
3124 jQuery.merge( [], elem.childNodes );
3125 }
3126}, function( name, fn ) {
3127 jQuery.fn[ name ] = function( until, selector ) {
3128 var ret = jQuery.map( this, fn, until );
3129
3130 if ( name.slice( -5 ) !== "Until" ) {
3131 selector = until;
3132 }
3133
3134 if ( selector && typeof selector === "string" ) {
3135 ret = jQuery.filter( selector, ret );
3136 }
3137
3138 if ( this.length > 1 ) {
3139
3140 // Remove duplicates
3141 if ( !guaranteedUnique[ name ] ) {
3142 ret = jQuery.uniqueSort( ret );
3143 }
3144
3145 // Reverse order for parents* and prev-derivatives
3146 if ( rparentsprev.test( name ) ) {
3147 ret = ret.reverse();
3148 }
3149 }
3150
3151 return this.pushStack( ret );
3152 };
3153} );
3154var rnotwhite = ( /\S+/g );
3155
3156
3157
3158// Convert String-formatted options into Object-formatted ones
3159function createOptions( options ) {
3160 var object = {};
3161 jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
3162 object[ flag ] = true;
3163 } );
3164 return object;
3165}
3166
3167/*
3168 * Create a callback list using the following parameters:
3169 *
3170 * options: an optional list of space-separated options that will change how
3171 * the callback list behaves or a more traditional option object
3172 *
3173 * By default a callback list will act like an event callback list and can be
3174 * "fired" multiple times.
3175 *
3176 * Possible options:
3177 *
3178 * once: will ensure the callback list can only be fired once (like a Deferred)
3179 *
3180 * memory: will keep track of previous values and will call any callback added
3181 * after the list has been fired right away with the latest "memorized"
3182 * values (like a Deferred)
3183 *
3184 * unique: will ensure a callback can only be added once (no duplicate in the list)
3185 *
3186 * stopOnFalse: interrupt callings when a callback returns false
3187 *
3188 */
3189jQuery.Callbacks = function( options ) {
3190
3191 // Convert options from String-formatted to Object-formatted if needed
3192 // (we check in cache first)
3193 options = typeof options === "string" ?
3194 createOptions( options ) :
3195 jQuery.extend( {}, options );
3196
3197 var // Flag to know if list is currently firing
3198 firing,
3199
3200 // Last fire value for non-forgettable lists
3201 memory,
3202
3203 // Flag to know if list was already fired
3204 fired,
3205
3206 // Flag to prevent firing
3207 locked,
3208
3209 // Actual callback list
3210 list = [],
3211
3212 // Queue of execution data for repeatable lists
3213 queue = [],
3214
3215 // Index of currently firing callback (modified by add/remove as needed)
3216 firingIndex = -1,
3217
3218 // Fire callbacks
3219 fire = function() {
3220
3221 // Enforce single-firing
3222 locked = options.once;
3223
3224 // Execute callbacks for all pending executions,
3225 // respecting firingIndex overrides and runtime changes
3226 fired = firing = true;
3227 for ( ; queue.length; firingIndex = -1 ) {
3228 memory = queue.shift();
3229 while ( ++firingIndex < list.length ) {
3230
3231 // Run callback and check for early termination
3232 if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
3233 options.stopOnFalse ) {
3234
3235 // Jump to end and forget the data so .add doesn't re-fire
3236 firingIndex = list.length;
3237 memory = false;
3238 }
3239 }
3240 }
3241
3242 // Forget the data if we're done with it
3243 if ( !options.memory ) {
3244 memory = false;
3245 }
3246
3247 firing = false;
3248
3249 // Clean up if we're done firing for good
3250 if ( locked ) {
3251
3252 // Keep an empty list if we have data for future add calls
3253 if ( memory ) {
3254 list = [];
3255
3256 // Otherwise, this object is spent
3257 } else {
3258 list = "";
3259 }
3260 }
3261 },
3262
3263 // Actual Callbacks object
3264 self = {
3265
3266 // Add a callback or a collection of callbacks to the list
3267 add: function() {
3268 if ( list ) {
3269
3270 // If we have memory from a past run, we should fire after adding
3271 if ( memory && !firing ) {
3272 firingIndex = list.length - 1;
3273 queue.push( memory );
3274 }
3275
3276 ( function add( args ) {
3277 jQuery.each( args, function( _, arg ) {
3278 if ( jQuery.isFunction( arg ) ) {
3279 if ( !options.unique || !self.has( arg ) ) {
3280 list.push( arg );
3281 }
3282 } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
3283
3284 // Inspect recursively
3285 add( arg );
3286 }
3287 } );
3288 } )( arguments );
3289
3290 if ( memory && !firing ) {
3291 fire();
3292 }
3293 }
3294 return this;
3295 },
3296
3297 // Remove a callback from the list
3298 remove: function() {
3299 jQuery.each( arguments, function( _, arg ) {
3300 var index;
3301 while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
3302 list.splice( index, 1 );
3303
3304 // Handle firing indexes
3305 if ( index <= firingIndex ) {
3306 firingIndex--;
3307 }
3308 }
3309 } );
3310 return this;
3311 },
3312
3313 // Check if a given callback is in the list.
3314 // If no argument is given, return whether or not list has callbacks attached.
3315 has: function( fn ) {
3316 return fn ?
3317 jQuery.inArray( fn, list ) > -1 :
3318 list.length > 0;
3319 },
3320
3321 // Remove all callbacks from the list
3322 empty: function() {
3323 if ( list ) {
3324 list = [];
3325 }
3326 return this;
3327 },
3328
3329 // Disable .fire and .add
3330 // Abort any current/pending executions
3331 // Clear all callbacks and values
3332 disable: function() {
3333 locked = queue = [];
3334 list = memory = "";
3335 return this;
3336 },
3337 disabled: function() {
3338 return !list;
3339 },
3340
3341 // Disable .fire
3342 // Also disable .add unless we have memory (since it would have no effect)
3343 // Abort any pending executions
3344 lock: function() {
3345 locked = true;
3346 if ( !memory ) {
3347 self.disable();
3348 }
3349 return this;
3350 },
3351 locked: function() {
3352 return !!locked;
3353 },
3354
3355 // Call all callbacks with the given context and arguments
3356 fireWith: function( context, args ) {
3357 if ( !locked ) {
3358 args = args || [];
3359 args = [ context, args.slice ? args.slice() : args ];
3360 queue.push( args );
3361 if ( !firing ) {
3362 fire();
3363 }
3364 }
3365 return this;
3366 },
3367
3368 // Call all the callbacks with the given arguments
3369 fire: function() {
3370 self.fireWith( this, arguments );
3371 return this;
3372 },
3373
3374 // To know if the callbacks have already been called at least once
3375 fired: function() {
3376 return !!fired;
3377 }
3378 };
3379
3380 return self;
3381};
3382
3383
3384jQuery.extend( {
3385
3386 Deferred: function( func ) {
3387 var tuples = [
3388
3389 // action, add listener, listener list, final state
3390 [ "resolve", "done", jQuery.Callbacks( "once memory" ), "resolved" ],
3391 [ "reject", "fail", jQuery.Callbacks( "once memory" ), "rejected" ],
3392 [ "notify", "progress", jQuery.Callbacks( "memory" ) ]
3393 ],
3394 state = "pending",
3395 promise = {
3396 state: function() {
3397 return state;
3398 },
3399 always: function() {
3400 deferred.done( arguments ).fail( arguments );
3401 return this;
3402 },
3403 then: function( /* fnDone, fnFail, fnProgress */ ) {
3404 var fns = arguments;
3405 return jQuery.Deferred( function( newDefer ) {
3406 jQuery.each( tuples, function( i, tuple ) {
3407 var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
3408
3409 // deferred[ done | fail | progress ] for forwarding actions to newDefer
3410 deferred[ tuple[ 1 ] ]( function() {
3411 var returned = fn && fn.apply( this, arguments );
3412 if ( returned && jQuery.isFunction( returned.promise ) ) {
3413 returned.promise()
3414 .progress( newDefer.notify )
3415 .done( newDefer.resolve )
3416 .fail( newDefer.reject );
3417 } else {
3418 newDefer[ tuple[ 0 ] + "With" ](
3419 this === promise ? newDefer.promise() : this,
3420 fn ? [ returned ] : arguments
3421 );
3422 }
3423 } );
3424 } );
3425 fns = null;
3426 } ).promise();
3427 },
3428
3429 // Get a promise for this deferred
3430 // If obj is provided, the promise aspect is added to the object
3431 promise: function( obj ) {
3432 return obj != null ? jQuery.extend( obj, promise ) : promise;
3433 }
3434 },
3435 deferred = {};
3436
3437 // Keep pipe for back-compat
3438 promise.pipe = promise.then;
3439
3440 // Add list-specific methods
3441 jQuery.each( tuples, function( i, tuple ) {
3442 var list = tuple[ 2 ],
3443 stateString = tuple[ 3 ];
3444
3445 // promise[ done | fail | progress ] = list.add
3446 promise[ tuple[ 1 ] ] = list.add;
3447
3448 // Handle state
3449 if ( stateString ) {
3450 list.add( function() {
3451
3452 // state = [ resolved | rejected ]
3453 state = stateString;
3454
3455 // [ reject_list | resolve_list ].disable; progress_list.lock
3456 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
3457 }
3458
3459 // deferred[ resolve | reject | notify ]
3460 deferred[ tuple[ 0 ] ] = function() {
3461 deferred[ tuple[ 0 ] + "With" ]( this === deferred ? promise : this, arguments );
3462 return this;
3463 };
3464 deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
3465 } );
3466
3467 // Make the deferred a promise
3468 promise.promise( deferred );
3469
3470 // Call given func if any
3471 if ( func ) {
3472 func.call( deferred, deferred );
3473 }
3474
3475 // All done!
3476 return deferred;
3477 },
3478
3479 // Deferred helper
3480 when: function( subordinate /* , ..., subordinateN */ ) {
3481 var i = 0,
3482 resolveValues = slice.call( arguments ),
3483 length = resolveValues.length,
3484
3485 // the count of uncompleted subordinates
3486 remaining = length !== 1 ||
3487 ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
3488
3489 // the master Deferred.
3490 // If resolveValues consist of only a single Deferred, just use that.
3491 deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
3492
3493 // Update function for both resolve and progress values
3494 updateFunc = function( i, contexts, values ) {
3495 return function( value ) {
3496 contexts[ i ] = this;
3497 values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
3498 if ( values === progressValues ) {
3499 deferred.notifyWith( contexts, values );
3500
3501 } else if ( !( --remaining ) ) {
3502 deferred.resolveWith( contexts, values );
3503 }
3504 };
3505 },
3506
3507 progressValues, progressContexts, resolveContexts;
3508
3509 // add listeners to Deferred subordinates; treat others as resolved
3510 if ( length > 1 ) {
3511 progressValues = new Array( length );
3512 progressContexts = new Array( length );
3513 resolveContexts = new Array( length );
3514 for ( ; i < length; i++ ) {
3515 if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
3516 resolveValues[ i ].promise()
3517 .progress( updateFunc( i, progressContexts, progressValues ) )
3518 .done( updateFunc( i, resolveContexts, resolveValues ) )
3519 .fail( deferred.reject );
3520 } else {
3521 --remaining;
3522 }
3523 }
3524 }
3525
3526 // if we're not waiting on anything, resolve the master
3527 if ( !remaining ) {
3528 deferred.resolveWith( resolveContexts, resolveValues );
3529 }
3530
3531 return deferred.promise();
3532 }
3533} );
3534
3535
3536// The deferred used on DOM ready
3537var readyList;
3538
3539jQuery.fn.ready = function( fn ) {
3540
3541 // Add the callback
3542 jQuery.ready.promise().done( fn );
3543
3544 return this;
3545};
3546
3547jQuery.extend( {
3548
3549 // Is the DOM ready to be used? Set to true once it occurs.
3550 isReady: false,
3551
3552 // A counter to track how many items to wait for before
3553 // the ready event fires. See #6781
3554 readyWait: 1,
3555
3556 // Hold (or release) the ready event
3557 holdReady: function( hold ) {
3558 if ( hold ) {
3559 jQuery.readyWait++;
3560 } else {
3561 jQuery.ready( true );
3562 }
3563 },
3564
3565 // Handle when the DOM is ready
3566 ready: function( wait ) {
3567
3568 // Abort if there are pending holds or we're already ready
3569 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
3570 return;
3571 }
3572
3573 // Remember that the DOM is ready
3574 jQuery.isReady = true;
3575
3576 // If a normal DOM Ready event fired, decrement, and wait if need be
3577 if ( wait !== true && --jQuery.readyWait > 0 ) {
3578 return;
3579 }
3580
3581 // If there are functions bound, to execute
3582 readyList.resolveWith( document, [ jQuery ] );
3583
3584 // Trigger any bound ready events
3585 if ( jQuery.fn.triggerHandler ) {
3586 jQuery( document ).triggerHandler( "ready" );
3587 jQuery( document ).off( "ready" );
3588 }
3589 }
3590} );
3591
3592/**
3593 * Clean-up method for dom ready events
3594 */
3595function detach() {
3596 if ( document.addEventListener ) {
3597 document.removeEventListener( "DOMContentLoaded", completed );
3598 window.removeEventListener( "load", completed );
3599
3600 } else {
3601 document.detachEvent( "onreadystatechange", completed );
3602 window.detachEvent( "onload", completed );
3603 }
3604}
3605
3606/**
3607 * The ready event handler and self cleanup method
3608 */
3609function completed() {
3610
3611 // readyState === "complete" is good enough for us to call the dom ready in oldIE
3612 if ( document.addEventListener ||
3613 window.event.type === "load" ||
3614 document.readyState === "complete" ) {
3615
3616 detach();
3617 jQuery.ready();
3618 }
3619}
3620
3621jQuery.ready.promise = function( obj ) {
3622 if ( !readyList ) {
3623
3624 readyList = jQuery.Deferred();
3625
3626 // Catch cases where $(document).ready() is called
3627 // after the browser event has already occurred.
3628 // Support: IE6-10
3629 // Older IE sometimes signals "interactive" too soon
3630 if ( document.readyState === "complete" ||
3631 ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
3632
3633 // Handle it asynchronously to allow scripts the opportunity to delay ready
3634 window.setTimeout( jQuery.ready );
3635
3636 // Standards-based browsers support DOMContentLoaded
3637 } else if ( document.addEventListener ) {
3638
3639 // Use the handy event callback
3640 document.addEventListener( "DOMContentLoaded", completed );
3641
3642 // A fallback to window.onload, that will always work
3643 window.addEventListener( "load", completed );
3644
3645 // If IE event model is used
3646 } else {
3647
3648 // Ensure firing before onload, maybe late but safe also for iframes
3649 document.attachEvent( "onreadystatechange", completed );
3650
3651 // A fallback to window.onload, that will always work
3652 window.attachEvent( "onload", completed );
3653
3654 // If IE and not a frame
3655 // continually check to see if the document is ready
3656 var top = false;
3657
3658 try {
3659 top = window.frameElement == null && document.documentElement;
3660 } catch ( e ) {}
3661
3662 if ( top && top.doScroll ) {
3663 ( function doScrollCheck() {
3664 if ( !jQuery.isReady ) {
3665
3666 try {
3667
3668 // Use the trick by Diego Perini
3669 // http://javascript.nwbox.com/IEContentLoaded/
3670 top.doScroll( "left" );
3671 } catch ( e ) {
3672 return window.setTimeout( doScrollCheck, 50 );
3673 }
3674
3675 // detach all dom ready events
3676 detach();
3677
3678 // and execute any waiting functions
3679 jQuery.ready();
3680 }
3681 } )();
3682 }
3683 }
3684 }
3685 return readyList.promise( obj );
3686};
3687
3688// Kick off the DOM ready check even if the user does not
3689jQuery.ready.promise();
3690
3691
3692
3693
3694// Support: IE<9
3695// Iteration over object's inherited properties before its own
3696var i;
3697for ( i in jQuery( support ) ) {
3698 break;
3699}
3700support.ownFirst = i === "0";
3701
3702// Note: most support tests are defined in their respective modules.
3703// false until the test is run
3704support.inlineBlockNeedsLayout = false;
3705
3706// Execute ASAP in case we need to set body.style.zoom
3707jQuery( function() {
3708
3709 // Minified: var a,b,c,d
3710 var val, div, body, container;
3711
3712 body = document.getElementsByTagName( "body" )[ 0 ];
3713 if ( !body || !body.style ) {
3714
3715 // Return for frameset docs that don't have a body
3716 return;
3717 }
3718
3719 // Setup
3720 div = document.createElement( "div" );
3721 container = document.createElement( "div" );
3722 container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
3723 body.appendChild( container ).appendChild( div );
3724
3725 if ( typeof div.style.zoom !== "undefined" ) {
3726
3727 // Support: IE<8
3728 // Check if natively block-level elements act like inline-block
3729 // elements when setting their display to 'inline' and giving
3730 // them layout
3731 div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";
3732
3733 support.inlineBlockNeedsLayout = val = div.offsetWidth === 3;
3734 if ( val ) {
3735
3736 // Prevent IE 6 from affecting layout for positioned elements #11048
3737 // Prevent IE from shrinking the body in IE 7 mode #12869
3738 // Support: IE<8
3739 body.style.zoom = 1;
3740 }
3741 }
3742
3743 body.removeChild( container );
3744} );
3745
3746
3747( function() {
3748 var div = document.createElement( "div" );
3749
3750 // Support: IE<9
3751 support.deleteExpando = true;
3752 try {
3753 delete div.test;
3754 } catch ( e ) {
3755 support.deleteExpando = false;
3756 }
3757
3758 // Null elements to avoid leaks in IE.
3759 div = null;
3760} )();
3761var acceptData = function( elem ) {
3762 var noData = jQuery.noData[ ( elem.nodeName + " " ).toLowerCase() ],
3763 nodeType = +elem.nodeType || 1;
3764
3765 // Do not set data on non-element DOM nodes because it will not be cleared (#8335).
3766 return nodeType !== 1 && nodeType !== 9 ?
3767 false :
3768
3769 // Nodes accept data unless otherwise specified; rejection can be conditional
3770 !noData || noData !== true && elem.getAttribute( "classid" ) === noData;
3771};
3772
3773
3774
3775
3776var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
3777 rmultiDash = /([A-Z])/g;
3778
3779function dataAttr( elem, key, data ) {
3780
3781 // If nothing was found internally, try to fetch any
3782 // data from the HTML5 data-* attribute
3783 if ( data === undefined && elem.nodeType === 1 ) {
3784
3785 var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
3786
3787 data = elem.getAttribute( name );
3788
3789 if ( typeof data === "string" ) {
3790 try {
3791 data = data === "true" ? true :
3792 data === "false" ? false :
3793 data === "null" ? null :
3794
3795 // Only convert to a number if it doesn't change the string
3796 +data + "" === data ? +data :
3797 rbrace.test( data ) ? jQuery.parseJSON( data ) :
3798 data;
3799 } catch ( e ) {}
3800
3801 // Make sure we set the data so it isn't changed later
3802 jQuery.data( elem, key, data );
3803
3804 } else {
3805 data = undefined;
3806 }
3807 }
3808
3809 return data;
3810}
3811
3812// checks a cache object for emptiness
3813function isEmptyDataObject( obj ) {
3814 var name;
3815 for ( name in obj ) {
3816
3817 // if the public data object is empty, the private is still empty
3818 if ( name === "data" && jQuery.isEmptyObject( obj[ name ] ) ) {
3819 continue;
3820 }
3821 if ( name !== "toJSON" ) {
3822 return false;
3823 }
3824 }
3825
3826 return true;
3827}
3828
3829function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
3830 if ( !acceptData( elem ) ) {
3831 return;
3832 }
3833
3834 var ret, thisCache,
3835 internalKey = jQuery.expando,
3836
3837 // We have to handle DOM nodes and JS objects differently because IE6-7
3838 // can't GC object references properly across the DOM-JS boundary
3839 isNode = elem.nodeType,
3840
3841 // Only DOM nodes need the global jQuery cache; JS object data is
3842 // attached directly to the object so GC can occur automatically
3843 cache = isNode ? jQuery.cache : elem,
3844
3845 // Only defining an ID for JS objects if its cache already exists allows
3846 // the code to shortcut on the same path as a DOM node with no cache
3847 id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
3848
3849 // Avoid doing any more work than we need to when trying to get data on an
3850 // object that has no data at all
3851 if ( ( !id || !cache[ id ] || ( !pvt && !cache[ id ].data ) ) &&
3852 data === undefined && typeof name === "string" ) {
3853 return;
3854 }
3855
3856 if ( !id ) {
3857
3858 // Only DOM nodes need a new unique ID for each element since their data
3859 // ends up in the global cache
3860 if ( isNode ) {
3861 id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
3862 } else {
3863 id = internalKey;
3864 }
3865 }
3866
3867 if ( !cache[ id ] ) {
3868
3869 // Avoid exposing jQuery metadata on plain JS objects when the object
3870 // is serialized using JSON.stringify
3871 cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
3872 }
3873
3874 // An object can be passed to jQuery.data instead of a key/value pair; this gets
3875 // shallow copied over onto the existing cache
3876 if ( typeof name === "object" || typeof name === "function" ) {
3877 if ( pvt ) {
3878 cache[ id ] = jQuery.extend( cache[ id ], name );
3879 } else {
3880 cache[ id ].data = jQuery.extend( cache[ id ].data, name );
3881 }
3882 }
3883
3884 thisCache = cache[ id ];
3885
3886 // jQuery data() is stored in a separate object inside the object's internal data
3887 // cache in order to avoid key collisions between internal data and user-defined
3888 // data.
3889 if ( !pvt ) {
3890 if ( !thisCache.data ) {
3891 thisCache.data = {};
3892 }
3893
3894 thisCache = thisCache.data;
3895 }
3896
3897 if ( data !== undefined ) {
3898 thisCache[ jQuery.camelCase( name ) ] = data;
3899 }
3900
3901 // Check for both converted-to-camel and non-converted data property names
3902 // If a data property was specified
3903 if ( typeof name === "string" ) {
3904
3905 // First Try to find as-is property data
3906 ret = thisCache[ name ];
3907
3908 // Test for null|undefined property data
3909 if ( ret == null ) {
3910
3911 // Try to find the camelCased property
3912 ret = thisCache[ jQuery.camelCase( name ) ];
3913 }
3914 } else {
3915 ret = thisCache;
3916 }
3917
3918 return ret;
3919}
3920
3921function internalRemoveData( elem, name, pvt ) {
3922 if ( !acceptData( elem ) ) {
3923 return;
3924 }
3925
3926 var thisCache, i,
3927 isNode = elem.nodeType,
3928
3929 // See jQuery.data for more information
3930 cache = isNode ? jQuery.cache : elem,
3931 id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
3932
3933 // If there is already no cache entry for this object, there is no
3934 // purpose in continuing
3935 if ( !cache[ id ] ) {
3936 return;
3937 }
3938
3939 if ( name ) {
3940
3941 thisCache = pvt ? cache[ id ] : cache[ id ].data;
3942
3943 if ( thisCache ) {
3944
3945 // Support array or space separated string names for data keys
3946 if ( !jQuery.isArray( name ) ) {
3947
3948 // try the string as a key before any manipulation
3949 if ( name in thisCache ) {
3950 name = [ name ];
3951 } else {
3952
3953 // split the camel cased version by spaces unless a key with the spaces exists
3954 name = jQuery.camelCase( name );
3955 if ( name in thisCache ) {
3956 name = [ name ];
3957 } else {
3958 name = name.split( " " );
3959 }
3960 }
3961 } else {
3962
3963 // If "name" is an array of keys...
3964 // When data is initially created, via ("key", "val") signature,
3965 // keys will be converted to camelCase.
3966 // Since there is no way to tell _how_ a key was added, remove
3967 // both plain key and camelCase key. #12786
3968 // This will only penalize the array argument path.
3969 name = name.concat( jQuery.map( name, jQuery.camelCase ) );
3970 }
3971
3972 i = name.length;
3973 while ( i-- ) {
3974 delete thisCache[ name[ i ] ];
3975 }
3976
3977 // If there is no data left in the cache, we want to continue
3978 // and let the cache object itself get destroyed
3979 if ( pvt ? !isEmptyDataObject( thisCache ) : !jQuery.isEmptyObject( thisCache ) ) {
3980 return;
3981 }
3982 }
3983 }
3984
3985 // See jQuery.data for more information
3986 if ( !pvt ) {
3987 delete cache[ id ].data;
3988
3989 // Don't destroy the parent cache unless the internal data object
3990 // had been the only thing left in it
3991 if ( !isEmptyDataObject( cache[ id ] ) ) {
3992 return;
3993 }
3994 }
3995
3996 // Destroy the cache
3997 if ( isNode ) {
3998 jQuery.cleanData( [ elem ], true );
3999
4000 // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
4001 /* jshint eqeqeq: false */
4002 } else if ( support.deleteExpando || cache != cache.window ) {
4003 /* jshint eqeqeq: true */
4004 delete cache[ id ];
4005
4006 // When all else fails, undefined
4007 } else {
4008 cache[ id ] = undefined;
4009 }
4010}
4011
4012jQuery.extend( {
4013 cache: {},
4014
4015 // The following elements (space-suffixed to avoid Object.prototype collisions)
4016 // throw uncatchable exceptions if you attempt to set expando properties
4017 noData: {
4018 "applet ": true,
4019 "embed ": true,
4020
4021 // ...but Flash objects (which have this classid) *can* handle expandos
4022 "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
4023 },
4024
4025 hasData: function( elem ) {
4026 elem = elem.nodeType ? jQuery.cache[ elem[ jQuery.expando ] ] : elem[ jQuery.expando ];
4027 return !!elem && !isEmptyDataObject( elem );
4028 },
4029
4030 data: function( elem, name, data ) {
4031 return internalData( elem, name, data );
4032 },
4033
4034 removeData: function( elem, name ) {
4035 return internalRemoveData( elem, name );
4036 },
4037
4038 // For internal use only.
4039 _data: function( elem, name, data ) {
4040 return internalData( elem, name, data, true );
4041 },
4042
4043 _removeData: function( elem, name ) {
4044 return internalRemoveData( elem, name, true );
4045 }
4046} );
4047
4048jQuery.fn.extend( {
4049 data: function( key, value ) {
4050 var i, name, data,
4051 elem = this[ 0 ],
4052 attrs = elem && elem.attributes;
4053
4054 // Special expections of .data basically thwart jQuery.access,
4055 // so implement the relevant behavior ourselves
4056
4057 // Gets all values
4058 if ( key === undefined ) {
4059 if ( this.length ) {
4060 data = jQuery.data( elem );
4061
4062 if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
4063 i = attrs.length;
4064 while ( i-- ) {
4065
4066 // Support: IE11+
4067 // The attrs elements can be null (#14894)
4068 if ( attrs[ i ] ) {
4069 name = attrs[ i ].name;
4070 if ( name.indexOf( "data-" ) === 0 ) {
4071 name = jQuery.camelCase( name.slice( 5 ) );
4072 dataAttr( elem, name, data[ name ] );
4073 }
4074 }
4075 }
4076 jQuery._data( elem, "parsedAttrs", true );
4077 }
4078 }
4079
4080 return data;
4081 }
4082
4083 // Sets multiple values
4084 if ( typeof key === "object" ) {
4085 return this.each( function() {
4086 jQuery.data( this, key );
4087 } );
4088 }
4089
4090 return arguments.length > 1 ?
4091
4092 // Sets one value
4093 this.each( function() {
4094 jQuery.data( this, key, value );
4095 } ) :
4096
4097 // Gets one value
4098 // Try to fetch any internally stored data first
4099 elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;
4100 },
4101
4102 removeData: function( key ) {
4103 return this.each( function() {
4104 jQuery.removeData( this, key );
4105 } );
4106 }
4107} );
4108
4109
4110jQuery.extend( {
4111 queue: function( elem, type, data ) {
4112 var queue;
4113
4114 if ( elem ) {
4115 type = ( type || "fx" ) + "queue";
4116 queue = jQuery._data( elem, type );
4117
4118 // Speed up dequeue by getting out quickly if this is just a lookup
4119 if ( data ) {
4120 if ( !queue || jQuery.isArray( data ) ) {
4121 queue = jQuery._data( elem, type, jQuery.makeArray( data ) );
4122 } else {
4123 queue.push( data );
4124 }
4125 }
4126 return queue || [];
4127 }
4128 },
4129
4130 dequeue: function( elem, type ) {
4131 type = type || "fx";
4132
4133 var queue = jQuery.queue( elem, type ),
4134 startLength = queue.length,
4135 fn = queue.shift(),
4136 hooks = jQuery._queueHooks( elem, type ),
4137 next = function() {
4138 jQuery.dequeue( elem, type );
4139 };
4140
4141 // If the fx queue is dequeued, always remove the progress sentinel
4142 if ( fn === "inprogress" ) {
4143 fn = queue.shift();
4144 startLength--;
4145 }
4146
4147 if ( fn ) {
4148
4149 // Add a progress sentinel to prevent the fx queue from being
4150 // automatically dequeued
4151 if ( type === "fx" ) {
4152 queue.unshift( "inprogress" );
4153 }
4154
4155 // clear up the last queue stop function
4156 delete hooks.stop;
4157 fn.call( elem, next, hooks );
4158 }
4159
4160 if ( !startLength && hooks ) {
4161 hooks.empty.fire();
4162 }
4163 },
4164
4165 // not intended for public consumption - generates a queueHooks object,
4166 // or returns the current one
4167 _queueHooks: function( elem, type ) {
4168 var key = type + "queueHooks";
4169 return jQuery._data( elem, key ) || jQuery._data( elem, key, {
4170 empty: jQuery.Callbacks( "once memory" ).add( function() {
4171 jQuery._removeData( elem, type + "queue" );
4172 jQuery._removeData( elem, key );
4173 } )
4174 } );
4175 }
4176} );
4177
4178jQuery.fn.extend( {
4179 queue: function( type, data ) {
4180 var setter = 2;
4181
4182 if ( typeof type !== "string" ) {
4183 data = type;
4184 type = "fx";
4185 setter--;
4186 }
4187
4188 if ( arguments.length < setter ) {
4189 return jQuery.queue( this[ 0 ], type );
4190 }
4191
4192 return data === undefined ?
4193 this :
4194 this.each( function() {
4195 var queue = jQuery.queue( this, type, data );
4196
4197 // ensure a hooks for this queue
4198 jQuery._queueHooks( this, type );
4199
4200 if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
4201 jQuery.dequeue( this, type );
4202 }
4203 } );
4204 },
4205 dequeue: function( type ) {
4206 return this.each( function() {
4207 jQuery.dequeue( this, type );
4208 } );
4209 },
4210 clearQueue: function( type ) {
4211 return this.queue( type || "fx", [] );
4212 },
4213
4214 // Get a promise resolved when queues of a certain type
4215 // are emptied (fx is the type by default)
4216 promise: function( type, obj ) {
4217 var tmp,
4218 count = 1,
4219 defer = jQuery.Deferred(),
4220 elements = this,
4221 i = this.length,
4222 resolve = function() {
4223 if ( !( --count ) ) {
4224 defer.resolveWith( elements, [ elements ] );
4225 }
4226 };
4227
4228 if ( typeof type !== "string" ) {
4229 obj = type;
4230 type = undefined;
4231 }
4232 type = type || "fx";
4233
4234 while ( i-- ) {
4235 tmp = jQuery._data( elements[ i ], type + "queueHooks" );
4236 if ( tmp && tmp.empty ) {
4237 count++;
4238 tmp.empty.add( resolve );
4239 }
4240 }
4241 resolve();
4242 return defer.promise( obj );
4243 }
4244} );
4245
4246
4247( function() {
4248 var shrinkWrapBlocksVal;
4249
4250 support.shrinkWrapBlocks = function() {
4251 if ( shrinkWrapBlocksVal != null ) {
4252 return shrinkWrapBlocksVal;
4253 }
4254
4255 // Will be changed later if needed.
4256 shrinkWrapBlocksVal = false;
4257
4258 // Minified: var b,c,d
4259 var div, body, container;
4260
4261 body = document.getElementsByTagName( "body" )[ 0 ];
4262 if ( !body || !body.style ) {
4263
4264 // Test fired too early or in an unsupported environment, exit.
4265 return;
4266 }
4267
4268 // Setup
4269 div = document.createElement( "div" );
4270 container = document.createElement( "div" );
4271 container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
4272 body.appendChild( container ).appendChild( div );
4273
4274 // Support: IE6
4275 // Check if elements with layout shrink-wrap their children
4276 if ( typeof div.style.zoom !== "undefined" ) {
4277
4278 // Reset CSS: box-sizing; display; margin; border
4279 div.style.cssText =
4280
4281 // Support: Firefox<29, Android 2.3
4282 // Vendor-prefix box-sizing
4283 "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
4284 "box-sizing:content-box;display:block;margin:0;border:0;" +
4285 "padding:1px;width:1px;zoom:1";
4286 div.appendChild( document.createElement( "div" ) ).style.width = "5px";
4287 shrinkWrapBlocksVal = div.offsetWidth !== 3;
4288 }
4289
4290 body.removeChild( container );
4291
4292 return shrinkWrapBlocksVal;
4293 };
4294
4295} )();
4296var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
4297
4298var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
4299
4300
4301var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
4302
4303var isHidden = function( elem, el ) {
4304
4305 // isHidden might be called from jQuery#filter function;
4306 // in that case, element will be second argument
4307 elem = el || elem;
4308 return jQuery.css( elem, "display" ) === "none" ||
4309 !jQuery.contains( elem.ownerDocument, elem );
4310 };
4311
4312
4313
4314function adjustCSS( elem, prop, valueParts, tween ) {
4315 var adjusted,
4316 scale = 1,
4317 maxIterations = 20,
4318 currentValue = tween ?
4319 function() { return tween.cur(); } :
4320 function() { return jQuery.css( elem, prop, "" ); },
4321 initial = currentValue(),
4322 unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
4323
4324 // Starting value computation is required for potential unit mismatches
4325 initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
4326 rcssNum.exec( jQuery.css( elem, prop ) );
4327
4328 if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
4329
4330 // Trust units reported by jQuery.css
4331 unit = unit || initialInUnit[ 3 ];
4332
4333 // Make sure we update the tween properties later on
4334 valueParts = valueParts || [];
4335
4336 // Iteratively approximate from a nonzero starting point
4337 initialInUnit = +initial || 1;
4338
4339 do {
4340
4341 // If previous iteration zeroed out, double until we get *something*.
4342 // Use string for doubling so we don't accidentally see scale as unchanged below
4343 scale = scale || ".5";
4344
4345 // Adjust and apply
4346 initialInUnit = initialInUnit / scale;
4347 jQuery.style( elem, prop, initialInUnit + unit );
4348
4349 // Update scale, tolerating zero or NaN from tween.cur()
4350 // Break the loop if scale is unchanged or perfect, or if we've just had enough.
4351 } while (
4352 scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
4353 );
4354 }
4355
4356 if ( valueParts ) {
4357 initialInUnit = +initialInUnit || +initial || 0;
4358
4359 // Apply relative offset (+=/-=) if specified
4360 adjusted = valueParts[ 1 ] ?
4361 initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
4362 +valueParts[ 2 ];
4363 if ( tween ) {
4364 tween.unit = unit;
4365 tween.start = initialInUnit;
4366 tween.end = adjusted;
4367 }
4368 }
4369 return adjusted;
4370}
4371
4372
4373// Multifunctional method to get and set values of a collection
4374// The value/s can optionally be executed if it's a function
4375var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
4376 var i = 0,
4377 length = elems.length,
4378 bulk = key == null;
4379
4380 // Sets many values
4381 if ( jQuery.type( key ) === "object" ) {
4382 chainable = true;
4383 for ( i in key ) {
4384 access( elems, fn, i, key[ i ], true, emptyGet, raw );
4385 }
4386
4387 // Sets one value
4388 } else if ( value !== undefined ) {
4389 chainable = true;
4390
4391 if ( !jQuery.isFunction( value ) ) {
4392 raw = true;
4393 }
4394
4395 if ( bulk ) {
4396
4397 // Bulk operations run against the entire set
4398 if ( raw ) {
4399 fn.call( elems, value );
4400 fn = null;
4401
4402 // ...except when executing function values
4403 } else {
4404 bulk = fn;
4405 fn = function( elem, key, value ) {
4406 return bulk.call( jQuery( elem ), value );
4407 };
4408 }
4409 }
4410
4411 if ( fn ) {
4412 for ( ; i < length; i++ ) {
4413 fn(
4414 elems[ i ],
4415 key,
4416 raw ? value : value.call( elems[ i ], i, fn( elems[ i ], key ) )
4417 );
4418 }
4419 }
4420 }
4421
4422 return chainable ?
4423 elems :
4424
4425 // Gets
4426 bulk ?
4427 fn.call( elems ) :
4428 length ? fn( elems[ 0 ], key ) : emptyGet;
4429};
4430var rcheckableType = ( /^(?:checkbox|radio)$/i );
4431
4432var rtagName = ( /<([\w:-]+)/ );
4433
4434var rscriptType = ( /^$|\/(?:java|ecma)script/i );
4435
4436var rleadingWhitespace = ( /^\s+/ );
4437
4438var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|" +
4439 "details|dialog|figcaption|figure|footer|header|hgroup|main|" +
4440 "mark|meter|nav|output|picture|progress|section|summary|template|time|video";
4441
4442
4443
4444function createSafeFragment( document ) {
4445 var list = nodeNames.split( "|" ),
4446 safeFrag = document.createDocumentFragment();
4447
4448 if ( safeFrag.createElement ) {
4449 while ( list.length ) {
4450 safeFrag.createElement(
4451 list.pop()
4452 );
4453 }
4454 }
4455 return safeFrag;
4456}
4457
4458
4459( function() {
4460 var div = document.createElement( "div" ),
4461 fragment = document.createDocumentFragment(),
4462 input = document.createElement( "input" );
4463
4464 // Setup
4465 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
4466
4467 // IE strips leading whitespace when .innerHTML is used
4468 support.leadingWhitespace = div.firstChild.nodeType === 3;
4469
4470 // Make sure that tbody elements aren't automatically inserted
4471 // IE will insert them into empty tables
4472 support.tbody = !div.getElementsByTagName( "tbody" ).length;
4473
4474 // Make sure that link elements get serialized correctly by innerHTML
4475 // This requires a wrapper element in IE
4476 support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;
4477
4478 // Makes sure cloning an html5 element does not cause problems
4479 // Where outerHTML is undefined, this still works
4480 support.html5Clone =
4481 document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>";
4482
4483 // Check if a disconnected checkbox will retain its checked
4484 // value of true after appended to the DOM (IE6/7)
4485 input.type = "checkbox";
4486 input.checked = true;
4487 fragment.appendChild( input );
4488 support.appendChecked = input.checked;
4489
4490 // Make sure textarea (and checkbox) defaultValue is properly cloned
4491 // Support: IE6-IE11+
4492 div.innerHTML = "<textarea>x</textarea>";
4493 support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
4494
4495 // #11217 - WebKit loses check when the name is after the checked attribute
4496 fragment.appendChild( div );
4497
4498 // Support: Windows Web Apps (WWA)
4499 // `name` and `type` must use .setAttribute for WWA (#14901)
4500 input = document.createElement( "input" );
4501 input.setAttribute( "type", "radio" );
4502 input.setAttribute( "checked", "checked" );
4503 input.setAttribute( "name", "t" );
4504
4505 div.appendChild( input );
4506
4507 // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
4508 // old WebKit doesn't clone checked state correctly in fragments
4509 support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
4510
4511 // Support: IE<9
4512 // Cloned elements keep attachEvent handlers, we use addEventListener on IE9+
4513 support.noCloneEvent = !!div.addEventListener;
4514
4515 // Support: IE<9
4516 // Since attributes and properties are the same in IE,
4517 // cleanData must set properties to undefined rather than use removeAttribute
4518 div[ jQuery.expando ] = 1;
4519 support.attributes = !div.getAttribute( jQuery.expando );
4520} )();
4521
4522
4523// We have to close these tags to support XHTML (#13200)
4524var wrapMap = {
4525 option: [ 1, "<select multiple='multiple'>", "</select>" ],
4526 legend: [ 1, "<fieldset>", "</fieldset>" ],
4527 area: [ 1, "<map>", "</map>" ],
4528
4529 // Support: IE8
4530 param: [ 1, "<object>", "</object>" ],
4531 thead: [ 1, "<table>", "</table>" ],
4532 tr: [ 2, "<table><tbody>", "</tbody></table>" ],
4533 col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
4534 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
4535
4536 // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
4537 // unless wrapped in a div with non-breaking characters in front of it.
4538 _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
4539};
4540
4541// Support: IE8-IE9
4542wrapMap.optgroup = wrapMap.option;
4543
4544wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
4545wrapMap.th = wrapMap.td;
4546
4547
4548function getAll( context, tag ) {
4549 var elems, elem,
4550 i = 0,
4551 found = typeof context.getElementsByTagName !== "undefined" ?
4552 context.getElementsByTagName( tag || "*" ) :
4553 typeof context.querySelectorAll !== "undefined" ?
4554 context.querySelectorAll( tag || "*" ) :
4555 undefined;
4556
4557 if ( !found ) {
4558 for ( found = [], elems = context.childNodes || context;
4559 ( elem = elems[ i ] ) != null;
4560 i++
4561 ) {
4562 if ( !tag || jQuery.nodeName( elem, tag ) ) {
4563 found.push( elem );
4564 } else {
4565 jQuery.merge( found, getAll( elem, tag ) );
4566 }
4567 }
4568 }
4569
4570 return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
4571 jQuery.merge( [ context ], found ) :
4572 found;
4573}
4574
4575
4576// Mark scripts as having already been evaluated
4577function setGlobalEval( elems, refElements ) {
4578 var elem,
4579 i = 0;
4580 for ( ; ( elem = elems[ i ] ) != null; i++ ) {
4581 jQuery._data(
4582 elem,
4583 "globalEval",
4584 !refElements || jQuery._data( refElements[ i ], "globalEval" )
4585 );
4586 }
4587}
4588
4589
4590var rhtml = /<|&#?\w+;/,
4591 rtbody = /<tbody/i;
4592
4593function fixDefaultChecked( elem ) {
4594 if ( rcheckableType.test( elem.type ) ) {
4595 elem.defaultChecked = elem.checked;
4596 }
4597}
4598
4599function buildFragment( elems, context, scripts, selection, ignored ) {
4600 var j, elem, contains,
4601 tmp, tag, tbody, wrap,
4602 l = elems.length,
4603
4604 // Ensure a safe fragment
4605 safe = createSafeFragment( context ),
4606
4607 nodes = [],
4608 i = 0;
4609
4610 for ( ; i < l; i++ ) {
4611 elem = elems[ i ];
4612
4613 if ( elem || elem === 0 ) {
4614
4615 // Add nodes directly
4616 if ( jQuery.type( elem ) === "object" ) {
4617 jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
4618
4619 // Convert non-html into a text node
4620 } else if ( !rhtml.test( elem ) ) {
4621 nodes.push( context.createTextNode( elem ) );
4622
4623 // Convert html into DOM nodes
4624 } else {
4625 tmp = tmp || safe.appendChild( context.createElement( "div" ) );
4626
4627 // Deserialize a standard representation
4628 tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
4629 wrap = wrapMap[ tag ] || wrapMap._default;
4630
4631 tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
4632
4633 // Descend through wrappers to the right content
4634 j = wrap[ 0 ];
4635 while ( j-- ) {
4636 tmp = tmp.lastChild;
4637 }
4638
4639 // Manually add leading whitespace removed by IE
4640 if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
4641 nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[ 0 ] ) );
4642 }
4643
4644 // Remove IE's autoinserted <tbody> from table fragments
4645 if ( !support.tbody ) {
4646
4647 // String was a <table>, *may* have spurious <tbody>
4648 elem = tag === "table" && !rtbody.test( elem ) ?
4649 tmp.firstChild :
4650
4651 // String was a bare <thead> or <tfoot>
4652 wrap[ 1 ] === "<table>" && !rtbody.test( elem ) ?
4653 tmp :
4654 0;
4655
4656 j = elem && elem.childNodes.length;
4657 while ( j-- ) {
4658 if ( jQuery.nodeName( ( tbody = elem.childNodes[ j ] ), "tbody" ) &&
4659 !tbody.childNodes.length ) {
4660
4661 elem.removeChild( tbody );
4662 }
4663 }
4664 }
4665
4666 jQuery.merge( nodes, tmp.childNodes );
4667
4668 // Fix #12392 for WebKit and IE > 9
4669 tmp.textContent = "";
4670
4671 // Fix #12392 for oldIE
4672 while ( tmp.firstChild ) {
4673 tmp.removeChild( tmp.firstChild );
4674 }
4675
4676 // Remember the top-level container for proper cleanup
4677 tmp = safe.lastChild;
4678 }
4679 }
4680 }
4681
4682 // Fix #11356: Clear elements from fragment
4683 if ( tmp ) {
4684 safe.removeChild( tmp );
4685 }
4686
4687 // Reset defaultChecked for any radios and checkboxes
4688 // about to be appended to the DOM in IE 6/7 (#8060)
4689 if ( !support.appendChecked ) {
4690 jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
4691 }
4692
4693 i = 0;
4694 while ( ( elem = nodes[ i++ ] ) ) {
4695
4696 // Skip elements already in the context collection (trac-4087)
4697 if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
4698 if ( ignored ) {
4699 ignored.push( elem );
4700 }
4701
4702 continue;
4703 }
4704
4705 contains = jQuery.contains( elem.ownerDocument, elem );
4706
4707 // Append to fragment
4708 tmp = getAll( safe.appendChild( elem ), "script" );
4709
4710 // Preserve script evaluation history
4711 if ( contains ) {
4712 setGlobalEval( tmp );
4713 }
4714
4715 // Capture executables
4716 if ( scripts ) {
4717 j = 0;
4718 while ( ( elem = tmp[ j++ ] ) ) {
4719 if ( rscriptType.test( elem.type || "" ) ) {
4720 scripts.push( elem );
4721 }
4722 }
4723 }
4724 }
4725
4726 tmp = null;
4727
4728 return safe;
4729}
4730
4731
4732( function() {
4733 var i, eventName,
4734 div = document.createElement( "div" );
4735
4736 // Support: IE<9 (lack submit/change bubble), Firefox (lack focus(in | out) events)
4737 for ( i in { submit: true, change: true, focusin: true } ) {
4738 eventName = "on" + i;
4739
4740 if ( !( support[ i ] = eventName in window ) ) {
4741
4742 // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
4743 div.setAttribute( eventName, "t" );
4744 support[ i ] = div.attributes[ eventName ].expando === false;
4745 }
4746 }
4747
4748 // Null elements to avoid leaks in IE.
4749 div = null;
4750} )();
4751
4752
4753var rformElems = /^(?:input|select|textarea)$/i,
4754 rkeyEvent = /^key/,
4755 rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
4756 rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
4757 rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
4758
4759function returnTrue() {
4760 return true;
4761}
4762
4763function returnFalse() {
4764 return false;
4765}
4766
4767// Support: IE9
4768// See #13393 for more info
4769function safeActiveElement() {
4770 try {
4771 return document.activeElement;
4772 } catch ( err ) { }
4773}
4774
4775function on( elem, types, selector, data, fn, one ) {
4776 var origFn, type;
4777
4778 // Types can be a map of types/handlers
4779 if ( typeof types === "object" ) {
4780
4781 // ( types-Object, selector, data )
4782 if ( typeof selector !== "string" ) {
4783
4784 // ( types-Object, data )
4785 data = data || selector;
4786 selector = undefined;
4787 }
4788 for ( type in types ) {
4789 on( elem, type, selector, data, types[ type ], one );
4790 }
4791 return elem;
4792 }
4793
4794 if ( data == null && fn == null ) {
4795
4796 // ( types, fn )
4797 fn = selector;
4798 data = selector = undefined;
4799 } else if ( fn == null ) {
4800 if ( typeof selector === "string" ) {
4801
4802 // ( types, selector, fn )
4803 fn = data;
4804 data = undefined;
4805 } else {
4806
4807 // ( types, data, fn )
4808 fn = data;
4809 data = selector;
4810 selector = undefined;
4811 }
4812 }
4813 if ( fn === false ) {
4814 fn = returnFalse;
4815 } else if ( !fn ) {
4816 return elem;
4817 }
4818
4819 if ( one === 1 ) {
4820 origFn = fn;
4821 fn = function( event ) {
4822
4823 // Can use an empty set, since event contains the info
4824 jQuery().off( event );
4825 return origFn.apply( this, arguments );
4826 };
4827
4828 // Use same guid so caller can remove using origFn
4829 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
4830 }
4831 return elem.each( function() {
4832 jQuery.event.add( this, types, fn, data, selector );
4833 } );
4834}
4835
4836/*
4837 * Helper functions for managing events -- not part of the public interface.
4838 * Props to Dean Edwards' addEvent library for many of the ideas.
4839 */
4840jQuery.event = {
4841
4842 global: {},
4843
4844 add: function( elem, types, handler, data, selector ) {
4845 var tmp, events, t, handleObjIn,
4846 special, eventHandle, handleObj,
4847 handlers, type, namespaces, origType,
4848 elemData = jQuery._data( elem );
4849
4850 // Don't attach events to noData or text/comment nodes (but allow plain objects)
4851 if ( !elemData ) {
4852 return;
4853 }
4854
4855 // Caller can pass in an object of custom data in lieu of the handler
4856 if ( handler.handler ) {
4857 handleObjIn = handler;
4858 handler = handleObjIn.handler;
4859 selector = handleObjIn.selector;
4860 }
4861
4862 // Make sure that the handler has a unique ID, used to find/remove it later
4863 if ( !handler.guid ) {
4864 handler.guid = jQuery.guid++;
4865 }
4866
4867 // Init the element's event structure and main handler, if this is the first
4868 if ( !( events = elemData.events ) ) {
4869 events = elemData.events = {};
4870 }
4871 if ( !( eventHandle = elemData.handle ) ) {
4872 eventHandle = elemData.handle = function( e ) {
4873
4874 // Discard the second event of a jQuery.event.trigger() and
4875 // when an event is called after a page has unloaded
4876 return typeof jQuery !== "undefined" &&
4877 ( !e || jQuery.event.triggered !== e.type ) ?
4878 jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
4879 undefined;
4880 };
4881
4882 // Add elem as a property of the handle fn to prevent a memory leak
4883 // with IE non-native events
4884 eventHandle.elem = elem;
4885 }
4886
4887 // Handle multiple events separated by a space
4888 types = ( types || "" ).match( rnotwhite ) || [ "" ];
4889 t = types.length;
4890 while ( t-- ) {
4891 tmp = rtypenamespace.exec( types[ t ] ) || [];
4892 type = origType = tmp[ 1 ];
4893 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
4894
4895 // There *must* be a type, no attaching namespace-only handlers
4896 if ( !type ) {
4897 continue;
4898 }
4899
4900 // If event changes its type, use the special event handlers for the changed type
4901 special = jQuery.event.special[ type ] || {};
4902
4903 // If selector defined, determine special event api type, otherwise given type
4904 type = ( selector ? special.delegateType : special.bindType ) || type;
4905
4906 // Update special based on newly reset type
4907 special = jQuery.event.special[ type ] || {};
4908
4909 // handleObj is passed to all event handlers
4910 handleObj = jQuery.extend( {
4911 type: type,
4912 origType: origType,
4913 data: data,
4914 handler: handler,
4915 guid: handler.guid,
4916 selector: selector,
4917 needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
4918 namespace: namespaces.join( "." )
4919 }, handleObjIn );
4920
4921 // Init the event handler queue if we're the first
4922 if ( !( handlers = events[ type ] ) ) {
4923 handlers = events[ type ] = [];
4924 handlers.delegateCount = 0;
4925
4926 // Only use addEventListener/attachEvent if the special events handler returns false
4927 if ( !special.setup ||
4928 special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
4929
4930 // Bind the global event handler to the element
4931 if ( elem.addEventListener ) {
4932 elem.addEventListener( type, eventHandle, false );
4933
4934 } else if ( elem.attachEvent ) {
4935 elem.attachEvent( "on" + type, eventHandle );
4936 }
4937 }
4938 }
4939
4940 if ( special.add ) {
4941 special.add.call( elem, handleObj );
4942
4943 if ( !handleObj.handler.guid ) {
4944 handleObj.handler.guid = handler.guid;
4945 }
4946 }
4947
4948 // Add to the element's handler list, delegates in front
4949 if ( selector ) {
4950 handlers.splice( handlers.delegateCount++, 0, handleObj );
4951 } else {
4952 handlers.push( handleObj );
4953 }
4954
4955 // Keep track of which events have ever been used, for event optimization
4956 jQuery.event.global[ type ] = true;
4957 }
4958
4959 // Nullify elem to prevent memory leaks in IE
4960 elem = null;
4961 },
4962
4963 // Detach an event or set of events from an element
4964 remove: function( elem, types, handler, selector, mappedTypes ) {
4965 var j, handleObj, tmp,
4966 origCount, t, events,
4967 special, handlers, type,
4968 namespaces, origType,
4969 elemData = jQuery.hasData( elem ) && jQuery._data( elem );
4970
4971 if ( !elemData || !( events = elemData.events ) ) {
4972 return;
4973 }
4974
4975 // Once for each type.namespace in types; type may be omitted
4976 types = ( types || "" ).match( rnotwhite ) || [ "" ];
4977 t = types.length;
4978 while ( t-- ) {
4979 tmp = rtypenamespace.exec( types[ t ] ) || [];
4980 type = origType = tmp[ 1 ];
4981 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
4982
4983 // Unbind all events (on this namespace, if provided) for the element
4984 if ( !type ) {
4985 for ( type in events ) {
4986 jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
4987 }
4988 continue;
4989 }
4990
4991 special = jQuery.event.special[ type ] || {};
4992 type = ( selector ? special.delegateType : special.bindType ) || type;
4993 handlers = events[ type ] || [];
4994 tmp = tmp[ 2 ] &&
4995 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
4996
4997 // Remove matching events
4998 origCount = j = handlers.length;
4999 while ( j-- ) {
5000 handleObj = handlers[ j ];
5001
5002 if ( ( mappedTypes || origType === handleObj.origType ) &&
5003 ( !handler || handler.guid === handleObj.guid ) &&
5004 ( !tmp || tmp.test( handleObj.namespace ) ) &&
5005 ( !selector || selector === handleObj.selector ||
5006 selector === "**" && handleObj.selector ) ) {
5007 handlers.splice( j, 1 );
5008
5009 if ( handleObj.selector ) {
5010 handlers.delegateCount--;
5011 }
5012 if ( special.remove ) {
5013 special.remove.call( elem, handleObj );
5014 }
5015 }
5016 }
5017
5018 // Remove generic event handler if we removed something and no more handlers exist
5019 // (avoids potential for endless recursion during removal of special event handlers)
5020 if ( origCount && !handlers.length ) {
5021 if ( !special.teardown ||
5022 special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
5023
5024 jQuery.removeEvent( elem, type, elemData.handle );
5025 }
5026
5027 delete events[ type ];
5028 }
5029 }
5030
5031 // Remove the expando if it's no longer used
5032 if ( jQuery.isEmptyObject( events ) ) {
5033 delete elemData.handle;
5034
5035 // removeData also checks for emptiness and clears the expando if empty
5036 // so use it instead of delete
5037 jQuery._removeData( elem, "events" );
5038 }
5039 },
5040
5041 trigger: function( event, data, elem, onlyHandlers ) {
5042 var handle, ontype, cur,
5043 bubbleType, special, tmp, i,
5044 eventPath = [ elem || document ],
5045 type = hasOwn.call( event, "type" ) ? event.type : event,
5046 namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
5047
5048 cur = tmp = elem = elem || document;
5049
5050 // Don't do events on text and comment nodes
5051 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
5052 return;
5053 }
5054
5055 // focus/blur morphs to focusin/out; ensure we're not firing them right now
5056 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
5057 return;
5058 }
5059
5060 if ( type.indexOf( "." ) > -1 ) {
5061
5062 // Namespaced trigger; create a regexp to match event type in handle()
5063 namespaces = type.split( "." );
5064 type = namespaces.shift();
5065 namespaces.sort();
5066 }
5067 ontype = type.indexOf( ":" ) < 0 && "on" + type;
5068
5069 // Caller can pass in a jQuery.Event object, Object, or just an event type string
5070 event = event[ jQuery.expando ] ?
5071 event :
5072 new jQuery.Event( type, typeof event === "object" && event );
5073
5074 // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
5075 event.isTrigger = onlyHandlers ? 2 : 3;
5076 event.namespace = namespaces.join( "." );
5077 event.rnamespace = event.namespace ?
5078 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
5079 null;
5080
5081 // Clean up the event in case it is being reused
5082 event.result = undefined;
5083 if ( !event.target ) {
5084 event.target = elem;
5085 }
5086
5087 // Clone any incoming data and prepend the event, creating the handler arg list
5088 data = data == null ?
5089 [ event ] :
5090 jQuery.makeArray( data, [ event ] );
5091
5092 // Allow special events to draw outside the lines
5093 special = jQuery.event.special[ type ] || {};
5094 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
5095 return;
5096 }
5097
5098 // Determine event propagation path in advance, per W3C events spec (#9951)
5099 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
5100 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
5101
5102 bubbleType = special.delegateType || type;
5103 if ( !rfocusMorph.test( bubbleType + type ) ) {
5104 cur = cur.parentNode;
5105 }
5106 for ( ; cur; cur = cur.parentNode ) {
5107 eventPath.push( cur );
5108 tmp = cur;
5109 }
5110
5111 // Only add window if we got to document (e.g., not plain obj or detached DOM)
5112 if ( tmp === ( elem.ownerDocument || document ) ) {
5113 eventPath.push( tmp.defaultView || tmp.parentWindow || window );
5114 }
5115 }
5116
5117 // Fire handlers on the event path
5118 i = 0;
5119 while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
5120
5121 event.type = i > 1 ?
5122 bubbleType :
5123 special.bindType || type;
5124
5125 // jQuery handler
5126 handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] &&
5127 jQuery._data( cur, "handle" );
5128
5129 if ( handle ) {
5130 handle.apply( cur, data );
5131 }
5132
5133 // Native handler
5134 handle = ontype && cur[ ontype ];
5135 if ( handle && handle.apply && acceptData( cur ) ) {
5136 event.result = handle.apply( cur, data );
5137 if ( event.result === false ) {
5138 event.preventDefault();
5139 }
5140 }
5141 }
5142 event.type = type;
5143
5144 // If nobody prevented the default action, do it now
5145 if ( !onlyHandlers && !event.isDefaultPrevented() ) {
5146
5147 if (
5148 ( !special._default ||
5149 special._default.apply( eventPath.pop(), data ) === false
5150 ) && acceptData( elem )
5151 ) {
5152
5153 // Call a native DOM method on the target with the same name name as the event.
5154 // Can't use an .isFunction() check here because IE6/7 fails that test.
5155 // Don't do default actions on window, that's where global variables be (#6170)
5156 if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
5157
5158 // Don't re-trigger an onFOO event when we call its FOO() method
5159 tmp = elem[ ontype ];
5160
5161 if ( tmp ) {
5162 elem[ ontype ] = null;
5163 }
5164
5165 // Prevent re-triggering of the same event, since we already bubbled it above
5166 jQuery.event.triggered = type;
5167 try {
5168 elem[ type ]();
5169 } catch ( e ) {
5170
5171 // IE<9 dies on focus/blur to hidden element (#1486,#12518)
5172 // only reproducible on winXP IE8 native, not IE9 in IE8 mode
5173 }
5174 jQuery.event.triggered = undefined;
5175
5176 if ( tmp ) {
5177 elem[ ontype ] = tmp;
5178 }
5179 }
5180 }
5181 }
5182
5183 return event.result;
5184 },
5185
5186 dispatch: function( event ) {
5187
5188 // Make a writable jQuery.Event from the native event object
5189 event = jQuery.event.fix( event );
5190
5191 var i, j, ret, matched, handleObj,
5192 handlerQueue = [],
5193 args = slice.call( arguments ),
5194 handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
5195 special = jQuery.event.special[ event.type ] || {};
5196
5197 // Use the fix-ed jQuery.Event rather than the (read-only) native event
5198 args[ 0 ] = event;
5199 event.delegateTarget = this;
5200
5201 // Call the preDispatch hook for the mapped type, and let it bail if desired
5202 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
5203 return;
5204 }
5205
5206 // Determine handlers
5207 handlerQueue = jQuery.event.handlers.call( this, event, handlers );
5208
5209 // Run delegates first; they may want to stop propagation beneath us
5210 i = 0;
5211 while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
5212 event.currentTarget = matched.elem;
5213
5214 j = 0;
5215 while ( ( handleObj = matched.handlers[ j++ ] ) &&
5216 !event.isImmediatePropagationStopped() ) {
5217
5218 // Triggered event must either 1) have no namespace, or 2) have namespace(s)
5219 // a subset or equal to those in the bound event (both can have no namespace).
5220 if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
5221
5222 event.handleObj = handleObj;
5223 event.data = handleObj.data;
5224
5225 ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
5226 handleObj.handler ).apply( matched.elem, args );
5227
5228 if ( ret !== undefined ) {
5229 if ( ( event.result = ret ) === false ) {
5230 event.preventDefault();
5231 event.stopPropagation();
5232 }
5233 }
5234 }
5235 }
5236 }
5237
5238 // Call the postDispatch hook for the mapped type
5239 if ( special.postDispatch ) {
5240 special.postDispatch.call( this, event );
5241 }
5242
5243 return event.result;
5244 },
5245
5246 handlers: function( event, handlers ) {
5247 var i, matches, sel, handleObj,
5248 handlerQueue = [],
5249 delegateCount = handlers.delegateCount,
5250 cur = event.target;
5251
5252 // Support (at least): Chrome, IE9
5253 // Find delegate handlers
5254 // Black-hole SVG <use> instance trees (#13180)
5255 //
5256 // Support: Firefox<=42+
5257 // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343)
5258 if ( delegateCount && cur.nodeType &&
5259 ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) {
5260
5261 /* jshint eqeqeq: false */
5262 for ( ; cur != this; cur = cur.parentNode || this ) {
5263 /* jshint eqeqeq: true */
5264
5265 // Don't check non-elements (#13208)
5266 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
5267 if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) {
5268 matches = [];
5269 for ( i = 0; i < delegateCount; i++ ) {
5270 handleObj = handlers[ i ];
5271
5272 // Don't conflict with Object.prototype properties (#13203)
5273 sel = handleObj.selector + " ";
5274
5275 if ( matches[ sel ] === undefined ) {
5276 matches[ sel ] = handleObj.needsContext ?
5277 jQuery( sel, this ).index( cur ) > -1 :
5278 jQuery.find( sel, this, null, [ cur ] ).length;
5279 }
5280 if ( matches[ sel ] ) {
5281 matches.push( handleObj );
5282 }
5283 }
5284 if ( matches.length ) {
5285 handlerQueue.push( { elem: cur, handlers: matches } );
5286 }
5287 }
5288 }
5289 }
5290
5291 // Add the remaining (directly-bound) handlers
5292 if ( delegateCount < handlers.length ) {
5293 handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } );
5294 }
5295
5296 return handlerQueue;
5297 },
5298
5299 fix: function( event ) {
5300 if ( event[ jQuery.expando ] ) {
5301 return event;
5302 }
5303
5304 // Create a writable copy of the event object and normalize some properties
5305 var i, prop, copy,
5306 type = event.type,
5307 originalEvent = event,
5308 fixHook = this.fixHooks[ type ];
5309
5310 if ( !fixHook ) {
5311 this.fixHooks[ type ] = fixHook =
5312 rmouseEvent.test( type ) ? this.mouseHooks :
5313 rkeyEvent.test( type ) ? this.keyHooks :
5314 {};
5315 }
5316 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
5317
5318 event = new jQuery.Event( originalEvent );
5319
5320 i = copy.length;
5321 while ( i-- ) {
5322 prop = copy[ i ];
5323 event[ prop ] = originalEvent[ prop ];
5324 }
5325
5326 // Support: IE<9
5327 // Fix target property (#1925)
5328 if ( !event.target ) {
5329 event.target = originalEvent.srcElement || document;
5330 }
5331
5332 // Support: Safari 6-8+
5333 // Target should not be a text node (#504, #13143)
5334 if ( event.target.nodeType === 3 ) {
5335 event.target = event.target.parentNode;
5336 }
5337
5338 // Support: IE<9
5339 // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
5340 event.metaKey = !!event.metaKey;
5341
5342 return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
5343 },
5344
5345 // Includes some event props shared by KeyEvent and MouseEvent
5346 props: ( "altKey bubbles cancelable ctrlKey currentTarget detail eventPhase " +
5347 "metaKey relatedTarget shiftKey target timeStamp view which" ).split( " " ),
5348
5349 fixHooks: {},
5350
5351 keyHooks: {
5352 props: "char charCode key keyCode".split( " " ),
5353 filter: function( event, original ) {
5354
5355 // Add which for key events
5356 if ( event.which == null ) {
5357 event.which = original.charCode != null ? original.charCode : original.keyCode;
5358 }
5359
5360 return event;
5361 }
5362 },
5363
5364 mouseHooks: {
5365 props: ( "button buttons clientX clientY fromElement offsetX offsetY " +
5366 "pageX pageY screenX screenY toElement" ).split( " " ),
5367 filter: function( event, original ) {
5368 var body, eventDoc, doc,
5369 button = original.button,
5370 fromElement = original.fromElement;
5371
5372 // Calculate pageX/Y if missing and clientX/Y available
5373 if ( event.pageX == null && original.clientX != null ) {
5374 eventDoc = event.target.ownerDocument || document;
5375 doc = eventDoc.documentElement;
5376 body = eventDoc.body;
5377
5378 event.pageX = original.clientX +
5379 ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) -
5380 ( doc && doc.clientLeft || body && body.clientLeft || 0 );
5381 event.pageY = original.clientY +
5382 ( doc && doc.scrollTop || body && body.scrollTop || 0 ) -
5383 ( doc && doc.clientTop || body && body.clientTop || 0 );
5384 }
5385
5386 // Add relatedTarget, if necessary
5387 if ( !event.relatedTarget && fromElement ) {
5388 event.relatedTarget = fromElement === event.target ?
5389 original.toElement :
5390 fromElement;
5391 }
5392
5393 // Add which for click: 1 === left; 2 === middle; 3 === right
5394 // Note: button is not normalized, so don't use it
5395 if ( !event.which && button !== undefined ) {
5396 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
5397 }
5398
5399 return event;
5400 }
5401 },
5402
5403 special: {
5404 load: {
5405
5406 // Prevent triggered image.load events from bubbling to window.load
5407 noBubble: true
5408 },
5409 focus: {
5410
5411 // Fire native event if possible so blur/focus sequence is correct
5412 trigger: function() {
5413 if ( this !== safeActiveElement() && this.focus ) {
5414 try {
5415 this.focus();
5416 return false;
5417 } catch ( e ) {
5418
5419 // Support: IE<9
5420 // If we error on focus to hidden element (#1486, #12518),
5421 // let .trigger() run the handlers
5422 }
5423 }
5424 },
5425 delegateType: "focusin"
5426 },
5427 blur: {
5428 trigger: function() {
5429 if ( this === safeActiveElement() && this.blur ) {
5430 this.blur();
5431 return false;
5432 }
5433 },
5434 delegateType: "focusout"
5435 },
5436 click: {
5437
5438 // For checkbox, fire native event so checked state will be right
5439 trigger: function() {
5440 if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
5441 this.click();
5442 return false;
5443 }
5444 },
5445
5446 // For cross-browser consistency, don't fire native .click() on links
5447 _default: function( event ) {
5448 return jQuery.nodeName( event.target, "a" );
5449 }
5450 },
5451
5452 beforeunload: {
5453 postDispatch: function( event ) {
5454
5455 // Support: Firefox 20+
5456 // Firefox doesn't alert if the returnValue field is not set.
5457 if ( event.result !== undefined && event.originalEvent ) {
5458 event.originalEvent.returnValue = event.result;
5459 }
5460 }
5461 }
5462 },
5463
5464 // Piggyback on a donor event to simulate a different one
5465 simulate: function( type, elem, event ) {
5466 var e = jQuery.extend(
5467 new jQuery.Event(),
5468 event,
5469 {
5470 type: type,
5471 isSimulated: true
5472
5473 // Previously, `originalEvent: {}` was set here, so stopPropagation call
5474 // would not be triggered on donor event, since in our own
5475 // jQuery.event.stopPropagation function we had a check for existence of
5476 // originalEvent.stopPropagation method, so, consequently it would be a noop.
5477 //
5478 // Guard for simulated events was moved to jQuery.event.stopPropagation function
5479 // since `originalEvent` should point to the original event for the
5480 // constancy with other events and for more focused logic
5481 }
5482 );
5483
5484 jQuery.event.trigger( e, null, elem );
5485
5486 if ( e.isDefaultPrevented() ) {
5487 event.preventDefault();
5488 }
5489 }
5490};
5491
5492jQuery.removeEvent = document.removeEventListener ?
5493 function( elem, type, handle ) {
5494
5495 // This "if" is needed for plain objects
5496 if ( elem.removeEventListener ) {
5497 elem.removeEventListener( type, handle );
5498 }
5499 } :
5500 function( elem, type, handle ) {
5501 var name = "on" + type;
5502
5503 if ( elem.detachEvent ) {
5504
5505 // #8545, #7054, preventing memory leaks for custom events in IE6-8
5506 // detachEvent needed property on element, by name of that event,
5507 // to properly expose it to GC
5508 if ( typeof elem[ name ] === "undefined" ) {
5509 elem[ name ] = null;
5510 }
5511
5512 elem.detachEvent( name, handle );
5513 }
5514 };
5515
5516jQuery.Event = function( src, props ) {
5517
5518 // Allow instantiation without the 'new' keyword
5519 if ( !( this instanceof jQuery.Event ) ) {
5520 return new jQuery.Event( src, props );
5521 }
5522
5523 // Event object
5524 if ( src && src.type ) {
5525 this.originalEvent = src;
5526 this.type = src.type;
5527
5528 // Events bubbling up the document may have been marked as prevented
5529 // by a handler lower down the tree; reflect the correct value.
5530 this.isDefaultPrevented = src.defaultPrevented ||
5531 src.defaultPrevented === undefined &&
5532
5533 // Support: IE < 9, Android < 4.0
5534 src.returnValue === false ?
5535 returnTrue :
5536 returnFalse;
5537
5538 // Event type
5539 } else {
5540 this.type = src;
5541 }
5542
5543 // Put explicitly provided properties onto the event object
5544 if ( props ) {
5545 jQuery.extend( this, props );
5546 }
5547
5548 // Create a timestamp if incoming event doesn't have one
5549 this.timeStamp = src && src.timeStamp || jQuery.now();
5550
5551 // Mark it as fixed
5552 this[ jQuery.expando ] = true;
5553};
5554
5555// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
5556// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
5557jQuery.Event.prototype = {
5558 constructor: jQuery.Event,
5559 isDefaultPrevented: returnFalse,
5560 isPropagationStopped: returnFalse,
5561 isImmediatePropagationStopped: returnFalse,
5562
5563 preventDefault: function() {
5564 var e = this.originalEvent;
5565
5566 this.isDefaultPrevented = returnTrue;
5567 if ( !e ) {
5568 return;
5569 }
5570
5571 // If preventDefault exists, run it on the original event
5572 if ( e.preventDefault ) {
5573 e.preventDefault();
5574
5575 // Support: IE
5576 // Otherwise set the returnValue property of the original event to false
5577 } else {
5578 e.returnValue = false;
5579 }
5580 },
5581 stopPropagation: function() {
5582 var e = this.originalEvent;
5583
5584 this.isPropagationStopped = returnTrue;
5585
5586 if ( !e || this.isSimulated ) {
5587 return;
5588 }
5589
5590 // If stopPropagation exists, run it on the original event
5591 if ( e.stopPropagation ) {
5592 e.stopPropagation();
5593 }
5594
5595 // Support: IE
5596 // Set the cancelBubble property of the original event to true
5597 e.cancelBubble = true;
5598 },
5599 stopImmediatePropagation: function() {
5600 var e = this.originalEvent;
5601
5602 this.isImmediatePropagationStopped = returnTrue;
5603
5604 if ( e && e.stopImmediatePropagation ) {
5605 e.stopImmediatePropagation();
5606 }
5607
5608 this.stopPropagation();
5609 }
5610};
5611
5612// Create mouseenter/leave events using mouseover/out and event-time checks
5613// so that event delegation works in jQuery.
5614// Do the same for pointerenter/pointerleave and pointerover/pointerout
5615//
5616// Support: Safari 7 only
5617// Safari sends mouseenter too often; see:
5618// https://code.google.com/p/chromium/issues/detail?id=470258
5619// for the description of the bug (it existed in older Chrome versions as well).
5620jQuery.each( {
5621 mouseenter: "mouseover",
5622 mouseleave: "mouseout",
5623 pointerenter: "pointerover",
5624 pointerleave: "pointerout"
5625}, function( orig, fix ) {
5626 jQuery.event.special[ orig ] = {
5627 delegateType: fix,
5628 bindType: fix,
5629
5630 handle: function( event ) {
5631 var ret,
5632 target = this,
5633 related = event.relatedTarget,
5634 handleObj = event.handleObj;
5635
5636 // For mouseenter/leave call the handler if related is outside the target.
5637 // NB: No relatedTarget if the mouse left/entered the browser window
5638 if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
5639 event.type = handleObj.origType;
5640 ret = handleObj.handler.apply( this, arguments );
5641 event.type = fix;
5642 }
5643 return ret;
5644 }
5645 };
5646} );
5647
5648// IE submit delegation
5649if ( !support.submit ) {
5650
5651 jQuery.event.special.submit = {
5652 setup: function() {
5653
5654 // Only need this for delegated form submit events
5655 if ( jQuery.nodeName( this, "form" ) ) {
5656 return false;
5657 }
5658
5659 // Lazy-add a submit handler when a descendant form may potentially be submitted
5660 jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
5661
5662 // Node name check avoids a VML-related crash in IE (#9807)
5663 var elem = e.target,
5664 form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ?
5665
5666 // Support: IE <=8
5667 // We use jQuery.prop instead of elem.form
5668 // to allow fixing the IE8 delegated submit issue (gh-2332)
5669 // by 3rd party polyfills/workarounds.
5670 jQuery.prop( elem, "form" ) :
5671 undefined;
5672
5673 if ( form && !jQuery._data( form, "submit" ) ) {
5674 jQuery.event.add( form, "submit._submit", function( event ) {
5675 event._submitBubble = true;
5676 } );
5677 jQuery._data( form, "submit", true );
5678 }
5679 } );
5680
5681 // return undefined since we don't need an event listener
5682 },
5683
5684 postDispatch: function( event ) {
5685
5686 // If form was submitted by the user, bubble the event up the tree
5687 if ( event._submitBubble ) {
5688 delete event._submitBubble;
5689 if ( this.parentNode && !event.isTrigger ) {
5690 jQuery.event.simulate( "submit", this.parentNode, event );
5691 }
5692 }
5693 },
5694
5695 teardown: function() {
5696
5697 // Only need this for delegated form submit events
5698 if ( jQuery.nodeName( this, "form" ) ) {
5699 return false;
5700 }
5701
5702 // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
5703 jQuery.event.remove( this, "._submit" );
5704 }
5705 };
5706}
5707
5708// IE change delegation and checkbox/radio fix
5709if ( !support.change ) {
5710
5711 jQuery.event.special.change = {
5712
5713 setup: function() {
5714
5715 if ( rformElems.test( this.nodeName ) ) {
5716
5717 // IE doesn't fire change on a check/radio until blur; trigger it on click
5718 // after a propertychange. Eat the blur-change in special.change.handle.
5719 // This still fires onchange a second time for check/radio after blur.
5720 if ( this.type === "checkbox" || this.type === "radio" ) {
5721 jQuery.event.add( this, "propertychange._change", function( event ) {
5722 if ( event.originalEvent.propertyName === "checked" ) {
5723 this._justChanged = true;
5724 }
5725 } );
5726 jQuery.event.add( this, "click._change", function( event ) {
5727 if ( this._justChanged && !event.isTrigger ) {
5728 this._justChanged = false;
5729 }
5730
5731 // Allow triggered, simulated change events (#11500)
5732 jQuery.event.simulate( "change", this, event );
5733 } );
5734 }
5735 return false;
5736 }
5737
5738 // Delegated event; lazy-add a change handler on descendant inputs
5739 jQuery.event.add( this, "beforeactivate._change", function( e ) {
5740 var elem = e.target;
5741
5742 if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "change" ) ) {
5743 jQuery.event.add( elem, "change._change", function( event ) {
5744 if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
5745 jQuery.event.simulate( "change", this.parentNode, event );
5746 }
5747 } );
5748 jQuery._data( elem, "change", true );
5749 }
5750 } );
5751 },
5752
5753 handle: function( event ) {
5754 var elem = event.target;
5755
5756 // Swallow native change events from checkbox/radio, we already triggered them above
5757 if ( this !== elem || event.isSimulated || event.isTrigger ||
5758 ( elem.type !== "radio" && elem.type !== "checkbox" ) ) {
5759
5760 return event.handleObj.handler.apply( this, arguments );
5761 }
5762 },
5763
5764 teardown: function() {
5765 jQuery.event.remove( this, "._change" );
5766
5767 return !rformElems.test( this.nodeName );
5768 }
5769 };
5770}
5771
5772// Support: Firefox
5773// Firefox doesn't have focus(in | out) events
5774// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
5775//
5776// Support: Chrome, Safari
5777// focus(in | out) events fire after focus & blur events,
5778// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
5779// Related ticket - https://code.google.com/p/chromium/issues/detail?id=449857
5780if ( !support.focusin ) {
5781 jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
5782
5783 // Attach a single capturing handler on the document while someone wants focusin/focusout
5784 var handler = function( event ) {
5785 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
5786 };
5787
5788 jQuery.event.special[ fix ] = {
5789 setup: function() {
5790 var doc = this.ownerDocument || this,
5791 attaches = jQuery._data( doc, fix );
5792
5793 if ( !attaches ) {
5794 doc.addEventListener( orig, handler, true );
5795 }
5796 jQuery._data( doc, fix, ( attaches || 0 ) + 1 );
5797 },
5798 teardown: function() {
5799 var doc = this.ownerDocument || this,
5800 attaches = jQuery._data( doc, fix ) - 1;
5801
5802 if ( !attaches ) {
5803 doc.removeEventListener( orig, handler, true );
5804 jQuery._removeData( doc, fix );
5805 } else {
5806 jQuery._data( doc, fix, attaches );
5807 }
5808 }
5809 };
5810 } );
5811}
5812
5813jQuery.fn.extend( {
5814
5815 on: function( types, selector, data, fn ) {
5816 return on( this, types, selector, data, fn );
5817 },
5818 one: function( types, selector, data, fn ) {
5819 return on( this, types, selector, data, fn, 1 );
5820 },
5821 off: function( types, selector, fn ) {
5822 var handleObj, type;
5823 if ( types && types.preventDefault && types.handleObj ) {
5824
5825 // ( event ) dispatched jQuery.Event
5826 handleObj = types.handleObj;
5827 jQuery( types.delegateTarget ).off(
5828 handleObj.namespace ?
5829 handleObj.origType + "." + handleObj.namespace :
5830 handleObj.origType,
5831 handleObj.selector,
5832 handleObj.handler
5833 );
5834 return this;
5835 }
5836 if ( typeof types === "object" ) {
5837
5838 // ( types-object [, selector] )
5839 for ( type in types ) {
5840 this.off( type, selector, types[ type ] );
5841 }
5842 return this;
5843 }
5844 if ( selector === false || typeof selector === "function" ) {
5845
5846 // ( types [, fn] )
5847 fn = selector;
5848 selector = undefined;
5849 }
5850 if ( fn === false ) {
5851 fn = returnFalse;
5852 }
5853 return this.each( function() {
5854 jQuery.event.remove( this, types, fn, selector );
5855 } );
5856 },
5857
5858 trigger: function( type, data ) {
5859 return this.each( function() {
5860 jQuery.event.trigger( type, data, this );
5861 } );
5862 },
5863 triggerHandler: function( type, data ) {
5864 var elem = this[ 0 ];
5865 if ( elem ) {
5866 return jQuery.event.trigger( type, data, elem, true );
5867 }
5868 }
5869} );
5870
5871
5872var rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
5873 rnoshimcache = new RegExp( "<(?:" + nodeNames + ")[\\s/>]", "i" ),
5874 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,
5875
5876 // Support: IE 10-11, Edge 10240+
5877 // In IE/Edge using regex groups here causes severe slowdowns.
5878 // See https://connect.microsoft.com/IE/feedback/details/1736512/
5879 rnoInnerhtml = /<script|<style|<link/i,
5880
5881 // checked="checked" or checked
5882 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5883 rscriptTypeMasked = /^true\/(.*)/,
5884 rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
5885 safeFragment = createSafeFragment( document ),
5886 fragmentDiv = safeFragment.appendChild( document.createElement( "div" ) );
5887
5888// Support: IE<8
5889// Manipulating tables requires a tbody
5890function manipulationTarget( elem, content ) {
5891 return jQuery.nodeName( elem, "table" ) &&
5892 jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
5893
5894 elem.getElementsByTagName( "tbody" )[ 0 ] ||
5895 elem.appendChild( elem.ownerDocument.createElement( "tbody" ) ) :
5896 elem;
5897}
5898
5899// Replace/restore the type attribute of script elements for safe DOM manipulation
5900function disableScript( elem ) {
5901 elem.type = ( jQuery.find.attr( elem, "type" ) !== null ) + "/" + elem.type;
5902 return elem;
5903}
5904function restoreScript( elem ) {
5905 var match = rscriptTypeMasked.exec( elem.type );
5906 if ( match ) {
5907 elem.type = match[ 1 ];
5908 } else {
5909 elem.removeAttribute( "type" );
5910 }
5911 return elem;
5912}
5913
5914function cloneCopyEvent( src, dest ) {
5915 if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
5916 return;
5917 }
5918
5919 var type, i, l,
5920 oldData = jQuery._data( src ),
5921 curData = jQuery._data( dest, oldData ),
5922 events = oldData.events;
5923
5924 if ( events ) {
5925 delete curData.handle;
5926 curData.events = {};
5927
5928 for ( type in events ) {
5929 for ( i = 0, l = events[ type ].length; i < l; i++ ) {
5930 jQuery.event.add( dest, type, events[ type ][ i ] );
5931 }
5932 }
5933 }
5934
5935 // make the cloned public data object a copy from the original
5936 if ( curData.data ) {
5937 curData.data = jQuery.extend( {}, curData.data );
5938 }
5939}
5940
5941function fixCloneNodeIssues( src, dest ) {
5942 var nodeName, e, data;
5943
5944 // We do not need to do anything for non-Elements
5945 if ( dest.nodeType !== 1 ) {
5946 return;
5947 }
5948
5949 nodeName = dest.nodeName.toLowerCase();
5950
5951 // IE6-8 copies events bound via attachEvent when using cloneNode.
5952 if ( !support.noCloneEvent && dest[ jQuery.expando ] ) {
5953 data = jQuery._data( dest );
5954
5955 for ( e in data.events ) {
5956 jQuery.removeEvent( dest, e, data.handle );
5957 }
5958
5959 // Event data gets referenced instead of copied if the expando gets copied too
5960 dest.removeAttribute( jQuery.expando );
5961 }
5962
5963 // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
5964 if ( nodeName === "script" && dest.text !== src.text ) {
5965 disableScript( dest ).text = src.text;
5966 restoreScript( dest );
5967
5968 // IE6-10 improperly clones children of object elements using classid.
5969 // IE10 throws NoModificationAllowedError if parent is null, #12132.
5970 } else if ( nodeName === "object" ) {
5971 if ( dest.parentNode ) {
5972 dest.outerHTML = src.outerHTML;
5973 }
5974
5975 // This path appears unavoidable for IE9. When cloning an object
5976 // element in IE9, the outerHTML strategy above is not sufficient.
5977 // If the src has innerHTML and the destination does not,
5978 // copy the src.innerHTML into the dest.innerHTML. #10324
5979 if ( support.html5Clone && ( src.innerHTML && !jQuery.trim( dest.innerHTML ) ) ) {
5980 dest.innerHTML = src.innerHTML;
5981 }
5982
5983 } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
5984
5985 // IE6-8 fails to persist the checked state of a cloned checkbox
5986 // or radio button. Worse, IE6-7 fail to give the cloned element
5987 // a checked appearance if the defaultChecked value isn't also set
5988
5989 dest.defaultChecked = dest.checked = src.checked;
5990
5991 // IE6-7 get confused and end up setting the value of a cloned
5992 // checkbox/radio button to an empty string instead of "on"
5993 if ( dest.value !== src.value ) {
5994 dest.value = src.value;
5995 }
5996
5997 // IE6-8 fails to return the selected option to the default selected
5998 // state when cloning options
5999 } else if ( nodeName === "option" ) {
6000 dest.defaultSelected = dest.selected = src.defaultSelected;
6001
6002 // IE6-8 fails to set the defaultValue to the correct value when
6003 // cloning other types of input fields
6004 } else if ( nodeName === "input" || nodeName === "textarea" ) {
6005 dest.defaultValue = src.defaultValue;
6006 }
6007}
6008
6009function domManip( collection, args, callback, ignored ) {
6010
6011 // Flatten any nested arrays
6012 args = concat.apply( [], args );
6013
6014 var first, node, hasScripts,
6015 scripts, doc, fragment,
6016 i = 0,
6017 l = collection.length,
6018 iNoClone = l - 1,
6019 value = args[ 0 ],
6020 isFunction = jQuery.isFunction( value );
6021
6022 // We can't cloneNode fragments that contain checked, in WebKit
6023 if ( isFunction ||
6024 ( l > 1 && typeof value === "string" &&
6025 !support.checkClone && rchecked.test( value ) ) ) {
6026 return collection.each( function( index ) {
6027 var self = collection.eq( index );
6028 if ( isFunction ) {
6029 args[ 0 ] = value.call( this, index, self.html() );
6030 }
6031 domManip( self, args, callback, ignored );
6032 } );
6033 }
6034
6035 if ( l ) {
6036 fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
6037 first = fragment.firstChild;
6038
6039 if ( fragment.childNodes.length === 1 ) {
6040 fragment = first;
6041 }
6042
6043 // Require either new content or an interest in ignored elements to invoke the callback
6044 if ( first || ignored ) {
6045 scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
6046 hasScripts = scripts.length;
6047
6048 // Use the original fragment for the last item
6049 // instead of the first because it can end up
6050 // being emptied incorrectly in certain situations (#8070).
6051 for ( ; i < l; i++ ) {
6052 node = fragment;
6053
6054 if ( i !== iNoClone ) {
6055 node = jQuery.clone( node, true, true );
6056
6057 // Keep references to cloned scripts for later restoration
6058 if ( hasScripts ) {
6059
6060 // Support: Android<4.1, PhantomJS<2
6061 // push.apply(_, arraylike) throws on ancient WebKit
6062 jQuery.merge( scripts, getAll( node, "script" ) );
6063 }
6064 }
6065
6066 callback.call( collection[ i ], node, i );
6067 }
6068
6069 if ( hasScripts ) {
6070 doc = scripts[ scripts.length - 1 ].ownerDocument;
6071
6072 // Reenable scripts
6073 jQuery.map( scripts, restoreScript );
6074
6075 // Evaluate executable scripts on first document insertion
6076 for ( i = 0; i < hasScripts; i++ ) {
6077 node = scripts[ i ];
6078 if ( rscriptType.test( node.type || "" ) &&
6079 !jQuery._data( node, "globalEval" ) &&
6080 jQuery.contains( doc, node ) ) {
6081
6082 if ( node.src ) {
6083
6084 // Optional AJAX dependency, but won't run scripts if not present
6085 if ( jQuery._evalUrl ) {
6086 jQuery._evalUrl( node.src );
6087 }
6088 } else {
6089 jQuery.globalEval(
6090 ( node.text || node.textContent || node.innerHTML || "" )
6091 .replace( rcleanScript, "" )
6092 );
6093 }
6094 }
6095 }
6096 }
6097
6098 // Fix #11809: Avoid leaking memory
6099 fragment = first = null;
6100 }
6101 }
6102
6103 return collection;
6104}
6105
6106function remove( elem, selector, keepData ) {
6107 var node,
6108 elems = selector ? jQuery.filter( selector, elem ) : elem,
6109 i = 0;
6110
6111 for ( ; ( node = elems[ i ] ) != null; i++ ) {
6112
6113 if ( !keepData && node.nodeType === 1 ) {
6114 jQuery.cleanData( getAll( node ) );
6115 }
6116
6117 if ( node.parentNode ) {
6118 if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
6119 setGlobalEval( getAll( node, "script" ) );
6120 }
6121 node.parentNode.removeChild( node );
6122 }
6123 }
6124
6125 return elem;
6126}
6127
6128jQuery.extend( {
6129 htmlPrefilter: function( html ) {
6130 return html.replace( rxhtmlTag, "<$1></$2>" );
6131 },
6132
6133 clone: function( elem, dataAndEvents, deepDataAndEvents ) {
6134 var destElements, node, clone, i, srcElements,
6135 inPage = jQuery.contains( elem.ownerDocument, elem );
6136
6137 if ( support.html5Clone || jQuery.isXMLDoc( elem ) ||
6138 !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
6139
6140 clone = elem.cloneNode( true );
6141
6142 // IE<=8 does not properly clone detached, unknown element nodes
6143 } else {
6144 fragmentDiv.innerHTML = elem.outerHTML;
6145 fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
6146 }
6147
6148 if ( ( !support.noCloneEvent || !support.noCloneChecked ) &&
6149 ( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) {
6150
6151 // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
6152 destElements = getAll( clone );
6153 srcElements = getAll( elem );
6154
6155 // Fix all IE cloning issues
6156 for ( i = 0; ( node = srcElements[ i ] ) != null; ++i ) {
6157
6158 // Ensure that the destination node is not null; Fixes #9587
6159 if ( destElements[ i ] ) {
6160 fixCloneNodeIssues( node, destElements[ i ] );
6161 }
6162 }
6163 }
6164
6165 // Copy the events from the original to the clone
6166 if ( dataAndEvents ) {
6167 if ( deepDataAndEvents ) {
6168 srcElements = srcElements || getAll( elem );
6169 destElements = destElements || getAll( clone );
6170
6171 for ( i = 0; ( node = srcElements[ i ] ) != null; i++ ) {
6172 cloneCopyEvent( node, destElements[ i ] );
6173 }
6174 } else {
6175 cloneCopyEvent( elem, clone );
6176 }
6177 }
6178
6179 // Preserve script evaluation history
6180 destElements = getAll( clone, "script" );
6181 if ( destElements.length > 0 ) {
6182 setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
6183 }
6184
6185 destElements = srcElements = node = null;
6186
6187 // Return the cloned set
6188 return clone;
6189 },
6190
6191 cleanData: function( elems, /* internal */ forceAcceptData ) {
6192 var elem, type, id, data,
6193 i = 0,
6194 internalKey = jQuery.expando,
6195 cache = jQuery.cache,
6196 attributes = support.attributes,
6197 special = jQuery.event.special;
6198
6199 for ( ; ( elem = elems[ i ] ) != null; i++ ) {
6200 if ( forceAcceptData || acceptData( elem ) ) {
6201
6202 id = elem[ internalKey ];
6203 data = id && cache[ id ];
6204
6205 if ( data ) {
6206 if ( data.events ) {
6207 for ( type in data.events ) {
6208 if ( special[ type ] ) {
6209 jQuery.event.remove( elem, type );
6210
6211 // This is a shortcut to avoid jQuery.event.remove's overhead
6212 } else {
6213 jQuery.removeEvent( elem, type, data.handle );
6214 }
6215 }
6216 }
6217
6218 // Remove cache only if it was not already removed by jQuery.event.remove
6219 if ( cache[ id ] ) {
6220
6221 delete cache[ id ];
6222
6223 // Support: IE<9
6224 // IE does not allow us to delete expando properties from nodes
6225 // IE creates expando attributes along with the property
6226 // IE does not have a removeAttribute function on Document nodes
6227 if ( !attributes && typeof elem.removeAttribute !== "undefined" ) {
6228 elem.removeAttribute( internalKey );
6229
6230 // Webkit & Blink performance suffers when deleting properties
6231 // from DOM nodes, so set to undefined instead
6232 // https://code.google.com/p/chromium/issues/detail?id=378607
6233 } else {
6234 elem[ internalKey ] = undefined;
6235 }
6236
6237 deletedIds.push( id );
6238 }
6239 }
6240 }
6241 }
6242 }
6243} );
6244
6245jQuery.fn.extend( {
6246
6247 // Keep domManip exposed until 3.0 (gh-2225)
6248 domManip: domManip,
6249
6250 detach: function( selector ) {
6251 return remove( this, selector, true );
6252 },
6253
6254 remove: function( selector ) {
6255 return remove( this, selector );
6256 },
6257
6258 text: function( value ) {
6259 return access( this, function( value ) {
6260 return value === undefined ?
6261 jQuery.text( this ) :
6262 this.empty().append(
6263 ( this[ 0 ] && this[ 0 ].ownerDocument || document ).createTextNode( value )
6264 );
6265 }, null, value, arguments.length );
6266 },
6267
6268 append: function() {
6269 return domManip( this, arguments, function( elem ) {
6270 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6271 var target = manipulationTarget( this, elem );
6272 target.appendChild( elem );
6273 }
6274 } );
6275 },
6276
6277 prepend: function() {
6278 return domManip( this, arguments, function( elem ) {
6279 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6280 var target = manipulationTarget( this, elem );
6281 target.insertBefore( elem, target.firstChild );
6282 }
6283 } );
6284 },
6285
6286 before: function() {
6287 return domManip( this, arguments, function( elem ) {
6288 if ( this.parentNode ) {
6289 this.parentNode.insertBefore( elem, this );
6290 }
6291 } );
6292 },
6293
6294 after: function() {
6295 return domManip( this, arguments, function( elem ) {
6296 if ( this.parentNode ) {
6297 this.parentNode.insertBefore( elem, this.nextSibling );
6298 }
6299 } );
6300 },
6301
6302 empty: function() {
6303 var elem,
6304 i = 0;
6305
6306 for ( ; ( elem = this[ i ] ) != null; i++ ) {
6307
6308 // Remove element nodes and prevent memory leaks
6309 if ( elem.nodeType === 1 ) {
6310 jQuery.cleanData( getAll( elem, false ) );
6311 }
6312
6313 // Remove any remaining nodes
6314 while ( elem.firstChild ) {
6315 elem.removeChild( elem.firstChild );
6316 }
6317
6318 // If this is a select, ensure that it displays empty (#12336)
6319 // Support: IE<9
6320 if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
6321 elem.options.length = 0;
6322 }
6323 }
6324
6325 return this;
6326 },
6327
6328 clone: function( dataAndEvents, deepDataAndEvents ) {
6329 dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
6330 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
6331
6332 return this.map( function() {
6333 return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
6334 } );
6335 },
6336
6337 html: function( value ) {
6338 return access( this, function( value ) {
6339 var elem = this[ 0 ] || {},
6340 i = 0,
6341 l = this.length;
6342
6343 if ( value === undefined ) {
6344 return elem.nodeType === 1 ?
6345 elem.innerHTML.replace( rinlinejQuery, "" ) :
6346 undefined;
6347 }
6348
6349 // See if we can take a shortcut and just use innerHTML
6350 if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
6351 ( support.htmlSerialize || !rnoshimcache.test( value ) ) &&
6352 ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
6353 !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
6354
6355 value = jQuery.htmlPrefilter( value );
6356
6357 try {
6358 for ( ; i < l; i++ ) {
6359
6360 // Remove element nodes and prevent memory leaks
6361 elem = this[ i ] || {};
6362 if ( elem.nodeType === 1 ) {
6363 jQuery.cleanData( getAll( elem, false ) );
6364 elem.innerHTML = value;
6365 }
6366 }
6367
6368 elem = 0;
6369
6370 // If using innerHTML throws an exception, use the fallback method
6371 } catch ( e ) {}
6372 }
6373
6374 if ( elem ) {
6375 this.empty().append( value );
6376 }
6377 }, null, value, arguments.length );
6378 },
6379
6380 replaceWith: function() {
6381 var ignored = [];
6382
6383 // Make the changes, replacing each non-ignored context element with the new content
6384 return domManip( this, arguments, function( elem ) {
6385 var parent = this.parentNode;
6386
6387 if ( jQuery.inArray( this, ignored ) < 0 ) {
6388 jQuery.cleanData( getAll( this ) );
6389 if ( parent ) {
6390 parent.replaceChild( elem, this );
6391 }
6392 }
6393
6394 // Force callback invocation
6395 }, ignored );
6396 }
6397} );
6398
6399jQuery.each( {
6400 appendTo: "append",
6401 prependTo: "prepend",
6402 insertBefore: "before",
6403 insertAfter: "after",
6404 replaceAll: "replaceWith"
6405}, function( name, original ) {
6406 jQuery.fn[ name ] = function( selector ) {
6407 var elems,
6408 i = 0,
6409 ret = [],
6410 insert = jQuery( selector ),
6411 last = insert.length - 1;
6412
6413 for ( ; i <= last; i++ ) {
6414 elems = i === last ? this : this.clone( true );
6415 jQuery( insert[ i ] )[ original ]( elems );
6416
6417 // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
6418 push.apply( ret, elems.get() );
6419 }
6420
6421 return this.pushStack( ret );
6422 };
6423} );
6424
6425
6426var iframe,
6427 elemdisplay = {
6428
6429 // Support: Firefox
6430 // We have to pre-define these values for FF (#10227)
6431 HTML: "block",
6432 BODY: "block"
6433 };
6434
6435/**
6436 * Retrieve the actual display of a element
6437 * @param {String} name nodeName of the element
6438 * @param {Object} doc Document object
6439 */
6440
6441// Called only from within defaultDisplay
6442function actualDisplay( name, doc ) {
6443 var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
6444
6445 display = jQuery.css( elem[ 0 ], "display" );
6446
6447 // We don't have any data stored on the element,
6448 // so use "detach" method as fast way to get rid of the element
6449 elem.detach();
6450
6451 return display;
6452}
6453
6454/**
6455 * Try to determine the default display value of an element
6456 * @param {String} nodeName
6457 */
6458function defaultDisplay( nodeName ) {
6459 var doc = document,
6460 display = elemdisplay[ nodeName ];
6461
6462 if ( !display ) {
6463 display = actualDisplay( nodeName, doc );
6464
6465 // If the simple way fails, read from inside an iframe
6466 if ( display === "none" || !display ) {
6467
6468 // Use the already-created iframe if possible
6469 iframe = ( iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" ) )
6470 .appendTo( doc.documentElement );
6471
6472 // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
6473 doc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;
6474
6475 // Support: IE
6476 doc.write();
6477 doc.close();
6478
6479 display = actualDisplay( nodeName, doc );
6480 iframe.detach();
6481 }
6482
6483 // Store the correct default display
6484 elemdisplay[ nodeName ] = display;
6485 }
6486
6487 return display;
6488}
6489var rmargin = ( /^margin/ );
6490
6491var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
6492
6493var swap = function( elem, options, callback, args ) {
6494 var ret, name,
6495 old = {};
6496
6497 // Remember the old values, and insert the new ones
6498 for ( name in options ) {
6499 old[ name ] = elem.style[ name ];
6500 elem.style[ name ] = options[ name ];
6501 }
6502
6503 ret = callback.apply( elem, args || [] );
6504
6505 // Revert the old values
6506 for ( name in options ) {
6507 elem.style[ name ] = old[ name ];
6508 }
6509
6510 return ret;
6511};
6512
6513
6514var documentElement = document.documentElement;
6515
6516
6517
6518( function() {
6519 var pixelPositionVal, pixelMarginRightVal, boxSizingReliableVal,
6520 reliableHiddenOffsetsVal, reliableMarginRightVal, reliableMarginLeftVal,
6521 container = document.createElement( "div" ),
6522 div = document.createElement( "div" );
6523
6524 // Finish early in limited (non-browser) environments
6525 if ( !div.style ) {
6526 return;
6527 }
6528
6529 div.style.cssText = "float:left;opacity:.5";
6530
6531 // Support: IE<9
6532 // Make sure that element opacity exists (as opposed to filter)
6533 support.opacity = div.style.opacity === "0.5";
6534
6535 // Verify style float existence
6536 // (IE uses styleFloat instead of cssFloat)
6537 support.cssFloat = !!div.style.cssFloat;
6538
6539 div.style.backgroundClip = "content-box";
6540 div.cloneNode( true ).style.backgroundClip = "";
6541 support.clearCloneStyle = div.style.backgroundClip === "content-box";
6542
6543 container = document.createElement( "div" );
6544 container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" +
6545 "padding:0;margin-top:1px;position:absolute";
6546 div.innerHTML = "";
6547 container.appendChild( div );
6548
6549 // Support: Firefox<29, Android 2.3
6550 // Vendor-prefix box-sizing
6551 support.boxSizing = div.style.boxSizing === "" || div.style.MozBoxSizing === "" ||
6552 div.style.WebkitBoxSizing === "";
6553
6554 jQuery.extend( support, {
6555 reliableHiddenOffsets: function() {
6556 if ( pixelPositionVal == null ) {
6557 computeStyleTests();
6558 }
6559 return reliableHiddenOffsetsVal;
6560 },
6561
6562 boxSizingReliable: function() {
6563
6564 // We're checking for pixelPositionVal here instead of boxSizingReliableVal
6565 // since that compresses better and they're computed together anyway.
6566 if ( pixelPositionVal == null ) {
6567 computeStyleTests();
6568 }
6569 return boxSizingReliableVal;
6570 },
6571
6572 pixelMarginRight: function() {
6573
6574 // Support: Android 4.0-4.3
6575 if ( pixelPositionVal == null ) {
6576 computeStyleTests();
6577 }
6578 return pixelMarginRightVal;
6579 },
6580
6581 pixelPosition: function() {
6582 if ( pixelPositionVal == null ) {
6583 computeStyleTests();
6584 }
6585 return pixelPositionVal;
6586 },
6587
6588 reliableMarginRight: function() {
6589
6590 // Support: Android 2.3
6591 if ( pixelPositionVal == null ) {
6592 computeStyleTests();
6593 }
6594 return reliableMarginRightVal;
6595 },
6596
6597 reliableMarginLeft: function() {
6598
6599 // Support: IE <=8 only, Android 4.0 - 4.3 only, Firefox <=3 - 37
6600 if ( pixelPositionVal == null ) {
6601 computeStyleTests();
6602 }
6603 return reliableMarginLeftVal;
6604 }
6605 } );
6606
6607 function computeStyleTests() {
6608 var contents, divStyle,
6609 documentElement = document.documentElement;
6610
6611 // Setup
6612 documentElement.appendChild( container );
6613
6614 div.style.cssText =
6615
6616 // Support: Android 2.3
6617 // Vendor-prefix box-sizing
6618 "-webkit-box-sizing:border-box;box-sizing:border-box;" +
6619 "position:relative;display:block;" +
6620 "margin:auto;border:1px;padding:1px;" +
6621 "top:1%;width:50%";
6622
6623 // Support: IE<9
6624 // Assume reasonable values in the absence of getComputedStyle
6625 pixelPositionVal = boxSizingReliableVal = reliableMarginLeftVal = false;
6626 pixelMarginRightVal = reliableMarginRightVal = true;
6627
6628 // Check for getComputedStyle so that this code is not run in IE<9.
6629 if ( window.getComputedStyle ) {
6630 divStyle = window.getComputedStyle( div );
6631 pixelPositionVal = ( divStyle || {} ).top !== "1%";
6632 reliableMarginLeftVal = ( divStyle || {} ).marginLeft === "2px";
6633 boxSizingReliableVal = ( divStyle || { width: "4px" } ).width === "4px";
6634
6635 // Support: Android 4.0 - 4.3 only
6636 // Some styles come back with percentage values, even though they shouldn't
6637 div.style.marginRight = "50%";
6638 pixelMarginRightVal = ( divStyle || { marginRight: "4px" } ).marginRight === "4px";
6639
6640 // Support: Android 2.3 only
6641 // Div with explicit width and no margin-right incorrectly
6642 // gets computed margin-right based on width of container (#3333)
6643 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
6644 contents = div.appendChild( document.createElement( "div" ) );
6645
6646 // Reset CSS: box-sizing; display; margin; border; padding
6647 contents.style.cssText = div.style.cssText =
6648
6649 // Support: Android 2.3
6650 // Vendor-prefix box-sizing
6651 "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
6652 "box-sizing:content-box;display:block;margin:0;border:0;padding:0";
6653 contents.style.marginRight = contents.style.width = "0";
6654 div.style.width = "1px";
6655
6656 reliableMarginRightVal =
6657 !parseFloat( ( window.getComputedStyle( contents ) || {} ).marginRight );
6658
6659 div.removeChild( contents );
6660 }
6661
6662 // Support: IE6-8
6663 // First check that getClientRects works as expected
6664 // Check if table cells still have offsetWidth/Height when they are set
6665 // to display:none and there are still other visible table cells in a
6666 // table row; if so, offsetWidth/Height are not reliable for use when
6667 // determining if an element has been hidden directly using
6668 // display:none (it is still safe to use offsets if a parent element is
6669 // hidden; don safety goggles and see bug #4512 for more information).
6670 div.style.display = "none";
6671 reliableHiddenOffsetsVal = div.getClientRects().length === 0;
6672 if ( reliableHiddenOffsetsVal ) {
6673 div.style.display = "";
6674 div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
6675 div.childNodes[ 0 ].style.borderCollapse = "separate";
6676 contents = div.getElementsByTagName( "td" );
6677 contents[ 0 ].style.cssText = "margin:0;border:0;padding:0;display:none";
6678 reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
6679 if ( reliableHiddenOffsetsVal ) {
6680 contents[ 0 ].style.display = "";
6681 contents[ 1 ].style.display = "none";
6682 reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
6683 }
6684 }
6685
6686 // Teardown
6687 documentElement.removeChild( container );
6688 }
6689
6690} )();
6691
6692
6693var getStyles, curCSS,
6694 rposition = /^(top|right|bottom|left)$/;
6695
6696if ( window.getComputedStyle ) {
6697 getStyles = function( elem ) {
6698
6699 // Support: IE<=11+, Firefox<=30+ (#15098, #14150)
6700 // IE throws on elements created in popups
6701 // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
6702 var view = elem.ownerDocument.defaultView;
6703
6704 if ( !view || !view.opener ) {
6705 view = window;
6706 }
6707
6708 return view.getComputedStyle( elem );
6709 };
6710
6711 curCSS = function( elem, name, computed ) {
6712 var width, minWidth, maxWidth, ret,
6713 style = elem.style;
6714
6715 computed = computed || getStyles( elem );
6716
6717 // getPropertyValue is only needed for .css('filter') in IE9, see #12537
6718 ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
6719
6720 // Support: Opera 12.1x only
6721 // Fall back to style even without computed
6722 // computed is undefined for elems on document fragments
6723 if ( ( ret === "" || ret === undefined ) && !jQuery.contains( elem.ownerDocument, elem ) ) {
6724 ret = jQuery.style( elem, name );
6725 }
6726
6727 if ( computed ) {
6728
6729 // A tribute to the "awesome hack by Dean Edwards"
6730 // Chrome < 17 and Safari 5.0 uses "computed value"
6731 // instead of "used value" for margin-right
6732 // Safari 5.1.7 (at least) returns percentage for a larger set of values,
6733 // but width seems to be reliably pixels
6734 // this is against the CSSOM draft spec:
6735 // http://dev.w3.org/csswg/cssom/#resolved-values
6736 if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {
6737
6738 // Remember the original values
6739 width = style.width;
6740 minWidth = style.minWidth;
6741 maxWidth = style.maxWidth;
6742
6743 // Put in the new values to get a computed value out
6744 style.minWidth = style.maxWidth = style.width = ret;
6745 ret = computed.width;
6746
6747 // Revert the changed values
6748 style.width = width;
6749 style.minWidth = minWidth;
6750 style.maxWidth = maxWidth;
6751 }
6752 }
6753
6754 // Support: IE
6755 // IE returns zIndex value as an integer.
6756 return ret === undefined ?
6757 ret :
6758 ret + "";
6759 };
6760} else if ( documentElement.currentStyle ) {
6761 getStyles = function( elem ) {
6762 return elem.currentStyle;
6763 };
6764
6765 curCSS = function( elem, name, computed ) {
6766 var left, rs, rsLeft, ret,
6767 style = elem.style;
6768
6769 computed = computed || getStyles( elem );
6770 ret = computed ? computed[ name ] : undefined;
6771
6772 // Avoid setting ret to empty string here
6773 // so we don't default to auto
6774 if ( ret == null && style && style[ name ] ) {
6775 ret = style[ name ];
6776 }
6777
6778 // From the awesome hack by Dean Edwards
6779 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
6780
6781 // If we're not dealing with a regular pixel number
6782 // but a number that has a weird ending, we need to convert it to pixels
6783 // but not position css attributes, as those are
6784 // proportional to the parent element instead
6785 // and we can't measure the parent instead because it
6786 // might trigger a "stacking dolls" problem
6787 if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
6788
6789 // Remember the original values
6790 left = style.left;
6791 rs = elem.runtimeStyle;
6792 rsLeft = rs && rs.left;
6793
6794 // Put in the new values to get a computed value out
6795 if ( rsLeft ) {
6796 rs.left = elem.currentStyle.left;
6797 }
6798 style.left = name === "fontSize" ? "1em" : ret;
6799 ret = style.pixelLeft + "px";
6800
6801 // Revert the changed values
6802 style.left = left;
6803 if ( rsLeft ) {
6804 rs.left = rsLeft;
6805 }
6806 }
6807
6808 // Support: IE
6809 // IE returns zIndex value as an integer.
6810 return ret === undefined ?
6811 ret :
6812 ret + "" || "auto";
6813 };
6814}
6815
6816
6817
6818
6819function addGetHookIf( conditionFn, hookFn ) {
6820
6821 // Define the hook, we'll check on the first run if it's really needed.
6822 return {
6823 get: function() {
6824 if ( conditionFn() ) {
6825
6826 // Hook not needed (or it's not possible to use it due
6827 // to missing dependency), remove it.
6828 delete this.get;
6829 return;
6830 }
6831
6832 // Hook needed; redefine it so that the support test is not executed again.
6833 return ( this.get = hookFn ).apply( this, arguments );
6834 }
6835 };
6836}
6837
6838
6839var
6840
6841 ralpha = /alpha\([^)]*\)/i,
6842 ropacity = /opacity\s*=\s*([^)]*)/i,
6843
6844 // swappable if display is none or starts with table except
6845 // "table", "table-cell", or "table-caption"
6846 // see here for display values:
6847 // https://developer.mozilla.org/en-US/docs/CSS/display
6848 rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6849 rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
6850
6851 cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6852 cssNormalTransform = {
6853 letterSpacing: "0",
6854 fontWeight: "400"
6855 },
6856
6857 cssPrefixes = [ "Webkit", "O", "Moz", "ms" ],
6858 emptyStyle = document.createElement( "div" ).style;
6859
6860
6861// return a css property mapped to a potentially vendor prefixed property
6862function vendorPropName( name ) {
6863
6864 // shortcut for names that are not vendor prefixed
6865 if ( name in emptyStyle ) {
6866 return name;
6867 }
6868
6869 // check for vendor prefixed names
6870 var capName = name.charAt( 0 ).toUpperCase() + name.slice( 1 ),
6871 i = cssPrefixes.length;
6872
6873 while ( i-- ) {
6874 name = cssPrefixes[ i ] + capName;
6875 if ( name in emptyStyle ) {
6876 return name;
6877 }
6878 }
6879}
6880
6881function showHide( elements, show ) {
6882 var display, elem, hidden,
6883 values = [],
6884 index = 0,
6885 length = elements.length;
6886
6887 for ( ; index < length; index++ ) {
6888 elem = elements[ index ];
6889 if ( !elem.style ) {
6890 continue;
6891 }
6892
6893 values[ index ] = jQuery._data( elem, "olddisplay" );
6894 display = elem.style.display;
6895 if ( show ) {
6896
6897 // Reset the inline display of this element to learn if it is
6898 // being hidden by cascaded rules or not
6899 if ( !values[ index ] && display === "none" ) {
6900 elem.style.display = "";
6901 }
6902
6903 // Set elements which have been overridden with display: none
6904 // in a stylesheet to whatever the default browser style is
6905 // for such an element
6906 if ( elem.style.display === "" && isHidden( elem ) ) {
6907 values[ index ] =
6908 jQuery._data( elem, "olddisplay", defaultDisplay( elem.nodeName ) );
6909 }
6910 } else {
6911 hidden = isHidden( elem );
6912
6913 if ( display && display !== "none" || !hidden ) {
6914 jQuery._data(
6915 elem,
6916 "olddisplay",
6917 hidden ? display : jQuery.css( elem, "display" )
6918 );
6919 }
6920 }
6921 }
6922
6923 // Set the display of most of the elements in a second loop
6924 // to avoid the constant reflow
6925 for ( index = 0; index < length; index++ ) {
6926 elem = elements[ index ];
6927 if ( !elem.style ) {
6928 continue;
6929 }
6930 if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
6931 elem.style.display = show ? values[ index ] || "" : "none";
6932 }
6933 }
6934
6935 return elements;
6936}
6937
6938function setPositiveNumber( elem, value, subtract ) {
6939 var matches = rnumsplit.exec( value );
6940 return matches ?
6941
6942 // Guard against undefined "subtract", e.g., when used as in cssHooks
6943 Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
6944 value;
6945}
6946
6947function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
6948 var i = extra === ( isBorderBox ? "border" : "content" ) ?
6949
6950 // If we already have the right measurement, avoid augmentation
6951 4 :
6952
6953 // Otherwise initialize for horizontal or vertical properties
6954 name === "width" ? 1 : 0,
6955
6956 val = 0;
6957
6958 for ( ; i < 4; i += 2 ) {
6959
6960 // both box models exclude margin, so add it if we want it
6961 if ( extra === "margin" ) {
6962 val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
6963 }
6964
6965 if ( isBorderBox ) {
6966
6967 // border-box includes padding, so remove it if we want content
6968 if ( extra === "content" ) {
6969 val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6970 }
6971
6972 // at this point, extra isn't border nor margin, so remove border
6973 if ( extra !== "margin" ) {
6974 val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6975 }
6976 } else {
6977
6978 // at this point, extra isn't content, so add padding
6979 val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6980
6981 // at this point, extra isn't content nor padding, so add border
6982 if ( extra !== "padding" ) {
6983 val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6984 }
6985 }
6986 }
6987
6988 return val;
6989}
6990
6991function getWidthOrHeight( elem, name, extra ) {
6992
6993 // Start with offset property, which is equivalent to the border-box value
6994 var valueIsBorderBox = true,
6995 val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
6996 styles = getStyles( elem ),
6997 isBorderBox = support.boxSizing &&
6998 jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
6999
7000 // some non-html elements return undefined for offsetWidth, so check for null/undefined
7001 // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
7002 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
7003 if ( val <= 0 || val == null ) {
7004
7005 // Fall back to computed then uncomputed css if necessary
7006 val = curCSS( elem, name, styles );
7007 if ( val < 0 || val == null ) {
7008 val = elem.style[ name ];
7009 }
7010
7011 // Computed unit is not pixels. Stop here and return.
7012 if ( rnumnonpx.test( val ) ) {
7013 return val;
7014 }
7015
7016 // we need the check for style in case a browser which returns unreliable values
7017 // for getComputedStyle silently falls back to the reliable elem.style
7018 valueIsBorderBox = isBorderBox &&
7019 ( support.boxSizingReliable() || val === elem.style[ name ] );
7020
7021 // Normalize "", auto, and prepare for extra
7022 val = parseFloat( val ) || 0;
7023 }
7024
7025 // use the active box-sizing model to add/subtract irrelevant styles
7026 return ( val +
7027 augmentWidthOrHeight(
7028 elem,
7029 name,
7030 extra || ( isBorderBox ? "border" : "content" ),
7031 valueIsBorderBox,
7032 styles
7033 )
7034 ) + "px";
7035}
7036
7037jQuery.extend( {
7038
7039 // Add in style property hooks for overriding the default
7040 // behavior of getting and setting a style property
7041 cssHooks: {
7042 opacity: {
7043 get: function( elem, computed ) {
7044 if ( computed ) {
7045
7046 // We should always get a number back from opacity
7047 var ret = curCSS( elem, "opacity" );
7048 return ret === "" ? "1" : ret;
7049 }
7050 }
7051 }
7052 },
7053
7054 // Don't automatically add "px" to these possibly-unitless properties
7055 cssNumber: {
7056 "animationIterationCount": true,
7057 "columnCount": true,
7058 "fillOpacity": true,
7059 "flexGrow": true,
7060 "flexShrink": true,
7061 "fontWeight": true,
7062 "lineHeight": true,
7063 "opacity": true,
7064 "order": true,
7065 "orphans": true,
7066 "widows": true,
7067 "zIndex": true,
7068 "zoom": true
7069 },
7070
7071 // Add in properties whose names you wish to fix before
7072 // setting or getting the value
7073 cssProps: {
7074
7075 // normalize float css property
7076 "float": support.cssFloat ? "cssFloat" : "styleFloat"
7077 },
7078
7079 // Get and set the style property on a DOM Node
7080 style: function( elem, name, value, extra ) {
7081
7082 // Don't set styles on text and comment nodes
7083 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
7084 return;
7085 }
7086
7087 // Make sure that we're working with the right name
7088 var ret, type, hooks,
7089 origName = jQuery.camelCase( name ),
7090 style = elem.style;
7091
7092 name = jQuery.cssProps[ origName ] ||
7093 ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
7094
7095 // gets hook for the prefixed version
7096 // followed by the unprefixed version
7097 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
7098
7099 // Check if we're setting a value
7100 if ( value !== undefined ) {
7101 type = typeof value;
7102
7103 // Convert "+=" or "-=" to relative numbers (#7345)
7104 if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
7105 value = adjustCSS( elem, name, ret );
7106
7107 // Fixes bug #9237
7108 type = "number";
7109 }
7110
7111 // Make sure that null and NaN values aren't set. See: #7116
7112 if ( value == null || value !== value ) {
7113 return;
7114 }
7115
7116 // If a number was passed in, add the unit (except for certain CSS properties)
7117 if ( type === "number" ) {
7118 value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
7119 }
7120
7121 // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
7122 // but it would mean to define eight
7123 // (for every problematic property) identical functions
7124 if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
7125 style[ name ] = "inherit";
7126 }
7127
7128 // If a hook was provided, use that value, otherwise just set the specified value
7129 if ( !hooks || !( "set" in hooks ) ||
7130 ( value = hooks.set( elem, value, extra ) ) !== undefined ) {
7131
7132 // Support: IE
7133 // Swallow errors from 'invalid' CSS values (#5509)
7134 try {
7135 style[ name ] = value;
7136 } catch ( e ) {}
7137 }
7138
7139 } else {
7140
7141 // If a hook was provided get the non-computed value from there
7142 if ( hooks && "get" in hooks &&
7143 ( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
7144
7145 return ret;
7146 }
7147
7148 // Otherwise just get the value from the style object
7149 return style[ name ];
7150 }
7151 },
7152
7153 css: function( elem, name, extra, styles ) {
7154 var num, val, hooks,
7155 origName = jQuery.camelCase( name );
7156
7157 // Make sure that we're working with the right name
7158 name = jQuery.cssProps[ origName ] ||
7159 ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
7160
7161 // gets hook for the prefixed version
7162 // followed by the unprefixed version
7163 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
7164
7165 // If a hook was provided get the computed value from there
7166 if ( hooks && "get" in hooks ) {
7167 val = hooks.get( elem, true, extra );
7168 }
7169
7170 // Otherwise, if a way to get the computed value exists, use that
7171 if ( val === undefined ) {
7172 val = curCSS( elem, name, styles );
7173 }
7174
7175 //convert "normal" to computed value
7176 if ( val === "normal" && name in cssNormalTransform ) {
7177 val = cssNormalTransform[ name ];
7178 }
7179
7180 // Return, converting to number if forced or a qualifier was provided and val looks numeric
7181 if ( extra === "" || extra ) {
7182 num = parseFloat( val );
7183 return extra === true || isFinite( num ) ? num || 0 : val;
7184 }
7185 return val;
7186 }
7187} );
7188
7189jQuery.each( [ "height", "width" ], function( i, name ) {
7190 jQuery.cssHooks[ name ] = {
7191 get: function( elem, computed, extra ) {
7192 if ( computed ) {
7193
7194 // certain elements can have dimension info if we invisibly show them
7195 // however, it must have a current display style that would benefit from this
7196 return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
7197 elem.offsetWidth === 0 ?
7198 swap( elem, cssShow, function() {
7199 return getWidthOrHeight( elem, name, extra );
7200 } ) :
7201 getWidthOrHeight( elem, name, extra );
7202 }
7203 },
7204
7205 set: function( elem, value, extra ) {
7206 var styles = extra && getStyles( elem );
7207 return setPositiveNumber( elem, value, extra ?
7208 augmentWidthOrHeight(
7209 elem,
7210 name,
7211 extra,
7212 support.boxSizing &&
7213 jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
7214 styles
7215 ) : 0
7216 );
7217 }
7218 };
7219} );
7220
7221if ( !support.opacity ) {
7222 jQuery.cssHooks.opacity = {
7223 get: function( elem, computed ) {
7224
7225 // IE uses filters for opacity
7226 return ropacity.test( ( computed && elem.currentStyle ?
7227 elem.currentStyle.filter :
7228 elem.style.filter ) || "" ) ?
7229 ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
7230 computed ? "1" : "";
7231 },
7232
7233 set: function( elem, value ) {
7234 var style = elem.style,
7235 currentStyle = elem.currentStyle,
7236 opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
7237 filter = currentStyle && currentStyle.filter || style.filter || "";
7238
7239 // IE has trouble with opacity if it does not have layout
7240 // Force it by setting the zoom level
7241 style.zoom = 1;
7242
7243 // if setting opacity to 1, and no other filters exist -
7244 // attempt to remove filter attribute #6652
7245 // if value === "", then remove inline opacity #12685
7246 if ( ( value >= 1 || value === "" ) &&
7247 jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
7248 style.removeAttribute ) {
7249
7250 // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
7251 // if "filter:" is present at all, clearType is disabled, we want to avoid this
7252 // style.removeAttribute is IE Only, but so apparently is this code path...
7253 style.removeAttribute( "filter" );
7254
7255 // if there is no filter style applied in a css rule
7256 // or unset inline opacity, we are done
7257 if ( value === "" || currentStyle && !currentStyle.filter ) {
7258 return;
7259 }
7260 }
7261
7262 // otherwise, set new filter values
7263 style.filter = ralpha.test( filter ) ?
7264 filter.replace( ralpha, opacity ) :
7265 filter + " " + opacity;
7266 }
7267 };
7268}
7269
7270jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
7271 function( elem, computed ) {
7272 if ( computed ) {
7273 return swap( elem, { "display": "inline-block" },
7274 curCSS, [ elem, "marginRight" ] );
7275 }
7276 }
7277);
7278
7279jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
7280 function( elem, computed ) {
7281 if ( computed ) {
7282 return (
7283 parseFloat( curCSS( elem, "marginLeft" ) ) ||
7284
7285 // Support: IE<=11+
7286 // Running getBoundingClientRect on a disconnected node in IE throws an error
7287 // Support: IE8 only
7288 // getClientRects() errors on disconnected elems
7289 ( jQuery.contains( elem.ownerDocument, elem ) ?
7290 elem.getBoundingClientRect().left -
7291 swap( elem, { marginLeft: 0 }, function() {
7292 return elem.getBoundingClientRect().left;
7293 } ) :
7294 0
7295 )
7296 ) + "px";
7297 }
7298 }
7299);
7300
7301// These hooks are used by animate to expand properties
7302jQuery.each( {
7303 margin: "",
7304 padding: "",
7305 border: "Width"
7306}, function( prefix, suffix ) {
7307 jQuery.cssHooks[ prefix + suffix ] = {
7308 expand: function( value ) {
7309 var i = 0,
7310 expanded = {},
7311
7312 // assumes a single number if not a string
7313 parts = typeof value === "string" ? value.split( " " ) : [ value ];
7314
7315 for ( ; i < 4; i++ ) {
7316 expanded[ prefix + cssExpand[ i ] + suffix ] =
7317 parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
7318 }
7319
7320 return expanded;
7321 }
7322 };
7323
7324 if ( !rmargin.test( prefix ) ) {
7325 jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
7326 }
7327} );
7328
7329jQuery.fn.extend( {
7330 css: function( name, value ) {
7331 return access( this, function( elem, name, value ) {
7332 var styles, len,
7333 map = {},
7334 i = 0;
7335
7336 if ( jQuery.isArray( name ) ) {
7337 styles = getStyles( elem );
7338 len = name.length;
7339
7340 for ( ; i < len; i++ ) {
7341 map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
7342 }
7343
7344 return map;
7345 }
7346
7347 return value !== undefined ?
7348 jQuery.style( elem, name, value ) :
7349 jQuery.css( elem, name );
7350 }, name, value, arguments.length > 1 );
7351 },
7352 show: function() {
7353 return showHide( this, true );
7354 },
7355 hide: function() {
7356 return showHide( this );
7357 },
7358 toggle: function( state ) {
7359 if ( typeof state === "boolean" ) {
7360 return state ? this.show() : this.hide();
7361 }
7362
7363 return this.each( function() {
7364 if ( isHidden( this ) ) {
7365 jQuery( this ).show();
7366 } else {
7367 jQuery( this ).hide();
7368 }
7369 } );
7370 }
7371} );
7372
7373
7374function Tween( elem, options, prop, end, easing ) {
7375 return new Tween.prototype.init( elem, options, prop, end, easing );
7376}
7377jQuery.Tween = Tween;
7378
7379Tween.prototype = {
7380 constructor: Tween,
7381 init: function( elem, options, prop, end, easing, unit ) {
7382 this.elem = elem;
7383 this.prop = prop;
7384 this.easing = easing || jQuery.easing._default;
7385 this.options = options;
7386 this.start = this.now = this.cur();
7387 this.end = end;
7388 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
7389 },
7390 cur: function() {
7391 var hooks = Tween.propHooks[ this.prop ];
7392
7393 return hooks && hooks.get ?
7394 hooks.get( this ) :
7395 Tween.propHooks._default.get( this );
7396 },
7397 run: function( percent ) {
7398 var eased,
7399 hooks = Tween.propHooks[ this.prop ];
7400
7401 if ( this.options.duration ) {
7402 this.pos = eased = jQuery.easing[ this.easing ](
7403 percent, this.options.duration * percent, 0, 1, this.options.duration
7404 );
7405 } else {
7406 this.pos = eased = percent;
7407 }
7408 this.now = ( this.end - this.start ) * eased + this.start;
7409
7410 if ( this.options.step ) {
7411 this.options.step.call( this.elem, this.now, this );
7412 }
7413
7414 if ( hooks && hooks.set ) {
7415 hooks.set( this );
7416 } else {
7417 Tween.propHooks._default.set( this );
7418 }
7419 return this;
7420 }
7421};
7422
7423Tween.prototype.init.prototype = Tween.prototype;
7424
7425Tween.propHooks = {
7426 _default: {
7427 get: function( tween ) {
7428 var result;
7429
7430 // Use a property on the element directly when it is not a DOM element,
7431 // or when there is no matching style property that exists.
7432 if ( tween.elem.nodeType !== 1 ||
7433 tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
7434 return tween.elem[ tween.prop ];
7435 }
7436
7437 // passing an empty string as a 3rd parameter to .css will automatically
7438 // attempt a parseFloat and fallback to a string if the parse fails
7439 // so, simple values such as "10px" are parsed to Float.
7440 // complex values such as "rotate(1rad)" are returned as is.
7441 result = jQuery.css( tween.elem, tween.prop, "" );
7442
7443 // Empty strings, null, undefined and "auto" are converted to 0.
7444 return !result || result === "auto" ? 0 : result;
7445 },
7446 set: function( tween ) {
7447
7448 // use step hook for back compat - use cssHook if its there - use .style if its
7449 // available and use plain properties where available
7450 if ( jQuery.fx.step[ tween.prop ] ) {
7451 jQuery.fx.step[ tween.prop ]( tween );
7452 } else if ( tween.elem.nodeType === 1 &&
7453 ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
7454 jQuery.cssHooks[ tween.prop ] ) ) {
7455 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
7456 } else {
7457 tween.elem[ tween.prop ] = tween.now;
7458 }
7459 }
7460 }
7461};
7462
7463// Support: IE <=9
7464// Panic based approach to setting things on disconnected nodes
7465
7466Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
7467 set: function( tween ) {
7468 if ( tween.elem.nodeType && tween.elem.parentNode ) {
7469 tween.elem[ tween.prop ] = tween.now;
7470 }
7471 }
7472};
7473
7474jQuery.easing = {
7475 linear: function( p ) {
7476 return p;
7477 },
7478 swing: function( p ) {
7479 return 0.5 - Math.cos( p * Math.PI ) / 2;
7480 },
7481 _default: "swing"
7482};
7483
7484jQuery.fx = Tween.prototype.init;
7485
7486// Back Compat <1.8 extension point
7487jQuery.fx.step = {};
7488
7489
7490
7491
7492var
7493 fxNow, timerId,
7494 rfxtypes = /^(?:toggle|show|hide)$/,
7495 rrun = /queueHooks$/;
7496
7497// Animations created synchronously will run synchronously
7498function createFxNow() {
7499 window.setTimeout( function() {
7500 fxNow = undefined;
7501 } );
7502 return ( fxNow = jQuery.now() );
7503}
7504
7505// Generate parameters to create a standard animation
7506function genFx( type, includeWidth ) {
7507 var which,
7508 attrs = { height: type },
7509 i = 0;
7510
7511 // if we include width, step value is 1 to do all cssExpand values,
7512 // if we don't include width, step value is 2 to skip over Left and Right
7513 includeWidth = includeWidth ? 1 : 0;
7514 for ( ; i < 4 ; i += 2 - includeWidth ) {
7515 which = cssExpand[ i ];
7516 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
7517 }
7518
7519 if ( includeWidth ) {
7520 attrs.opacity = attrs.width = type;
7521 }
7522
7523 return attrs;
7524}
7525
7526function createTween( value, prop, animation ) {
7527 var tween,
7528 collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
7529 index = 0,
7530 length = collection.length;
7531 for ( ; index < length; index++ ) {
7532 if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
7533
7534 // we're done with this property
7535 return tween;
7536 }
7537 }
7538}
7539
7540function defaultPrefilter( elem, props, opts ) {
7541 /* jshint validthis: true */
7542 var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
7543 anim = this,
7544 orig = {},
7545 style = elem.style,
7546 hidden = elem.nodeType && isHidden( elem ),
7547 dataShow = jQuery._data( elem, "fxshow" );
7548
7549 // handle queue: false promises
7550 if ( !opts.queue ) {
7551 hooks = jQuery._queueHooks( elem, "fx" );
7552 if ( hooks.unqueued == null ) {
7553 hooks.unqueued = 0;
7554 oldfire = hooks.empty.fire;
7555 hooks.empty.fire = function() {
7556 if ( !hooks.unqueued ) {
7557 oldfire();
7558 }
7559 };
7560 }
7561 hooks.unqueued++;
7562
7563 anim.always( function() {
7564
7565 // doing this makes sure that the complete handler will be called
7566 // before this completes
7567 anim.always( function() {
7568 hooks.unqueued--;
7569 if ( !jQuery.queue( elem, "fx" ).length ) {
7570 hooks.empty.fire();
7571 }
7572 } );
7573 } );
7574 }
7575
7576 // height/width overflow pass
7577 if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
7578
7579 // Make sure that nothing sneaks out
7580 // Record all 3 overflow attributes because IE does not
7581 // change the overflow attribute when overflowX and
7582 // overflowY are set to the same value
7583 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
7584
7585 // Set display property to inline-block for height/width
7586 // animations on inline elements that are having width/height animated
7587 display = jQuery.css( elem, "display" );
7588
7589 // Test default display if display is currently "none"
7590 checkDisplay = display === "none" ?
7591 jQuery._data( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
7592
7593 if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
7594
7595 // inline-level elements accept inline-block;
7596 // block-level elements need to be inline with layout
7597 if ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === "inline" ) {
7598 style.display = "inline-block";
7599 } else {
7600 style.zoom = 1;
7601 }
7602 }
7603 }
7604
7605 if ( opts.overflow ) {
7606 style.overflow = "hidden";
7607 if ( !support.shrinkWrapBlocks() ) {
7608 anim.always( function() {
7609 style.overflow = opts.overflow[ 0 ];
7610 style.overflowX = opts.overflow[ 1 ];
7611 style.overflowY = opts.overflow[ 2 ];
7612 } );
7613 }
7614 }
7615
7616 // show/hide pass
7617 for ( prop in props ) {
7618 value = props[ prop ];
7619 if ( rfxtypes.exec( value ) ) {
7620 delete props[ prop ];
7621 toggle = toggle || value === "toggle";
7622 if ( value === ( hidden ? "hide" : "show" ) ) {
7623
7624 // If there is dataShow left over from a stopped hide or show
7625 // and we are going to proceed with show, we should pretend to be hidden
7626 if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
7627 hidden = true;
7628 } else {
7629 continue;
7630 }
7631 }
7632 orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
7633
7634 // Any non-fx value stops us from restoring the original display value
7635 } else {
7636 display = undefined;
7637 }
7638 }
7639
7640 if ( !jQuery.isEmptyObject( orig ) ) {
7641 if ( dataShow ) {
7642 if ( "hidden" in dataShow ) {
7643 hidden = dataShow.hidden;
7644 }
7645 } else {
7646 dataShow = jQuery._data( elem, "fxshow", {} );
7647 }
7648
7649 // store state if its toggle - enables .stop().toggle() to "reverse"
7650 if ( toggle ) {
7651 dataShow.hidden = !hidden;
7652 }
7653 if ( hidden ) {
7654 jQuery( elem ).show();
7655 } else {
7656 anim.done( function() {
7657 jQuery( elem ).hide();
7658 } );
7659 }
7660 anim.done( function() {
7661 var prop;
7662 jQuery._removeData( elem, "fxshow" );
7663 for ( prop in orig ) {
7664 jQuery.style( elem, prop, orig[ prop ] );
7665 }
7666 } );
7667 for ( prop in orig ) {
7668 tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
7669
7670 if ( !( prop in dataShow ) ) {
7671 dataShow[ prop ] = tween.start;
7672 if ( hidden ) {
7673 tween.end = tween.start;
7674 tween.start = prop === "width" || prop === "height" ? 1 : 0;
7675 }
7676 }
7677 }
7678
7679 // If this is a noop like .hide().hide(), restore an overwritten display value
7680 } else if ( ( display === "none" ? defaultDisplay( elem.nodeName ) : display ) === "inline" ) {
7681 style.display = display;
7682 }
7683}
7684
7685function propFilter( props, specialEasing ) {
7686 var index, name, easing, value, hooks;
7687
7688 // camelCase, specialEasing and expand cssHook pass
7689 for ( index in props ) {
7690 name = jQuery.camelCase( index );
7691 easing = specialEasing[ name ];
7692 value = props[ index ];
7693 if ( jQuery.isArray( value ) ) {
7694 easing = value[ 1 ];
7695 value = props[ index ] = value[ 0 ];
7696 }
7697
7698 if ( index !== name ) {
7699 props[ name ] = value;
7700 delete props[ index ];
7701 }
7702
7703 hooks = jQuery.cssHooks[ name ];
7704 if ( hooks && "expand" in hooks ) {
7705 value = hooks.expand( value );
7706 delete props[ name ];
7707
7708 // not quite $.extend, this wont overwrite keys already present.
7709 // also - reusing 'index' from above because we have the correct "name"
7710 for ( index in value ) {
7711 if ( !( index in props ) ) {
7712 props[ index ] = value[ index ];
7713 specialEasing[ index ] = easing;
7714 }
7715 }
7716 } else {
7717 specialEasing[ name ] = easing;
7718 }
7719 }
7720}
7721
7722function Animation( elem, properties, options ) {
7723 var result,
7724 stopped,
7725 index = 0,
7726 length = Animation.prefilters.length,
7727 deferred = jQuery.Deferred().always( function() {
7728
7729 // don't match elem in the :animated selector
7730 delete tick.elem;
7731 } ),
7732 tick = function() {
7733 if ( stopped ) {
7734 return false;
7735 }
7736 var currentTime = fxNow || createFxNow(),
7737 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
7738
7739 // Support: Android 2.3
7740 // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
7741 temp = remaining / animation.duration || 0,
7742 percent = 1 - temp,
7743 index = 0,
7744 length = animation.tweens.length;
7745
7746 for ( ; index < length ; index++ ) {
7747 animation.tweens[ index ].run( percent );
7748 }
7749
7750 deferred.notifyWith( elem, [ animation, percent, remaining ] );
7751
7752 if ( percent < 1 && length ) {
7753 return remaining;
7754 } else {
7755 deferred.resolveWith( elem, [ animation ] );
7756 return false;
7757 }
7758 },
7759 animation = deferred.promise( {
7760 elem: elem,
7761 props: jQuery.extend( {}, properties ),
7762 opts: jQuery.extend( true, {
7763 specialEasing: {},
7764 easing: jQuery.easing._default
7765 }, options ),
7766 originalProperties: properties,
7767 originalOptions: options,
7768 startTime: fxNow || createFxNow(),
7769 duration: options.duration,
7770 tweens: [],
7771 createTween: function( prop, end ) {
7772 var tween = jQuery.Tween( elem, animation.opts, prop, end,
7773 animation.opts.specialEasing[ prop ] || animation.opts.easing );
7774 animation.tweens.push( tween );
7775 return tween;
7776 },
7777 stop: function( gotoEnd ) {
7778 var index = 0,
7779
7780 // if we are going to the end, we want to run all the tweens
7781 // otherwise we skip this part
7782 length = gotoEnd ? animation.tweens.length : 0;
7783 if ( stopped ) {
7784 return this;
7785 }
7786 stopped = true;
7787 for ( ; index < length ; index++ ) {
7788 animation.tweens[ index ].run( 1 );
7789 }
7790
7791 // resolve when we played the last frame
7792 // otherwise, reject
7793 if ( gotoEnd ) {
7794 deferred.notifyWith( elem, [ animation, 1, 0 ] );
7795 deferred.resolveWith( elem, [ animation, gotoEnd ] );
7796 } else {
7797 deferred.rejectWith( elem, [ animation, gotoEnd ] );
7798 }
7799 return this;
7800 }
7801 } ),
7802 props = animation.props;
7803
7804 propFilter( props, animation.opts.specialEasing );
7805
7806 for ( ; index < length ; index++ ) {
7807 result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
7808 if ( result ) {
7809 if ( jQuery.isFunction( result.stop ) ) {
7810 jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
7811 jQuery.proxy( result.stop, result );
7812 }
7813 return result;
7814 }
7815 }
7816
7817 jQuery.map( props, createTween, animation );
7818
7819 if ( jQuery.isFunction( animation.opts.start ) ) {
7820 animation.opts.start.call( elem, animation );
7821 }
7822
7823 jQuery.fx.timer(
7824 jQuery.extend( tick, {
7825 elem: elem,
7826 anim: animation,
7827 queue: animation.opts.queue
7828 } )
7829 );
7830
7831 // attach callbacks from options
7832 return animation.progress( animation.opts.progress )
7833 .done( animation.opts.done, animation.opts.complete )
7834 .fail( animation.opts.fail )
7835 .always( animation.opts.always );
7836}
7837
7838jQuery.Animation = jQuery.extend( Animation, {
7839
7840 tweeners: {
7841 "*": [ function( prop, value ) {
7842 var tween = this.createTween( prop, value );
7843 adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
7844 return tween;
7845 } ]
7846 },
7847
7848 tweener: function( props, callback ) {
7849 if ( jQuery.isFunction( props ) ) {
7850 callback = props;
7851 props = [ "*" ];
7852 } else {
7853 props = props.match( rnotwhite );
7854 }
7855
7856 var prop,
7857 index = 0,
7858 length = props.length;
7859
7860 for ( ; index < length ; index++ ) {
7861 prop = props[ index ];
7862 Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
7863 Animation.tweeners[ prop ].unshift( callback );
7864 }
7865 },
7866
7867 prefilters: [ defaultPrefilter ],
7868
7869 prefilter: function( callback, prepend ) {
7870 if ( prepend ) {
7871 Animation.prefilters.unshift( callback );
7872 } else {
7873 Animation.prefilters.push( callback );
7874 }
7875 }
7876} );
7877
7878jQuery.speed = function( speed, easing, fn ) {
7879 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
7880 complete: fn || !fn && easing ||
7881 jQuery.isFunction( speed ) && speed,
7882 duration: speed,
7883 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
7884 };
7885
7886 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
7887 opt.duration in jQuery.fx.speeds ?
7888 jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
7889
7890 // normalize opt.queue - true/undefined/null -> "fx"
7891 if ( opt.queue == null || opt.queue === true ) {
7892 opt.queue = "fx";
7893 }
7894
7895 // Queueing
7896 opt.old = opt.complete;
7897
7898 opt.complete = function() {
7899 if ( jQuery.isFunction( opt.old ) ) {
7900 opt.old.call( this );
7901 }
7902
7903 if ( opt.queue ) {
7904 jQuery.dequeue( this, opt.queue );
7905 }
7906 };
7907
7908 return opt;
7909};
7910
7911jQuery.fn.extend( {
7912 fadeTo: function( speed, to, easing, callback ) {
7913
7914 // show any hidden elements after setting opacity to 0
7915 return this.filter( isHidden ).css( "opacity", 0 ).show()
7916
7917 // animate to the value specified
7918 .end().animate( { opacity: to }, speed, easing, callback );
7919 },
7920 animate: function( prop, speed, easing, callback ) {
7921 var empty = jQuery.isEmptyObject( prop ),
7922 optall = jQuery.speed( speed, easing, callback ),
7923 doAnimation = function() {
7924
7925 // Operate on a copy of prop so per-property easing won't be lost
7926 var anim = Animation( this, jQuery.extend( {}, prop ), optall );
7927
7928 // Empty animations, or finishing resolves immediately
7929 if ( empty || jQuery._data( this, "finish" ) ) {
7930 anim.stop( true );
7931 }
7932 };
7933 doAnimation.finish = doAnimation;
7934
7935 return empty || optall.queue === false ?
7936 this.each( doAnimation ) :
7937 this.queue( optall.queue, doAnimation );
7938 },
7939 stop: function( type, clearQueue, gotoEnd ) {
7940 var stopQueue = function( hooks ) {
7941 var stop = hooks.stop;
7942 delete hooks.stop;
7943 stop( gotoEnd );
7944 };
7945
7946 if ( typeof type !== "string" ) {
7947 gotoEnd = clearQueue;
7948 clearQueue = type;
7949 type = undefined;
7950 }
7951 if ( clearQueue && type !== false ) {
7952 this.queue( type || "fx", [] );
7953 }
7954
7955 return this.each( function() {
7956 var dequeue = true,
7957 index = type != null && type + "queueHooks",
7958 timers = jQuery.timers,
7959 data = jQuery._data( this );
7960
7961 if ( index ) {
7962 if ( data[ index ] && data[ index ].stop ) {
7963 stopQueue( data[ index ] );
7964 }
7965 } else {
7966 for ( index in data ) {
7967 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
7968 stopQueue( data[ index ] );
7969 }
7970 }
7971 }
7972
7973 for ( index = timers.length; index--; ) {
7974 if ( timers[ index ].elem === this &&
7975 ( type == null || timers[ index ].queue === type ) ) {
7976
7977 timers[ index ].anim.stop( gotoEnd );
7978 dequeue = false;
7979 timers.splice( index, 1 );
7980 }
7981 }
7982
7983 // start the next in the queue if the last step wasn't forced
7984 // timers currently will call their complete callbacks, which will dequeue
7985 // but only if they were gotoEnd
7986 if ( dequeue || !gotoEnd ) {
7987 jQuery.dequeue( this, type );
7988 }
7989 } );
7990 },
7991 finish: function( type ) {
7992 if ( type !== false ) {
7993 type = type || "fx";
7994 }
7995 return this.each( function() {
7996 var index,
7997 data = jQuery._data( this ),
7998 queue = data[ type + "queue" ],
7999 hooks = data[ type + "queueHooks" ],
8000 timers = jQuery.timers,
8001 length = queue ? queue.length : 0;
8002
8003 // enable finishing flag on private data
8004 data.finish = true;
8005
8006 // empty the queue first
8007 jQuery.queue( this, type, [] );
8008
8009 if ( hooks && hooks.stop ) {
8010 hooks.stop.call( this, true );
8011 }
8012
8013 // look for any active animations, and finish them
8014 for ( index = timers.length; index--; ) {
8015 if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
8016 timers[ index ].anim.stop( true );
8017 timers.splice( index, 1 );
8018 }
8019 }
8020
8021 // look for any animations in the old queue and finish them
8022 for ( index = 0; index < length; index++ ) {
8023 if ( queue[ index ] && queue[ index ].finish ) {
8024 queue[ index ].finish.call( this );
8025 }
8026 }
8027
8028 // turn off finishing flag
8029 delete data.finish;
8030 } );
8031 }
8032} );
8033
8034jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
8035 var cssFn = jQuery.fn[ name ];
8036 jQuery.fn[ name ] = function( speed, easing, callback ) {
8037 return speed == null || typeof speed === "boolean" ?
8038 cssFn.apply( this, arguments ) :
8039 this.animate( genFx( name, true ), speed, easing, callback );
8040 };
8041} );
8042
8043// Generate shortcuts for custom animations
8044jQuery.each( {
8045 slideDown: genFx( "show" ),
8046 slideUp: genFx( "hide" ),
8047 slideToggle: genFx( "toggle" ),
8048 fadeIn: { opacity: "show" },
8049 fadeOut: { opacity: "hide" },
8050 fadeToggle: { opacity: "toggle" }
8051}, function( name, props ) {
8052 jQuery.fn[ name ] = function( speed, easing, callback ) {
8053 return this.animate( props, speed, easing, callback );
8054 };
8055} );
8056
8057jQuery.timers = [];
8058jQuery.fx.tick = function() {
8059 var timer,
8060 timers = jQuery.timers,
8061 i = 0;
8062
8063 fxNow = jQuery.now();
8064
8065 for ( ; i < timers.length; i++ ) {
8066 timer = timers[ i ];
8067
8068 // Checks the timer has not already been removed
8069 if ( !timer() && timers[ i ] === timer ) {
8070 timers.splice( i--, 1 );
8071 }
8072 }
8073
8074 if ( !timers.length ) {
8075 jQuery.fx.stop();
8076 }
8077 fxNow = undefined;
8078};
8079
8080jQuery.fx.timer = function( timer ) {
8081 jQuery.timers.push( timer );
8082 if ( timer() ) {
8083 jQuery.fx.start();
8084 } else {
8085 jQuery.timers.pop();
8086 }
8087};
8088
8089jQuery.fx.interval = 13;
8090
8091jQuery.fx.start = function() {
8092 if ( !timerId ) {
8093 timerId = window.setInterval( jQuery.fx.tick, jQuery.fx.interval );
8094 }
8095};
8096
8097jQuery.fx.stop = function() {
8098 window.clearInterval( timerId );
8099 timerId = null;
8100};
8101
8102jQuery.fx.speeds = {
8103 slow: 600,
8104 fast: 200,
8105
8106 // Default speed
8107 _default: 400
8108};
8109
8110
8111// Based off of the plugin by Clint Helfers, with permission.
8112// http://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
8113jQuery.fn.delay = function( time, type ) {
8114 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
8115 type = type || "fx";
8116
8117 return this.queue( type, function( next, hooks ) {
8118 var timeout = window.setTimeout( next, time );
8119 hooks.stop = function() {
8120 window.clearTimeout( timeout );
8121 };
8122 } );
8123};
8124
8125
8126( function() {
8127 var a,
8128 input = document.createElement( "input" ),
8129 div = document.createElement( "div" ),
8130 select = document.createElement( "select" ),
8131 opt = select.appendChild( document.createElement( "option" ) );
8132
8133 // Setup
8134 div = document.createElement( "div" );
8135 div.setAttribute( "className", "t" );
8136 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
8137 a = div.getElementsByTagName( "a" )[ 0 ];
8138
8139 // Support: Windows Web Apps (WWA)
8140 // `type` must use .setAttribute for WWA (#14901)
8141 input.setAttribute( "type", "checkbox" );
8142 div.appendChild( input );
8143
8144 a = div.getElementsByTagName( "a" )[ 0 ];
8145
8146 // First batch of tests.
8147 a.style.cssText = "top:1px";
8148
8149 // Test setAttribute on camelCase class.
8150 // If it works, we need attrFixes when doing get/setAttribute (ie6/7)
8151 support.getSetAttribute = div.className !== "t";
8152
8153 // Get the style information from getAttribute
8154 // (IE uses .cssText instead)
8155 support.style = /top/.test( a.getAttribute( "style" ) );
8156
8157 // Make sure that URLs aren't manipulated
8158 // (IE normalizes it by default)
8159 support.hrefNormalized = a.getAttribute( "href" ) === "/a";
8160
8161 // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
8162 support.checkOn = !!input.value;
8163
8164 // Make sure that a selected-by-default option has a working selected property.
8165 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
8166 support.optSelected = opt.selected;
8167
8168 // Tests for enctype support on a form (#6743)
8169 support.enctype = !!document.createElement( "form" ).enctype;
8170
8171 // Make sure that the options inside disabled selects aren't marked as disabled
8172 // (WebKit marks them as disabled)
8173 select.disabled = true;
8174 support.optDisabled = !opt.disabled;
8175
8176 // Support: IE8 only
8177 // Check if we can trust getAttribute("value")
8178 input = document.createElement( "input" );
8179 input.setAttribute( "value", "" );
8180 support.input = input.getAttribute( "value" ) === "";
8181
8182 // Check if an input maintains its value after becoming a radio
8183 input.value = "t";
8184 input.setAttribute( "type", "radio" );
8185 support.radioValue = input.value === "t";
8186} )();
8187
8188
8189var rreturn = /\r/g,
8190 rspaces = /[\x20\t\r\n\f]+/g;
8191
8192jQuery.fn.extend( {
8193 val: function( value ) {
8194 var hooks, ret, isFunction,
8195 elem = this[ 0 ];
8196
8197 if ( !arguments.length ) {
8198 if ( elem ) {
8199 hooks = jQuery.valHooks[ elem.type ] ||
8200 jQuery.valHooks[ elem.nodeName.toLowerCase() ];
8201
8202 if (
8203 hooks &&
8204 "get" in hooks &&
8205 ( ret = hooks.get( elem, "value" ) ) !== undefined
8206 ) {
8207 return ret;
8208 }
8209
8210 ret = elem.value;
8211
8212 return typeof ret === "string" ?
8213
8214 // handle most common string cases
8215 ret.replace( rreturn, "" ) :
8216
8217 // handle cases where value is null/undef or number
8218 ret == null ? "" : ret;
8219 }
8220
8221 return;
8222 }
8223
8224 isFunction = jQuery.isFunction( value );
8225
8226 return this.each( function( i ) {
8227 var val;
8228
8229 if ( this.nodeType !== 1 ) {
8230 return;
8231 }
8232
8233 if ( isFunction ) {
8234 val = value.call( this, i, jQuery( this ).val() );
8235 } else {
8236 val = value;
8237 }
8238
8239 // Treat null/undefined as ""; convert numbers to string
8240 if ( val == null ) {
8241 val = "";
8242 } else if ( typeof val === "number" ) {
8243 val += "";
8244 } else if ( jQuery.isArray( val ) ) {
8245 val = jQuery.map( val, function( value ) {
8246 return value == null ? "" : value + "";
8247 } );
8248 }
8249
8250 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
8251
8252 // If set returns undefined, fall back to normal setting
8253 if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
8254 this.value = val;
8255 }
8256 } );
8257 }
8258} );
8259
8260jQuery.extend( {
8261 valHooks: {
8262 option: {
8263 get: function( elem ) {
8264 var val = jQuery.find.attr( elem, "value" );
8265 return val != null ?
8266 val :
8267
8268 // Support: IE10-11+
8269 // option.text throws exceptions (#14686, #14858)
8270 // Strip and collapse whitespace
8271 // https://html.spec.whatwg.org/#strip-and-collapse-whitespace
8272 jQuery.trim( jQuery.text( elem ) ).replace( rspaces, " " );
8273 }
8274 },
8275 select: {
8276 get: function( elem ) {
8277 var value, option,
8278 options = elem.options,
8279 index = elem.selectedIndex,
8280 one = elem.type === "select-one" || index < 0,
8281 values = one ? null : [],
8282 max = one ? index + 1 : options.length,
8283 i = index < 0 ?
8284 max :
8285 one ? index : 0;
8286
8287 // Loop through all the selected options
8288 for ( ; i < max; i++ ) {
8289 option = options[ i ];
8290
8291 // oldIE doesn't update selected after form reset (#2551)
8292 if ( ( option.selected || i === index ) &&
8293
8294 // Don't return options that are disabled or in a disabled optgroup
8295 ( support.optDisabled ?
8296 !option.disabled :
8297 option.getAttribute( "disabled" ) === null ) &&
8298 ( !option.parentNode.disabled ||
8299 !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
8300
8301 // Get the specific value for the option
8302 value = jQuery( option ).val();
8303
8304 // We don't need an array for one selects
8305 if ( one ) {
8306 return value;
8307 }
8308
8309 // Multi-Selects return an array
8310 values.push( value );
8311 }
8312 }
8313
8314 return values;
8315 },
8316
8317 set: function( elem, value ) {
8318 var optionSet, option,
8319 options = elem.options,
8320 values = jQuery.makeArray( value ),
8321 i = options.length;
8322
8323 while ( i-- ) {
8324 option = options[ i ];
8325
8326 if ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 ) {
8327
8328 // Support: IE6
8329 // When new option element is added to select box we need to
8330 // force reflow of newly added node in order to workaround delay
8331 // of initialization properties
8332 try {
8333 option.selected = optionSet = true;
8334
8335 } catch ( _ ) {
8336
8337 // Will be executed only in IE6
8338 option.scrollHeight;
8339 }
8340
8341 } else {
8342 option.selected = false;
8343 }
8344 }
8345
8346 // Force browsers to behave consistently when non-matching value is set
8347 if ( !optionSet ) {
8348 elem.selectedIndex = -1;
8349 }
8350
8351 return options;
8352 }
8353 }
8354 }
8355} );
8356
8357// Radios and checkboxes getter/setter
8358jQuery.each( [ "radio", "checkbox" ], function() {
8359 jQuery.valHooks[ this ] = {
8360 set: function( elem, value ) {
8361 if ( jQuery.isArray( value ) ) {
8362 return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
8363 }
8364 }
8365 };
8366 if ( !support.checkOn ) {
8367 jQuery.valHooks[ this ].get = function( elem ) {
8368 return elem.getAttribute( "value" ) === null ? "on" : elem.value;
8369 };
8370 }
8371} );
8372
8373
8374
8375
8376var nodeHook, boolHook,
8377 attrHandle = jQuery.expr.attrHandle,
8378 ruseDefault = /^(?:checked|selected)$/i,
8379 getSetAttribute = support.getSetAttribute,
8380 getSetInput = support.input;
8381
8382jQuery.fn.extend( {
8383 attr: function( name, value ) {
8384 return access( this, jQuery.attr, name, value, arguments.length > 1 );
8385 },
8386
8387 removeAttr: function( name ) {
8388 return this.each( function() {
8389 jQuery.removeAttr( this, name );
8390 } );
8391 }
8392} );
8393
8394jQuery.extend( {
8395 attr: function( elem, name, value ) {
8396 var ret, hooks,
8397 nType = elem.nodeType;
8398
8399 // Don't get/set attributes on text, comment and attribute nodes
8400 if ( nType === 3 || nType === 8 || nType === 2 ) {
8401 return;
8402 }
8403
8404 // Fallback to prop when attributes are not supported
8405 if ( typeof elem.getAttribute === "undefined" ) {
8406 return jQuery.prop( elem, name, value );
8407 }
8408
8409 // All attributes are lowercase
8410 // Grab necessary hook if one is defined
8411 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
8412 name = name.toLowerCase();
8413 hooks = jQuery.attrHooks[ name ] ||
8414 ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
8415 }
8416
8417 if ( value !== undefined ) {
8418 if ( value === null ) {
8419 jQuery.removeAttr( elem, name );
8420 return;
8421 }
8422
8423 if ( hooks && "set" in hooks &&
8424 ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
8425 return ret;
8426 }
8427
8428 elem.setAttribute( name, value + "" );
8429 return value;
8430 }
8431
8432 if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
8433 return ret;
8434 }
8435
8436 ret = jQuery.find.attr( elem, name );
8437
8438 // Non-existent attributes return null, we normalize to undefined
8439 return ret == null ? undefined : ret;
8440 },
8441
8442 attrHooks: {
8443 type: {
8444 set: function( elem, value ) {
8445 if ( !support.radioValue && value === "radio" &&
8446 jQuery.nodeName( elem, "input" ) ) {
8447
8448 // Setting the type on a radio button after the value resets the value in IE8-9
8449 // Reset value to default in case type is set after value during creation
8450 var val = elem.value;
8451 elem.setAttribute( "type", value );
8452 if ( val ) {
8453 elem.value = val;
8454 }
8455 return value;
8456 }
8457 }
8458 }
8459 },
8460
8461 removeAttr: function( elem, value ) {
8462 var name, propName,
8463 i = 0,
8464 attrNames = value && value.match( rnotwhite );
8465
8466 if ( attrNames && elem.nodeType === 1 ) {
8467 while ( ( name = attrNames[ i++ ] ) ) {
8468 propName = jQuery.propFix[ name ] || name;
8469
8470 // Boolean attributes get special treatment (#10870)
8471 if ( jQuery.expr.match.bool.test( name ) ) {
8472
8473 // Set corresponding property to false
8474 if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
8475 elem[ propName ] = false;
8476
8477 // Support: IE<9
8478 // Also clear defaultChecked/defaultSelected (if appropriate)
8479 } else {
8480 elem[ jQuery.camelCase( "default-" + name ) ] =
8481 elem[ propName ] = false;
8482 }
8483
8484 // See #9699 for explanation of this approach (setting first, then removal)
8485 } else {
8486 jQuery.attr( elem, name, "" );
8487 }
8488
8489 elem.removeAttribute( getSetAttribute ? name : propName );
8490 }
8491 }
8492 }
8493} );
8494
8495// Hooks for boolean attributes
8496boolHook = {
8497 set: function( elem, value, name ) {
8498 if ( value === false ) {
8499
8500 // Remove boolean attributes when set to false
8501 jQuery.removeAttr( elem, name );
8502 } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
8503
8504 // IE<8 needs the *property* name
8505 elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
8506
8507 } else {
8508
8509 // Support: IE<9
8510 // Use defaultChecked and defaultSelected for oldIE
8511 elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
8512 }
8513 return name;
8514 }
8515};
8516
8517jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
8518 var getter = attrHandle[ name ] || jQuery.find.attr;
8519
8520 if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
8521 attrHandle[ name ] = function( elem, name, isXML ) {
8522 var ret, handle;
8523 if ( !isXML ) {
8524
8525 // Avoid an infinite loop by temporarily removing this function from the getter
8526 handle = attrHandle[ name ];
8527 attrHandle[ name ] = ret;
8528 ret = getter( elem, name, isXML ) != null ?
8529 name.toLowerCase() :
8530 null;
8531 attrHandle[ name ] = handle;
8532 }
8533 return ret;
8534 };
8535 } else {
8536 attrHandle[ name ] = function( elem, name, isXML ) {
8537 if ( !isXML ) {
8538 return elem[ jQuery.camelCase( "default-" + name ) ] ?
8539 name.toLowerCase() :
8540 null;
8541 }
8542 };
8543 }
8544} );
8545
8546// fix oldIE attroperties
8547if ( !getSetInput || !getSetAttribute ) {
8548 jQuery.attrHooks.value = {
8549 set: function( elem, value, name ) {
8550 if ( jQuery.nodeName( elem, "input" ) ) {
8551
8552 // Does not return so that setAttribute is also used
8553 elem.defaultValue = value;
8554 } else {
8555
8556 // Use nodeHook if defined (#1954); otherwise setAttribute is fine
8557 return nodeHook && nodeHook.set( elem, value, name );
8558 }
8559 }
8560 };
8561}
8562
8563// IE6/7 do not support getting/setting some attributes with get/setAttribute
8564if ( !getSetAttribute ) {
8565
8566 // Use this for any attribute in IE6/7
8567 // This fixes almost every IE6/7 issue
8568 nodeHook = {
8569 set: function( elem, value, name ) {
8570
8571 // Set the existing or create a new attribute node
8572 var ret = elem.getAttributeNode( name );
8573 if ( !ret ) {
8574 elem.setAttributeNode(
8575 ( ret = elem.ownerDocument.createAttribute( name ) )
8576 );
8577 }
8578
8579 ret.value = value += "";
8580
8581 // Break association with cloned elements by also using setAttribute (#9646)
8582 if ( name === "value" || value === elem.getAttribute( name ) ) {
8583 return value;
8584 }
8585 }
8586 };
8587
8588 // Some attributes are constructed with empty-string values when not defined
8589 attrHandle.id = attrHandle.name = attrHandle.coords =
8590 function( elem, name, isXML ) {
8591 var ret;
8592 if ( !isXML ) {
8593 return ( ret = elem.getAttributeNode( name ) ) && ret.value !== "" ?
8594 ret.value :
8595 null;
8596 }
8597 };
8598
8599 // Fixing value retrieval on a button requires this module
8600 jQuery.valHooks.button = {
8601 get: function( elem, name ) {
8602 var ret = elem.getAttributeNode( name );
8603 if ( ret && ret.specified ) {
8604 return ret.value;
8605 }
8606 },
8607 set: nodeHook.set
8608 };
8609
8610 // Set contenteditable to false on removals(#10429)
8611 // Setting to empty string throws an error as an invalid value
8612 jQuery.attrHooks.contenteditable = {
8613 set: function( elem, value, name ) {
8614 nodeHook.set( elem, value === "" ? false : value, name );
8615 }
8616 };
8617
8618 // Set width and height to auto instead of 0 on empty string( Bug #8150 )
8619 // This is for removals
8620 jQuery.each( [ "width", "height" ], function( i, name ) {
8621 jQuery.attrHooks[ name ] = {
8622 set: function( elem, value ) {
8623 if ( value === "" ) {
8624 elem.setAttribute( name, "auto" );
8625 return value;
8626 }
8627 }
8628 };
8629 } );
8630}
8631
8632if ( !support.style ) {
8633 jQuery.attrHooks.style = {
8634 get: function( elem ) {
8635
8636 // Return undefined in the case of empty string
8637 // Note: IE uppercases css property names, but if we were to .toLowerCase()
8638 // .cssText, that would destroy case sensitivity in URL's, like in "background"
8639 return elem.style.cssText || undefined;
8640 },
8641 set: function( elem, value ) {
8642 return ( elem.style.cssText = value + "" );
8643 }
8644 };
8645}
8646
8647
8648
8649
8650var rfocusable = /^(?:input|select|textarea|button|object)$/i,
8651 rclickable = /^(?:a|area)$/i;
8652
8653jQuery.fn.extend( {
8654 prop: function( name, value ) {
8655 return access( this, jQuery.prop, name, value, arguments.length > 1 );
8656 },
8657
8658 removeProp: function( name ) {
8659 name = jQuery.propFix[ name ] || name;
8660 return this.each( function() {
8661
8662 // try/catch handles cases where IE balks (such as removing a property on window)
8663 try {
8664 this[ name ] = undefined;
8665 delete this[ name ];
8666 } catch ( e ) {}
8667 } );
8668 }
8669} );
8670
8671jQuery.extend( {
8672 prop: function( elem, name, value ) {
8673 var ret, hooks,
8674 nType = elem.nodeType;
8675
8676 // Don't get/set properties on text, comment and attribute nodes
8677 if ( nType === 3 || nType === 8 || nType === 2 ) {
8678 return;
8679 }
8680
8681 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
8682
8683 // Fix name and attach hooks
8684 name = jQuery.propFix[ name ] || name;
8685 hooks = jQuery.propHooks[ name ];
8686 }
8687
8688 if ( value !== undefined ) {
8689 if ( hooks && "set" in hooks &&
8690 ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
8691 return ret;
8692 }
8693
8694 return ( elem[ name ] = value );
8695 }
8696
8697 if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
8698 return ret;
8699 }
8700
8701 return elem[ name ];
8702 },
8703
8704 propHooks: {
8705 tabIndex: {
8706 get: function( elem ) {
8707
8708 // elem.tabIndex doesn't always return the
8709 // correct value when it hasn't been explicitly set
8710 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
8711 // Use proper attribute retrieval(#12072)
8712 var tabindex = jQuery.find.attr( elem, "tabindex" );
8713
8714 return tabindex ?
8715 parseInt( tabindex, 10 ) :
8716 rfocusable.test( elem.nodeName ) ||
8717 rclickable.test( elem.nodeName ) && elem.href ?
8718 0 :
8719 -1;
8720 }
8721 }
8722 },
8723
8724 propFix: {
8725 "for": "htmlFor",
8726 "class": "className"
8727 }
8728} );
8729
8730// Some attributes require a special call on IE
8731// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
8732if ( !support.hrefNormalized ) {
8733
8734 // href/src property should get the full normalized URL (#10299/#12915)
8735 jQuery.each( [ "href", "src" ], function( i, name ) {
8736 jQuery.propHooks[ name ] = {
8737 get: function( elem ) {
8738 return elem.getAttribute( name, 4 );
8739 }
8740 };
8741 } );
8742}
8743
8744// Support: Safari, IE9+
8745// Accessing the selectedIndex property
8746// forces the browser to respect setting selected
8747// on the option
8748// The getter ensures a default option is selected
8749// when in an optgroup
8750if ( !support.optSelected ) {
8751 jQuery.propHooks.selected = {
8752 get: function( elem ) {
8753 var parent = elem.parentNode;
8754
8755 if ( parent ) {
8756 parent.selectedIndex;
8757
8758 // Make sure that it also works with optgroups, see #5701
8759 if ( parent.parentNode ) {
8760 parent.parentNode.selectedIndex;
8761 }
8762 }
8763 return null;
8764 },
8765 set: function( elem ) {
8766 var parent = elem.parentNode;
8767 if ( parent ) {
8768 parent.selectedIndex;
8769
8770 if ( parent.parentNode ) {
8771 parent.parentNode.selectedIndex;
8772 }
8773 }
8774 }
8775 };
8776}
8777
8778jQuery.each( [
8779 "tabIndex",
8780 "readOnly",
8781 "maxLength",
8782 "cellSpacing",
8783 "cellPadding",
8784 "rowSpan",
8785 "colSpan",
8786 "useMap",
8787 "frameBorder",
8788 "contentEditable"
8789], function() {
8790 jQuery.propFix[ this.toLowerCase() ] = this;
8791} );
8792
8793// IE6/7 call enctype encoding
8794if ( !support.enctype ) {
8795 jQuery.propFix.enctype = "encoding";
8796}
8797
8798
8799
8800
8801var rclass = /[\t\r\n\f]/g;
8802
8803function getClass( elem ) {
8804 return jQuery.attr( elem, "class" ) || "";
8805}
8806
8807jQuery.fn.extend( {
8808 addClass: function( value ) {
8809 var classes, elem, cur, curValue, clazz, j, finalValue,
8810 i = 0;
8811
8812 if ( jQuery.isFunction( value ) ) {
8813 return this.each( function( j ) {
8814 jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
8815 } );
8816 }
8817
8818 if ( typeof value === "string" && value ) {
8819 classes = value.match( rnotwhite ) || [];
8820
8821 while ( ( elem = this[ i++ ] ) ) {
8822 curValue = getClass( elem );
8823 cur = elem.nodeType === 1 &&
8824 ( " " + curValue + " " ).replace( rclass, " " );
8825
8826 if ( cur ) {
8827 j = 0;
8828 while ( ( clazz = classes[ j++ ] ) ) {
8829 if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
8830 cur += clazz + " ";
8831 }
8832 }
8833
8834 // only assign if different to avoid unneeded rendering.
8835 finalValue = jQuery.trim( cur );
8836 if ( curValue !== finalValue ) {
8837 jQuery.attr( elem, "class", finalValue );
8838 }
8839 }
8840 }
8841 }
8842
8843 return this;
8844 },
8845
8846 removeClass: function( value ) {
8847 var classes, elem, cur, curValue, clazz, j, finalValue,
8848 i = 0;
8849
8850 if ( jQuery.isFunction( value ) ) {
8851 return this.each( function( j ) {
8852 jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
8853 } );
8854 }
8855
8856 if ( !arguments.length ) {
8857 return this.attr( "class", "" );
8858 }
8859
8860 if ( typeof value === "string" && value ) {
8861 classes = value.match( rnotwhite ) || [];
8862
8863 while ( ( elem = this[ i++ ] ) ) {
8864 curValue = getClass( elem );
8865
8866 // This expression is here for better compressibility (see addClass)
8867 cur = elem.nodeType === 1 &&
8868 ( " " + curValue + " " ).replace( rclass, " " );
8869
8870 if ( cur ) {
8871 j = 0;
8872 while ( ( clazz = classes[ j++ ] ) ) {
8873
8874 // Remove *all* instances
8875 while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
8876 cur = cur.replace( " " + clazz + " ", " " );
8877 }
8878 }
8879
8880 // Only assign if different to avoid unneeded rendering.
8881 finalValue = jQuery.trim( cur );
8882 if ( curValue !== finalValue ) {
8883 jQuery.attr( elem, "class", finalValue );
8884 }
8885 }
8886 }
8887 }
8888
8889 return this;
8890 },
8891
8892 toggleClass: function( value, stateVal ) {
8893 var type = typeof value;
8894
8895 if ( typeof stateVal === "boolean" && type === "string" ) {
8896 return stateVal ? this.addClass( value ) : this.removeClass( value );
8897 }
8898
8899 if ( jQuery.isFunction( value ) ) {
8900 return this.each( function( i ) {
8901 jQuery( this ).toggleClass(
8902 value.call( this, i, getClass( this ), stateVal ),
8903 stateVal
8904 );
8905 } );
8906 }
8907
8908 return this.each( function() {
8909 var className, i, self, classNames;
8910
8911 if ( type === "string" ) {
8912
8913 // Toggle individual class names
8914 i = 0;
8915 self = jQuery( this );
8916 classNames = value.match( rnotwhite ) || [];
8917
8918 while ( ( className = classNames[ i++ ] ) ) {
8919
8920 // Check each className given, space separated list
8921 if ( self.hasClass( className ) ) {
8922 self.removeClass( className );
8923 } else {
8924 self.addClass( className );
8925 }
8926 }
8927
8928 // Toggle whole class name
8929 } else if ( value === undefined || type === "boolean" ) {
8930 className = getClass( this );
8931 if ( className ) {
8932
8933 // store className if set
8934 jQuery._data( this, "__className__", className );
8935 }
8936
8937 // If the element has a class name or if we're passed "false",
8938 // then remove the whole classname (if there was one, the above saved it).
8939 // Otherwise bring back whatever was previously saved (if anything),
8940 // falling back to the empty string if nothing was stored.
8941 jQuery.attr( this, "class",
8942 className || value === false ?
8943 "" :
8944 jQuery._data( this, "__className__" ) || ""
8945 );
8946 }
8947 } );
8948 },
8949
8950 hasClass: function( selector ) {
8951 var className, elem,
8952 i = 0;
8953
8954 className = " " + selector + " ";
8955 while ( ( elem = this[ i++ ] ) ) {
8956 if ( elem.nodeType === 1 &&
8957 ( " " + getClass( elem ) + " " ).replace( rclass, " " )
8958 .indexOf( className ) > -1
8959 ) {
8960 return true;
8961 }
8962 }
8963
8964 return false;
8965 }
8966} );
8967
8968
8969
8970
8971// Return jQuery for attributes-only inclusion
8972
8973
8974jQuery.each( ( "blur focus focusin focusout load resize scroll unload click dblclick " +
8975 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
8976 "change select submit keydown keypress keyup error contextmenu" ).split( " " ),
8977 function( i, name ) {
8978
8979 // Handle event binding
8980 jQuery.fn[ name ] = function( data, fn ) {
8981 return arguments.length > 0 ?
8982 this.on( name, null, data, fn ) :
8983 this.trigger( name );
8984 };
8985} );
8986
8987jQuery.fn.extend( {
8988 hover: function( fnOver, fnOut ) {
8989 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
8990 }
8991} );
8992
8993
8994var location = window.location;
8995
8996var nonce = jQuery.now();
8997
8998var rquery = ( /\?/ );
8999
9000
9001
9002var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;
9003
9004jQuery.parseJSON = function( data ) {
9005
9006 // Attempt to parse using the native JSON parser first
9007 if ( window.JSON && window.JSON.parse ) {
9008
9009 // Support: Android 2.3
9010 // Workaround failure to string-cast null input
9011 return window.JSON.parse( data + "" );
9012 }
9013
9014 var requireNonComma,
9015 depth = null,
9016 str = jQuery.trim( data + "" );
9017
9018 // Guard against invalid (and possibly dangerous) input by ensuring that nothing remains
9019 // after removing valid tokens
9020 return str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {
9021
9022 // Force termination if we see a misplaced comma
9023 if ( requireNonComma && comma ) {
9024 depth = 0;
9025 }
9026
9027 // Perform no more replacements after returning to outermost depth
9028 if ( depth === 0 ) {
9029 return token;
9030 }
9031
9032 // Commas must not follow "[", "{", or ","
9033 requireNonComma = open || comma;
9034
9035 // Determine new depth
9036 // array/object open ("[" or "{"): depth += true - false (increment)
9037 // array/object close ("]" or "}"): depth += false - true (decrement)
9038 // other cases ("," or primitive): depth += true - true (numeric cast)
9039 depth += !close - !open;
9040
9041 // Remove this token
9042 return "";
9043 } ) ) ?
9044 ( Function( "return " + str ) )() :
9045 jQuery.error( "Invalid JSON: " + data );
9046};
9047
9048
9049// Cross-browser xml parsing
9050jQuery.parseXML = function( data ) {
9051 var xml, tmp;
9052 if ( !data || typeof data !== "string" ) {
9053 return null;
9054 }
9055 try {
9056 if ( window.DOMParser ) { // Standard
9057 tmp = new window.DOMParser();
9058 xml = tmp.parseFromString( data, "text/xml" );
9059 } else { // IE
9060 xml = new window.ActiveXObject( "Microsoft.XMLDOM" );
9061 xml.async = "false";
9062 xml.loadXML( data );
9063 }
9064 } catch ( e ) {
9065 xml = undefined;
9066 }
9067 if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
9068 jQuery.error( "Invalid XML: " + data );
9069 }
9070 return xml;
9071};
9072
9073
9074var
9075 rhash = /#.*$/,
9076 rts = /([?&])_=[^&]*/,
9077
9078 // IE leaves an \r character at EOL
9079 rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg,
9080
9081 // #7653, #8125, #8152: local protocol detection
9082 rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
9083 rnoContent = /^(?:GET|HEAD)$/,
9084 rprotocol = /^\/\//,
9085 rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
9086
9087 /* Prefilters
9088 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
9089 * 2) These are called:
9090 * - BEFORE asking for a transport
9091 * - AFTER param serialization (s.data is a string if s.processData is true)
9092 * 3) key is the dataType
9093 * 4) the catchall symbol "*" can be used
9094 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
9095 */
9096 prefilters = {},
9097
9098 /* Transports bindings
9099 * 1) key is the dataType
9100 * 2) the catchall symbol "*" can be used
9101 * 3) selection will start with transport dataType and THEN go to "*" if needed
9102 */
9103 transports = {},
9104
9105 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
9106 allTypes = "*/".concat( "*" ),
9107
9108 // Document location
9109 ajaxLocation = location.href,
9110
9111 // Segment location into parts
9112 ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
9113
9114// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
9115function addToPrefiltersOrTransports( structure ) {
9116
9117 // dataTypeExpression is optional and defaults to "*"
9118 return function( dataTypeExpression, func ) {
9119
9120 if ( typeof dataTypeExpression !== "string" ) {
9121 func = dataTypeExpression;
9122 dataTypeExpression = "*";
9123 }
9124
9125 var dataType,
9126 i = 0,
9127 dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
9128
9129 if ( jQuery.isFunction( func ) ) {
9130
9131 // For each dataType in the dataTypeExpression
9132 while ( ( dataType = dataTypes[ i++ ] ) ) {
9133
9134 // Prepend if requested
9135 if ( dataType.charAt( 0 ) === "+" ) {
9136 dataType = dataType.slice( 1 ) || "*";
9137 ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
9138
9139 // Otherwise append
9140 } else {
9141 ( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
9142 }
9143 }
9144 }
9145 };
9146}
9147
9148// Base inspection function for prefilters and transports
9149function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
9150
9151 var inspected = {},
9152 seekingTransport = ( structure === transports );
9153
9154 function inspect( dataType ) {
9155 var selected;
9156 inspected[ dataType ] = true;
9157 jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
9158 var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
9159 if ( typeof dataTypeOrTransport === "string" &&
9160 !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
9161
9162 options.dataTypes.unshift( dataTypeOrTransport );
9163 inspect( dataTypeOrTransport );
9164 return false;
9165 } else if ( seekingTransport ) {
9166 return !( selected = dataTypeOrTransport );
9167 }
9168 } );
9169 return selected;
9170 }
9171
9172 return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
9173}
9174
9175// A special extend for ajax options
9176// that takes "flat" options (not to be deep extended)
9177// Fixes #9887
9178function ajaxExtend( target, src ) {
9179 var deep, key,
9180 flatOptions = jQuery.ajaxSettings.flatOptions || {};
9181
9182 for ( key in src ) {
9183 if ( src[ key ] !== undefined ) {
9184 ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
9185 }
9186 }
9187 if ( deep ) {
9188 jQuery.extend( true, target, deep );
9189 }
9190
9191 return target;
9192}
9193
9194/* Handles responses to an ajax request:
9195 * - finds the right dataType (mediates between content-type and expected dataType)
9196 * - returns the corresponding response
9197 */
9198function ajaxHandleResponses( s, jqXHR, responses ) {
9199 var firstDataType, ct, finalDataType, type,
9200 contents = s.contents,
9201 dataTypes = s.dataTypes;
9202
9203 // Remove auto dataType and get content-type in the process
9204 while ( dataTypes[ 0 ] === "*" ) {
9205 dataTypes.shift();
9206 if ( ct === undefined ) {
9207 ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
9208 }
9209 }
9210
9211 // Check if we're dealing with a known content-type
9212 if ( ct ) {
9213 for ( type in contents ) {
9214 if ( contents[ type ] && contents[ type ].test( ct ) ) {
9215 dataTypes.unshift( type );
9216 break;
9217 }
9218 }
9219 }
9220
9221 // Check to see if we have a response for the expected dataType
9222 if ( dataTypes[ 0 ] in responses ) {
9223 finalDataType = dataTypes[ 0 ];
9224 } else {
9225
9226 // Try convertible dataTypes
9227 for ( type in responses ) {
9228 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
9229 finalDataType = type;
9230 break;
9231 }
9232 if ( !firstDataType ) {
9233 firstDataType = type;
9234 }
9235 }
9236
9237 // Or just use first one
9238 finalDataType = finalDataType || firstDataType;
9239 }
9240
9241 // If we found a dataType
9242 // We add the dataType to the list if needed
9243 // and return the corresponding response
9244 if ( finalDataType ) {
9245 if ( finalDataType !== dataTypes[ 0 ] ) {
9246 dataTypes.unshift( finalDataType );
9247 }
9248 return responses[ finalDataType ];
9249 }
9250}
9251
9252/* Chain conversions given the request and the original response
9253 * Also sets the responseXXX fields on the jqXHR instance
9254 */
9255function ajaxConvert( s, response, jqXHR, isSuccess ) {
9256 var conv2, current, conv, tmp, prev,
9257 converters = {},
9258
9259 // Work with a copy of dataTypes in case we need to modify it for conversion
9260 dataTypes = s.dataTypes.slice();
9261
9262 // Create converters map with lowercased keys
9263 if ( dataTypes[ 1 ] ) {
9264 for ( conv in s.converters ) {
9265 converters[ conv.toLowerCase() ] = s.converters[ conv ];
9266 }
9267 }
9268
9269 current = dataTypes.shift();
9270
9271 // Convert to each sequential dataType
9272 while ( current ) {
9273
9274 if ( s.responseFields[ current ] ) {
9275 jqXHR[ s.responseFields[ current ] ] = response;
9276 }
9277
9278 // Apply the dataFilter if provided
9279 if ( !prev && isSuccess && s.dataFilter ) {
9280 response = s.dataFilter( response, s.dataType );
9281 }
9282
9283 prev = current;
9284 current = dataTypes.shift();
9285
9286 if ( current ) {
9287
9288 // There's only work to do if current dataType is non-auto
9289 if ( current === "*" ) {
9290
9291 current = prev;
9292
9293 // Convert response if prev dataType is non-auto and differs from current
9294 } else if ( prev !== "*" && prev !== current ) {
9295
9296 // Seek a direct converter
9297 conv = converters[ prev + " " + current ] || converters[ "* " + current ];
9298
9299 // If none found, seek a pair
9300 if ( !conv ) {
9301 for ( conv2 in converters ) {
9302
9303 // If conv2 outputs current
9304 tmp = conv2.split( " " );
9305 if ( tmp[ 1 ] === current ) {
9306
9307 // If prev can be converted to accepted input
9308 conv = converters[ prev + " " + tmp[ 0 ] ] ||
9309 converters[ "* " + tmp[ 0 ] ];
9310 if ( conv ) {
9311
9312 // Condense equivalence converters
9313 if ( conv === true ) {
9314 conv = converters[ conv2 ];
9315
9316 // Otherwise, insert the intermediate dataType
9317 } else if ( converters[ conv2 ] !== true ) {
9318 current = tmp[ 0 ];
9319 dataTypes.unshift( tmp[ 1 ] );
9320 }
9321 break;
9322 }
9323 }
9324 }
9325 }
9326
9327 // Apply converter (if not an equivalence)
9328 if ( conv !== true ) {
9329
9330 // Unless errors are allowed to bubble, catch and return them
9331 if ( conv && s[ "throws" ] ) { // jscs:ignore requireDotNotation
9332 response = conv( response );
9333 } else {
9334 try {
9335 response = conv( response );
9336 } catch ( e ) {
9337 return {
9338 state: "parsererror",
9339 error: conv ? e : "No conversion from " + prev + " to " + current
9340 };
9341 }
9342 }
9343 }
9344 }
9345 }
9346 }
9347
9348 return { state: "success", data: response };
9349}
9350
9351jQuery.extend( {
9352
9353 // Counter for holding the number of active queries
9354 active: 0,
9355
9356 // Last-Modified header cache for next request
9357 lastModified: {},
9358 etag: {},
9359
9360 ajaxSettings: {
9361 url: ajaxLocation,
9362 type: "GET",
9363 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
9364 global: true,
9365 processData: true,
9366 async: true,
9367 contentType: "application/x-www-form-urlencoded; charset=UTF-8",
9368 /*
9369 timeout: 0,
9370 data: null,
9371 dataType: null,
9372 username: null,
9373 password: null,
9374 cache: null,
9375 throws: false,
9376 traditional: false,
9377 headers: {},
9378 */
9379
9380 accepts: {
9381 "*": allTypes,
9382 text: "text/plain",
9383 html: "text/html",
9384 xml: "application/xml, text/xml",
9385 json: "application/json, text/javascript"
9386 },
9387
9388 contents: {
9389 xml: /\bxml\b/,
9390 html: /\bhtml/,
9391 json: /\bjson\b/
9392 },
9393
9394 responseFields: {
9395 xml: "responseXML",
9396 text: "responseText",
9397 json: "responseJSON"
9398 },
9399
9400 // Data converters
9401 // Keys separate source (or catchall "*") and destination types with a single space
9402 converters: {
9403
9404 // Convert anything to text
9405 "* text": String,
9406
9407 // Text to html (true = no transformation)
9408 "text html": true,
9409
9410 // Evaluate text as a json expression
9411 "text json": jQuery.parseJSON,
9412
9413 // Parse text as xml
9414 "text xml": jQuery.parseXML
9415 },
9416
9417 // For options that shouldn't be deep extended:
9418 // you can add your own custom options here if
9419 // and when you create one that shouldn't be
9420 // deep extended (see ajaxExtend)
9421 flatOptions: {
9422 url: true,
9423 context: true
9424 }
9425 },
9426
9427 // Creates a full fledged settings object into target
9428 // with both ajaxSettings and settings fields.
9429 // If target is omitted, writes into ajaxSettings.
9430 ajaxSetup: function( target, settings ) {
9431 return settings ?
9432
9433 // Building a settings object
9434 ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
9435
9436 // Extending ajaxSettings
9437 ajaxExtend( jQuery.ajaxSettings, target );
9438 },
9439
9440 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
9441 ajaxTransport: addToPrefiltersOrTransports( transports ),
9442
9443 // Main method
9444 ajax: function( url, options ) {
9445
9446 // If url is an object, simulate pre-1.5 signature
9447 if ( typeof url === "object" ) {
9448 options = url;
9449 url = undefined;
9450 }
9451
9452 // Force options to be an object
9453 options = options || {};
9454
9455 var
9456
9457 // Cross-domain detection vars
9458 parts,
9459
9460 // Loop variable
9461 i,
9462
9463 // URL without anti-cache param
9464 cacheURL,
9465
9466 // Response headers as string
9467 responseHeadersString,
9468
9469 // timeout handle
9470 timeoutTimer,
9471
9472 // To know if global events are to be dispatched
9473 fireGlobals,
9474
9475 transport,
9476
9477 // Response headers
9478 responseHeaders,
9479
9480 // Create the final options object
9481 s = jQuery.ajaxSetup( {}, options ),
9482
9483 // Callbacks context
9484 callbackContext = s.context || s,
9485
9486 // Context for global events is callbackContext if it is a DOM node or jQuery collection
9487 globalEventContext = s.context &&
9488 ( callbackContext.nodeType || callbackContext.jquery ) ?
9489 jQuery( callbackContext ) :
9490 jQuery.event,
9491
9492 // Deferreds
9493 deferred = jQuery.Deferred(),
9494 completeDeferred = jQuery.Callbacks( "once memory" ),
9495
9496 // Status-dependent callbacks
9497 statusCode = s.statusCode || {},
9498
9499 // Headers (they are sent all at once)
9500 requestHeaders = {},
9501 requestHeadersNames = {},
9502
9503 // The jqXHR state
9504 state = 0,
9505
9506 // Default abort message
9507 strAbort = "canceled",
9508
9509 // Fake xhr
9510 jqXHR = {
9511 readyState: 0,
9512
9513 // Builds headers hashtable if needed
9514 getResponseHeader: function( key ) {
9515 var match;
9516 if ( state === 2 ) {
9517 if ( !responseHeaders ) {
9518 responseHeaders = {};
9519 while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
9520 responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
9521 }
9522 }
9523 match = responseHeaders[ key.toLowerCase() ];
9524 }
9525 return match == null ? null : match;
9526 },
9527
9528 // Raw string
9529 getAllResponseHeaders: function() {
9530 return state === 2 ? responseHeadersString : null;
9531 },
9532
9533 // Caches the header
9534 setRequestHeader: function( name, value ) {
9535 var lname = name.toLowerCase();
9536 if ( !state ) {
9537 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
9538 requestHeaders[ name ] = value;
9539 }
9540 return this;
9541 },
9542
9543 // Overrides response content-type header
9544 overrideMimeType: function( type ) {
9545 if ( !state ) {
9546 s.mimeType = type;
9547 }
9548 return this;
9549 },
9550
9551 // Status-dependent callbacks
9552 statusCode: function( map ) {
9553 var code;
9554 if ( map ) {
9555 if ( state < 2 ) {
9556 for ( code in map ) {
9557
9558 // Lazy-add the new callback in a way that preserves old ones
9559 statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
9560 }
9561 } else {
9562
9563 // Execute the appropriate callbacks
9564 jqXHR.always( map[ jqXHR.status ] );
9565 }
9566 }
9567 return this;
9568 },
9569
9570 // Cancel the request
9571 abort: function( statusText ) {
9572 var finalText = statusText || strAbort;
9573 if ( transport ) {
9574 transport.abort( finalText );
9575 }
9576 done( 0, finalText );
9577 return this;
9578 }
9579 };
9580
9581 // Attach deferreds
9582 deferred.promise( jqXHR ).complete = completeDeferred.add;
9583 jqXHR.success = jqXHR.done;
9584 jqXHR.error = jqXHR.fail;
9585
9586 // Remove hash character (#7531: and string promotion)
9587 // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
9588 // Handle falsy url in the settings object (#10093: consistency with old signature)
9589 // We also use the url parameter if available
9590 s.url = ( ( url || s.url || ajaxLocation ) + "" )
9591 .replace( rhash, "" )
9592 .replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
9593
9594 // Alias method option to type as per ticket #12004
9595 s.type = options.method || options.type || s.method || s.type;
9596
9597 // Extract dataTypes list
9598 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
9599
9600 // A cross-domain request is in order when we have a protocol:host:port mismatch
9601 if ( s.crossDomain == null ) {
9602 parts = rurl.exec( s.url.toLowerCase() );
9603 s.crossDomain = !!( parts &&
9604 ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
9605 ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
9606 ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
9607 );
9608 }
9609
9610 // Convert data if not already a string
9611 if ( s.data && s.processData && typeof s.data !== "string" ) {
9612 s.data = jQuery.param( s.data, s.traditional );
9613 }
9614
9615 // Apply prefilters
9616 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
9617
9618 // If request was aborted inside a prefilter, stop there
9619 if ( state === 2 ) {
9620 return jqXHR;
9621 }
9622
9623 // We can fire global events as of now if asked to
9624 // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
9625 fireGlobals = jQuery.event && s.global;
9626
9627 // Watch for a new set of requests
9628 if ( fireGlobals && jQuery.active++ === 0 ) {
9629 jQuery.event.trigger( "ajaxStart" );
9630 }
9631
9632 // Uppercase the type
9633 s.type = s.type.toUpperCase();
9634
9635 // Determine if request has content
9636 s.hasContent = !rnoContent.test( s.type );
9637
9638 // Save the URL in case we're toying with the If-Modified-Since
9639 // and/or If-None-Match header later on
9640 cacheURL = s.url;
9641
9642 // More options handling for requests with no content
9643 if ( !s.hasContent ) {
9644
9645 // If data is available, append data to url
9646 if ( s.data ) {
9647 cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
9648
9649 // #9682: remove data so that it's not used in an eventual retry
9650 delete s.data;
9651 }
9652
9653 // Add anti-cache in url if needed
9654 if ( s.cache === false ) {
9655 s.url = rts.test( cacheURL ) ?
9656
9657 // If there is already a '_' parameter, set its value
9658 cacheURL.replace( rts, "$1_=" + nonce++ ) :
9659
9660 // Otherwise add one to the end
9661 cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
9662 }
9663 }
9664
9665 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9666 if ( s.ifModified ) {
9667 if ( jQuery.lastModified[ cacheURL ] ) {
9668 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
9669 }
9670 if ( jQuery.etag[ cacheURL ] ) {
9671 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
9672 }
9673 }
9674
9675 // Set the correct header, if data is being sent
9676 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
9677 jqXHR.setRequestHeader( "Content-Type", s.contentType );
9678 }
9679
9680 // Set the Accepts header for the server, depending on the dataType
9681 jqXHR.setRequestHeader(
9682 "Accept",
9683 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
9684 s.accepts[ s.dataTypes[ 0 ] ] +
9685 ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
9686 s.accepts[ "*" ]
9687 );
9688
9689 // Check for headers option
9690 for ( i in s.headers ) {
9691 jqXHR.setRequestHeader( i, s.headers[ i ] );
9692 }
9693
9694 // Allow custom headers/mimetypes and early abort
9695 if ( s.beforeSend &&
9696 ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
9697
9698 // Abort if not done already and return
9699 return jqXHR.abort();
9700 }
9701
9702 // aborting is no longer a cancellation
9703 strAbort = "abort";
9704
9705 // Install callbacks on deferreds
9706 for ( i in { success: 1, error: 1, complete: 1 } ) {
9707 jqXHR[ i ]( s[ i ] );
9708 }
9709
9710 // Get transport
9711 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
9712
9713 // If no transport, we auto-abort
9714 if ( !transport ) {
9715 done( -1, "No Transport" );
9716 } else {
9717 jqXHR.readyState = 1;
9718
9719 // Send global event
9720 if ( fireGlobals ) {
9721 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
9722 }
9723
9724 // If request was aborted inside ajaxSend, stop there
9725 if ( state === 2 ) {
9726 return jqXHR;
9727 }
9728
9729 // Timeout
9730 if ( s.async && s.timeout > 0 ) {
9731 timeoutTimer = window.setTimeout( function() {
9732 jqXHR.abort( "timeout" );
9733 }, s.timeout );
9734 }
9735
9736 try {
9737 state = 1;
9738 transport.send( requestHeaders, done );
9739 } catch ( e ) {
9740
9741 // Propagate exception as error if not done
9742 if ( state < 2 ) {
9743 done( -1, e );
9744
9745 // Simply rethrow otherwise
9746 } else {
9747 throw e;
9748 }
9749 }
9750 }
9751
9752 // Callback for when everything is done
9753 function done( status, nativeStatusText, responses, headers ) {
9754 var isSuccess, success, error, response, modified,
9755 statusText = nativeStatusText;
9756
9757 // Called once
9758 if ( state === 2 ) {
9759 return;
9760 }
9761
9762 // State is "done" now
9763 state = 2;
9764
9765 // Clear timeout if it exists
9766 if ( timeoutTimer ) {
9767 window.clearTimeout( timeoutTimer );
9768 }
9769
9770 // Dereference transport for early garbage collection
9771 // (no matter how long the jqXHR object will be used)
9772 transport = undefined;
9773
9774 // Cache response headers
9775 responseHeadersString = headers || "";
9776
9777 // Set readyState
9778 jqXHR.readyState = status > 0 ? 4 : 0;
9779
9780 // Determine if successful
9781 isSuccess = status >= 200 && status < 300 || status === 304;
9782
9783 // Get response data
9784 if ( responses ) {
9785 response = ajaxHandleResponses( s, jqXHR, responses );
9786 }
9787
9788 // Convert no matter what (that way responseXXX fields are always set)
9789 response = ajaxConvert( s, response, jqXHR, isSuccess );
9790
9791 // If successful, handle type chaining
9792 if ( isSuccess ) {
9793
9794 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9795 if ( s.ifModified ) {
9796 modified = jqXHR.getResponseHeader( "Last-Modified" );
9797 if ( modified ) {
9798 jQuery.lastModified[ cacheURL ] = modified;
9799 }
9800 modified = jqXHR.getResponseHeader( "etag" );
9801 if ( modified ) {
9802 jQuery.etag[ cacheURL ] = modified;
9803 }
9804 }
9805
9806 // if no content
9807 if ( status === 204 || s.type === "HEAD" ) {
9808 statusText = "nocontent";
9809
9810 // if not modified
9811 } else if ( status === 304 ) {
9812 statusText = "notmodified";
9813
9814 // If we have data, let's convert it
9815 } else {
9816 statusText = response.state;
9817 success = response.data;
9818 error = response.error;
9819 isSuccess = !error;
9820 }
9821 } else {
9822
9823 // We extract error from statusText
9824 // then normalize statusText and status for non-aborts
9825 error = statusText;
9826 if ( status || !statusText ) {
9827 statusText = "error";
9828 if ( status < 0 ) {
9829 status = 0;
9830 }
9831 }
9832 }
9833
9834 // Set data for the fake xhr object
9835 jqXHR.status = status;
9836 jqXHR.statusText = ( nativeStatusText || statusText ) + "";
9837
9838 // Success/Error
9839 if ( isSuccess ) {
9840 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
9841 } else {
9842 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
9843 }
9844
9845 // Status-dependent callbacks
9846 jqXHR.statusCode( statusCode );
9847 statusCode = undefined;
9848
9849 if ( fireGlobals ) {
9850 globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
9851 [ jqXHR, s, isSuccess ? success : error ] );
9852 }
9853
9854 // Complete
9855 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
9856
9857 if ( fireGlobals ) {
9858 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
9859
9860 // Handle the global AJAX counter
9861 if ( !( --jQuery.active ) ) {
9862 jQuery.event.trigger( "ajaxStop" );
9863 }
9864 }
9865 }
9866
9867 return jqXHR;
9868 },
9869
9870 getJSON: function( url, data, callback ) {
9871 return jQuery.get( url, data, callback, "json" );
9872 },
9873
9874 getScript: function( url, callback ) {
9875 return jQuery.get( url, undefined, callback, "script" );
9876 }
9877} );
9878
9879jQuery.each( [ "get", "post" ], function( i, method ) {
9880 jQuery[ method ] = function( url, data, callback, type ) {
9881
9882 // shift arguments if data argument was omitted
9883 if ( jQuery.isFunction( data ) ) {
9884 type = type || callback;
9885 callback = data;
9886 data = undefined;
9887 }
9888
9889 // The url can be an options object (which then must have .url)
9890 return jQuery.ajax( jQuery.extend( {
9891 url: url,
9892 type: method,
9893 dataType: type,
9894 data: data,
9895 success: callback
9896 }, jQuery.isPlainObject( url ) && url ) );
9897 };
9898} );
9899
9900
9901jQuery._evalUrl = function( url ) {
9902 return jQuery.ajax( {
9903 url: url,
9904
9905 // Make this explicit, since user can override this through ajaxSetup (#11264)
9906 type: "GET",
9907 dataType: "script",
9908 cache: true,
9909 async: false,
9910 global: false,
9911 "throws": true
9912 } );
9913};
9914
9915
9916jQuery.fn.extend( {
9917 wrapAll: function( html ) {
9918 if ( jQuery.isFunction( html ) ) {
9919 return this.each( function( i ) {
9920 jQuery( this ).wrapAll( html.call( this, i ) );
9921 } );
9922 }
9923
9924 if ( this[ 0 ] ) {
9925
9926 // The elements to wrap the target around
9927 var wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
9928
9929 if ( this[ 0 ].parentNode ) {
9930 wrap.insertBefore( this[ 0 ] );
9931 }
9932
9933 wrap.map( function() {
9934 var elem = this;
9935
9936 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
9937 elem = elem.firstChild;
9938 }
9939
9940 return elem;
9941 } ).append( this );
9942 }
9943
9944 return this;
9945 },
9946
9947 wrapInner: function( html ) {
9948 if ( jQuery.isFunction( html ) ) {
9949 return this.each( function( i ) {
9950 jQuery( this ).wrapInner( html.call( this, i ) );
9951 } );
9952 }
9953
9954 return this.each( function() {
9955 var self = jQuery( this ),
9956 contents = self.contents();
9957
9958 if ( contents.length ) {
9959 contents.wrapAll( html );
9960
9961 } else {
9962 self.append( html );
9963 }
9964 } );
9965 },
9966
9967 wrap: function( html ) {
9968 var isFunction = jQuery.isFunction( html );
9969
9970 return this.each( function( i ) {
9971 jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );
9972 } );
9973 },
9974
9975 unwrap: function() {
9976 return this.parent().each( function() {
9977 if ( !jQuery.nodeName( this, "body" ) ) {
9978 jQuery( this ).replaceWith( this.childNodes );
9979 }
9980 } ).end();
9981 }
9982} );
9983
9984
9985function getDisplay( elem ) {
9986 return elem.style && elem.style.display || jQuery.css( elem, "display" );
9987}
9988
9989function filterHidden( elem ) {
9990
9991 // Disconnected elements are considered hidden
9992 if ( !jQuery.contains( elem.ownerDocument || document, elem ) ) {
9993 return true;
9994 }
9995 while ( elem && elem.nodeType === 1 ) {
9996 if ( getDisplay( elem ) === "none" || elem.type === "hidden" ) {
9997 return true;
9998 }
9999 elem = elem.parentNode;
10000 }
10001 return false;
10002}
10003
10004jQuery.expr.filters.hidden = function( elem ) {
10005
10006 // Support: Opera <= 12.12
10007 // Opera reports offsetWidths and offsetHeights less than zero on some elements
10008 return support.reliableHiddenOffsets() ?
10009 ( elem.offsetWidth <= 0 && elem.offsetHeight <= 0 &&
10010 !elem.getClientRects().length ) :
10011 filterHidden( elem );
10012};
10013
10014jQuery.expr.filters.visible = function( elem ) {
10015 return !jQuery.expr.filters.hidden( elem );
10016};
10017
10018
10019
10020
10021var r20 = /%20/g,
10022 rbracket = /\[\]$/,
10023 rCRLF = /\r?\n/g,
10024 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
10025 rsubmittable = /^(?:input|select|textarea|keygen)/i;
10026
10027function buildParams( prefix, obj, traditional, add ) {
10028 var name;
10029
10030 if ( jQuery.isArray( obj ) ) {
10031
10032 // Serialize array item.
10033 jQuery.each( obj, function( i, v ) {
10034 if ( traditional || rbracket.test( prefix ) ) {
10035
10036 // Treat each array item as a scalar.
10037 add( prefix, v );
10038
10039 } else {
10040
10041 // Item is non-scalar (array or object), encode its numeric index.
10042 buildParams(
10043 prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
10044 v,
10045 traditional,
10046 add
10047 );
10048 }
10049 } );
10050
10051 } else if ( !traditional && jQuery.type( obj ) === "object" ) {
10052
10053 // Serialize object item.
10054 for ( name in obj ) {
10055 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
10056 }
10057
10058 } else {
10059
10060 // Serialize scalar item.
10061 add( prefix, obj );
10062 }
10063}
10064
10065// Serialize an array of form elements or a set of
10066// key/values into a query string
10067jQuery.param = function( a, traditional ) {
10068 var prefix,
10069 s = [],
10070 add = function( key, value ) {
10071
10072 // If value is a function, invoke it and return its value
10073 value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
10074 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
10075 };
10076
10077 // Set traditional to true for jQuery <= 1.3.2 behavior.
10078 if ( traditional === undefined ) {
10079 traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
10080 }
10081
10082 // If an array was passed in, assume that it is an array of form elements.
10083 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
10084
10085 // Serialize the form elements
10086 jQuery.each( a, function() {
10087 add( this.name, this.value );
10088 } );
10089
10090 } else {
10091
10092 // If traditional, encode the "old" way (the way 1.3.2 or older
10093 // did it), otherwise encode params recursively.
10094 for ( prefix in a ) {
10095 buildParams( prefix, a[ prefix ], traditional, add );
10096 }
10097 }
10098
10099 // Return the resulting serialization
10100 return s.join( "&" ).replace( r20, "+" );
10101};
10102
10103jQuery.fn.extend( {
10104 serialize: function() {
10105 return jQuery.param( this.serializeArray() );
10106 },
10107 serializeArray: function() {
10108 return this.map( function() {
10109
10110 // Can add propHook for "elements" to filter or add form elements
10111 var elements = jQuery.prop( this, "elements" );
10112 return elements ? jQuery.makeArray( elements ) : this;
10113 } )
10114 .filter( function() {
10115 var type = this.type;
10116
10117 // Use .is(":disabled") so that fieldset[disabled] works
10118 return this.name && !jQuery( this ).is( ":disabled" ) &&
10119 rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
10120 ( this.checked || !rcheckableType.test( type ) );
10121 } )
10122 .map( function( i, elem ) {
10123 var val = jQuery( this ).val();
10124
10125 return val == null ?
10126 null :
10127 jQuery.isArray( val ) ?
10128 jQuery.map( val, function( val ) {
10129 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
10130 } ) :
10131 { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
10132 } ).get();
10133 }
10134} );
10135
10136
10137// Create the request object
10138// (This is still attached to ajaxSettings for backward compatibility)
10139jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
10140
10141 // Support: IE6-IE8
10142 function() {
10143
10144 // XHR cannot access local files, always use ActiveX for that case
10145 if ( this.isLocal ) {
10146 return createActiveXHR();
10147 }
10148
10149 // Support: IE 9-11
10150 // IE seems to error on cross-domain PATCH requests when ActiveX XHR
10151 // is used. In IE 9+ always use the native XHR.
10152 // Note: this condition won't catch Edge as it doesn't define
10153 // document.documentMode but it also doesn't support ActiveX so it won't
10154 // reach this code.
10155 if ( document.documentMode > 8 ) {
10156 return createStandardXHR();
10157 }
10158
10159 // Support: IE<9
10160 // oldIE XHR does not support non-RFC2616 methods (#13240)
10161 // See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
10162 // and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
10163 // Although this check for six methods instead of eight
10164 // since IE also does not support "trace" and "connect"
10165 return /^(get|post|head|put|delete|options)$/i.test( this.type ) &&
10166 createStandardXHR() || createActiveXHR();
10167 } :
10168
10169 // For all other browsers, use the standard XMLHttpRequest object
10170 createStandardXHR;
10171
10172var xhrId = 0,
10173 xhrCallbacks = {},
10174 xhrSupported = jQuery.ajaxSettings.xhr();
10175
10176// Support: IE<10
10177// Open requests must be manually aborted on unload (#5280)
10178// See https://support.microsoft.com/kb/2856746 for more info
10179if ( window.attachEvent ) {
10180 window.attachEvent( "onunload", function() {
10181 for ( var key in xhrCallbacks ) {
10182 xhrCallbacks[ key ]( undefined, true );
10183 }
10184 } );
10185}
10186
10187// Determine support properties
10188support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
10189xhrSupported = support.ajax = !!xhrSupported;
10190
10191// Create transport if the browser can provide an xhr
10192if ( xhrSupported ) {
10193
10194 jQuery.ajaxTransport( function( options ) {
10195
10196 // Cross domain only allowed if supported through XMLHttpRequest
10197 if ( !options.crossDomain || support.cors ) {
10198
10199 var callback;
10200
10201 return {
10202 send: function( headers, complete ) {
10203 var i,
10204 xhr = options.xhr(),
10205 id = ++xhrId;
10206
10207 // Open the socket
10208 xhr.open(
10209 options.type,
10210 options.url,
10211 options.async,
10212 options.username,
10213 options.password
10214 );
10215
10216 // Apply custom fields if provided
10217 if ( options.xhrFields ) {
10218 for ( i in options.xhrFields ) {
10219 xhr[ i ] = options.xhrFields[ i ];
10220 }
10221 }
10222
10223 // Override mime type if needed
10224 if ( options.mimeType && xhr.overrideMimeType ) {
10225 xhr.overrideMimeType( options.mimeType );
10226 }
10227
10228 // X-Requested-With header
10229 // For cross-domain requests, seeing as conditions for a preflight are
10230 // akin to a jigsaw puzzle, we simply never set it to be sure.
10231 // (it can always be set on a per-request basis or even using ajaxSetup)
10232 // For same-domain requests, won't change header if already provided.
10233 if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
10234 headers[ "X-Requested-With" ] = "XMLHttpRequest";
10235 }
10236
10237 // Set headers
10238 for ( i in headers ) {
10239
10240 // Support: IE<9
10241 // IE's ActiveXObject throws a 'Type Mismatch' exception when setting
10242 // request header to a null-value.
10243 //
10244 // To keep consistent with other XHR implementations, cast the value
10245 // to string and ignore `undefined`.
10246 if ( headers[ i ] !== undefined ) {
10247 xhr.setRequestHeader( i, headers[ i ] + "" );
10248 }
10249 }
10250
10251 // Do send the request
10252 // This may raise an exception which is actually
10253 // handled in jQuery.ajax (so no try/catch here)
10254 xhr.send( ( options.hasContent && options.data ) || null );
10255
10256 // Listener
10257 callback = function( _, isAbort ) {
10258 var status, statusText, responses;
10259
10260 // Was never called and is aborted or complete
10261 if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
10262
10263 // Clean up
10264 delete xhrCallbacks[ id ];
10265 callback = undefined;
10266 xhr.onreadystatechange = jQuery.noop;
10267
10268 // Abort manually if needed
10269 if ( isAbort ) {
10270 if ( xhr.readyState !== 4 ) {
10271 xhr.abort();
10272 }
10273 } else {
10274 responses = {};
10275 status = xhr.status;
10276
10277 // Support: IE<10
10278 // Accessing binary-data responseText throws an exception
10279 // (#11426)
10280 if ( typeof xhr.responseText === "string" ) {
10281 responses.text = xhr.responseText;
10282 }
10283
10284 // Firefox throws an exception when accessing
10285 // statusText for faulty cross-domain requests
10286 try {
10287 statusText = xhr.statusText;
10288 } catch ( e ) {
10289
10290 // We normalize with Webkit giving an empty statusText
10291 statusText = "";
10292 }
10293
10294 // Filter status for non standard behaviors
10295
10296 // If the request is local and we have data: assume a success
10297 // (success with no data won't get notified, that's the best we
10298 // can do given current implementations)
10299 if ( !status && options.isLocal && !options.crossDomain ) {
10300 status = responses.text ? 200 : 404;
10301
10302 // IE - #1450: sometimes returns 1223 when it should be 204
10303 } else if ( status === 1223 ) {
10304 status = 204;
10305 }
10306 }
10307 }
10308
10309 // Call complete if needed
10310 if ( responses ) {
10311 complete( status, statusText, responses, xhr.getAllResponseHeaders() );
10312 }
10313 };
10314
10315 // Do send the request
10316 // `xhr.send` may raise an exception, but it will be
10317 // handled in jQuery.ajax (so no try/catch here)
10318 if ( !options.async ) {
10319
10320 // If we're in sync mode we fire the callback
10321 callback();
10322 } else if ( xhr.readyState === 4 ) {
10323
10324 // (IE6 & IE7) if it's in cache and has been
10325 // retrieved directly we need to fire the callback
10326 window.setTimeout( callback );
10327 } else {
10328
10329 // Register the callback, but delay it in case `xhr.send` throws
10330 // Add to the list of active xhr callbacks
10331 xhr.onreadystatechange = xhrCallbacks[ id ] = callback;
10332 }
10333 },
10334
10335 abort: function() {
10336 if ( callback ) {
10337 callback( undefined, true );
10338 }
10339 }
10340 };
10341 }
10342 } );
10343}
10344
10345// Functions to create xhrs
10346function createStandardXHR() {
10347 try {
10348 return new window.XMLHttpRequest();
10349 } catch ( e ) {}
10350}
10351
10352function createActiveXHR() {
10353 try {
10354 return new window.ActiveXObject( "Microsoft.XMLHTTP" );
10355 } catch ( e ) {}
10356}
10357
10358
10359
10360
10361// Install script dataType
10362jQuery.ajaxSetup( {
10363 accepts: {
10364 script: "text/javascript, application/javascript, " +
10365 "application/ecmascript, application/x-ecmascript"
10366 },
10367 contents: {
10368 script: /\b(?:java|ecma)script\b/
10369 },
10370 converters: {
10371 "text script": function( text ) {
10372 jQuery.globalEval( text );
10373 return text;
10374 }
10375 }
10376} );
10377
10378// Handle cache's special case and global
10379jQuery.ajaxPrefilter( "script", function( s ) {
10380 if ( s.cache === undefined ) {
10381 s.cache = false;
10382 }
10383 if ( s.crossDomain ) {
10384 s.type = "GET";
10385 s.global = false;
10386 }
10387} );
10388
10389// Bind script tag hack transport
10390jQuery.ajaxTransport( "script", function( s ) {
10391
10392 // This transport only deals with cross domain requests
10393 if ( s.crossDomain ) {
10394
10395 var script,
10396 head = document.head || jQuery( "head" )[ 0 ] || document.documentElement;
10397
10398 return {
10399
10400 send: function( _, callback ) {
10401
10402 script = document.createElement( "script" );
10403
10404 script.async = true;
10405
10406 if ( s.scriptCharset ) {
10407 script.charset = s.scriptCharset;
10408 }
10409
10410 script.src = s.url;
10411
10412 // Attach handlers for all browsers
10413 script.onload = script.onreadystatechange = function( _, isAbort ) {
10414
10415 if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
10416
10417 // Handle memory leak in IE
10418 script.onload = script.onreadystatechange = null;
10419
10420 // Remove the script
10421 if ( script.parentNode ) {
10422 script.parentNode.removeChild( script );
10423 }
10424
10425 // Dereference the script
10426 script = null;
10427
10428 // Callback if not abort
10429 if ( !isAbort ) {
10430 callback( 200, "success" );
10431 }
10432 }
10433 };
10434
10435 // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
10436 // Use native DOM manipulation to avoid our domManip AJAX trickery
10437 head.insertBefore( script, head.firstChild );
10438 },
10439
10440 abort: function() {
10441 if ( script ) {
10442 script.onload( undefined, true );
10443 }
10444 }
10445 };
10446 }
10447} );
10448
10449
10450
10451
10452var oldCallbacks = [],
10453 rjsonp = /(=)\?(?=&|$)|\?\?/;
10454
10455// Default jsonp settings
10456jQuery.ajaxSetup( {
10457 jsonp: "callback",
10458 jsonpCallback: function() {
10459 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
10460 this[ callback ] = true;
10461 return callback;
10462 }
10463} );
10464
10465// Detect, normalize options and install callbacks for jsonp requests
10466jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
10467
10468 var callbackName, overwritten, responseContainer,
10469 jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
10470 "url" :
10471 typeof s.data === "string" &&
10472 ( s.contentType || "" )
10473 .indexOf( "application/x-www-form-urlencoded" ) === 0 &&
10474 rjsonp.test( s.data ) && "data"
10475 );
10476
10477 // Handle iff the expected data type is "jsonp" or we have a parameter to set
10478 if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
10479
10480 // Get callback name, remembering preexisting value associated with it
10481 callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
10482 s.jsonpCallback() :
10483 s.jsonpCallback;
10484
10485 // Insert callback into url or form data
10486 if ( jsonProp ) {
10487 s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
10488 } else if ( s.jsonp !== false ) {
10489 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
10490 }
10491
10492 // Use data converter to retrieve json after script execution
10493 s.converters[ "script json" ] = function() {
10494 if ( !responseContainer ) {
10495 jQuery.error( callbackName + " was not called" );
10496 }
10497 return responseContainer[ 0 ];
10498 };
10499
10500 // force json dataType
10501 s.dataTypes[ 0 ] = "json";
10502
10503 // Install callback
10504 overwritten = window[ callbackName ];
10505 window[ callbackName ] = function() {
10506 responseContainer = arguments;
10507 };
10508
10509 // Clean-up function (fires after converters)
10510 jqXHR.always( function() {
10511
10512 // If previous value didn't exist - remove it
10513 if ( overwritten === undefined ) {
10514 jQuery( window ).removeProp( callbackName );
10515
10516 // Otherwise restore preexisting value
10517 } else {
10518 window[ callbackName ] = overwritten;
10519 }
10520
10521 // Save back as free
10522 if ( s[ callbackName ] ) {
10523
10524 // make sure that re-using the options doesn't screw things around
10525 s.jsonpCallback = originalSettings.jsonpCallback;
10526
10527 // save the callback name for future use
10528 oldCallbacks.push( callbackName );
10529 }
10530
10531 // Call if it was a function and we have a response
10532 if ( responseContainer && jQuery.isFunction( overwritten ) ) {
10533 overwritten( responseContainer[ 0 ] );
10534 }
10535
10536 responseContainer = overwritten = undefined;
10537 } );
10538
10539 // Delegate to script
10540 return "script";
10541 }
10542} );
10543
10544
10545
10546
10547// data: string of html
10548// context (optional): If specified, the fragment will be created in this context,
10549// defaults to document
10550// keepScripts (optional): If true, will include scripts passed in the html string
10551jQuery.parseHTML = function( data, context, keepScripts ) {
10552 if ( !data || typeof data !== "string" ) {
10553 return null;
10554 }
10555 if ( typeof context === "boolean" ) {
10556 keepScripts = context;
10557 context = false;
10558 }
10559 context = context || document;
10560
10561 var parsed = rsingleTag.exec( data ),
10562 scripts = !keepScripts && [];
10563
10564 // Single tag
10565 if ( parsed ) {
10566 return [ context.createElement( parsed[ 1 ] ) ];
10567 }
10568
10569 parsed = buildFragment( [ data ], context, scripts );
10570
10571 if ( scripts && scripts.length ) {
10572 jQuery( scripts ).remove();
10573 }
10574
10575 return jQuery.merge( [], parsed.childNodes );
10576};
10577
10578
10579// Keep a copy of the old load method
10580var _load = jQuery.fn.load;
10581
10582/**
10583 * Load a url into a page
10584 */
10585jQuery.fn.load = function( url, params, callback ) {
10586 if ( typeof url !== "string" && _load ) {
10587 return _load.apply( this, arguments );
10588 }
10589
10590 var selector, type, response,
10591 self = this,
10592 off = url.indexOf( " " );
10593
10594 if ( off > -1 ) {
10595 selector = jQuery.trim( url.slice( off, url.length ) );
10596 url = url.slice( 0, off );
10597 }
10598
10599 // If it's a function
10600 if ( jQuery.isFunction( params ) ) {
10601
10602 // We assume that it's the callback
10603 callback = params;
10604 params = undefined;
10605
10606 // Otherwise, build a param string
10607 } else if ( params && typeof params === "object" ) {
10608 type = "POST";
10609 }
10610
10611 // If we have elements to modify, make the request
10612 if ( self.length > 0 ) {
10613 jQuery.ajax( {
10614 url: url,
10615
10616 // If "type" variable is undefined, then "GET" method will be used.
10617 // Make value of this field explicit since
10618 // user can override it through ajaxSetup method
10619 type: type || "GET",
10620 dataType: "html",
10621 data: params
10622 } ).done( function( responseText ) {
10623
10624 // Save response for use in complete callback
10625 response = arguments;
10626
10627 self.html( selector ?
10628
10629 // If a selector was specified, locate the right elements in a dummy div
10630 // Exclude scripts to avoid IE 'Permission Denied' errors
10631 jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
10632
10633 // Otherwise use the full result
10634 responseText );
10635
10636 // If the request succeeds, this function gets "data", "status", "jqXHR"
10637 // but they are ignored because response was set above.
10638 // If it fails, this function gets "jqXHR", "status", "error"
10639 } ).always( callback && function( jqXHR, status ) {
10640 self.each( function() {
10641 callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
10642 } );
10643 } );
10644 }
10645
10646 return this;
10647};
10648
10649
10650
10651
10652// Attach a bunch of functions for handling common AJAX events
10653jQuery.each( [
10654 "ajaxStart",
10655 "ajaxStop",
10656 "ajaxComplete",
10657 "ajaxError",
10658 "ajaxSuccess",
10659 "ajaxSend"
10660], function( i, type ) {
10661 jQuery.fn[ type ] = function( fn ) {
10662 return this.on( type, fn );
10663 };
10664} );
10665
10666
10667
10668
10669jQuery.expr.filters.animated = function( elem ) {
10670 return jQuery.grep( jQuery.timers, function( fn ) {
10671 return elem === fn.elem;
10672 } ).length;
10673};
10674
10675
10676
10677
10678
10679/**
10680 * Gets a window from an element
10681 */
10682function getWindow( elem ) {
10683 return jQuery.isWindow( elem ) ?
10684 elem :
10685 elem.nodeType === 9 ?
10686 elem.defaultView || elem.parentWindow :
10687 false;
10688}
10689
10690jQuery.offset = {
10691 setOffset: function( elem, options, i ) {
10692 var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
10693 position = jQuery.css( elem, "position" ),
10694 curElem = jQuery( elem ),
10695 props = {};
10696
10697 // set position first, in-case top/left are set even on static elem
10698 if ( position === "static" ) {
10699 elem.style.position = "relative";
10700 }
10701
10702 curOffset = curElem.offset();
10703 curCSSTop = jQuery.css( elem, "top" );
10704 curCSSLeft = jQuery.css( elem, "left" );
10705 calculatePosition = ( position === "absolute" || position === "fixed" ) &&
10706 jQuery.inArray( "auto", [ curCSSTop, curCSSLeft ] ) > -1;
10707
10708 // need to be able to calculate position if either top or left
10709 // is auto and position is either absolute or fixed
10710 if ( calculatePosition ) {
10711 curPosition = curElem.position();
10712 curTop = curPosition.top;
10713 curLeft = curPosition.left;
10714 } else {
10715 curTop = parseFloat( curCSSTop ) || 0;
10716 curLeft = parseFloat( curCSSLeft ) || 0;
10717 }
10718
10719 if ( jQuery.isFunction( options ) ) {
10720
10721 // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
10722 options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
10723 }
10724
10725 if ( options.top != null ) {
10726 props.top = ( options.top - curOffset.top ) + curTop;
10727 }
10728 if ( options.left != null ) {
10729 props.left = ( options.left - curOffset.left ) + curLeft;
10730 }
10731
10732 if ( "using" in options ) {
10733 options.using.call( elem, props );
10734 } else {
10735 curElem.css( props );
10736 }
10737 }
10738};
10739
10740jQuery.fn.extend( {
10741 offset: function( options ) {
10742 if ( arguments.length ) {
10743 return options === undefined ?
10744 this :
10745 this.each( function( i ) {
10746 jQuery.offset.setOffset( this, options, i );
10747 } );
10748 }
10749
10750 var docElem, win,
10751 box = { top: 0, left: 0 },
10752 elem = this[ 0 ],
10753 doc = elem && elem.ownerDocument;
10754
10755 if ( !doc ) {
10756 return;
10757 }
10758
10759 docElem = doc.documentElement;
10760
10761 // Make sure it's not a disconnected DOM node
10762 if ( !jQuery.contains( docElem, elem ) ) {
10763 return box;
10764 }
10765
10766 // If we don't have gBCR, just use 0,0 rather than error
10767 // BlackBerry 5, iOS 3 (original iPhone)
10768 if ( typeof elem.getBoundingClientRect !== "undefined" ) {
10769 box = elem.getBoundingClientRect();
10770 }
10771 win = getWindow( doc );
10772 return {
10773 top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
10774 left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
10775 };
10776 },
10777
10778 position: function() {
10779 if ( !this[ 0 ] ) {
10780 return;
10781 }
10782
10783 var offsetParent, offset,
10784 parentOffset = { top: 0, left: 0 },
10785 elem = this[ 0 ];
10786
10787 // Fixed elements are offset from window (parentOffset = {top:0, left: 0},
10788 // because it is its only offset parent
10789 if ( jQuery.css( elem, "position" ) === "fixed" ) {
10790
10791 // we assume that getBoundingClientRect is available when computed position is fixed
10792 offset = elem.getBoundingClientRect();
10793 } else {
10794
10795 // Get *real* offsetParent
10796 offsetParent = this.offsetParent();
10797
10798 // Get correct offsets
10799 offset = this.offset();
10800 if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
10801 parentOffset = offsetParent.offset();
10802 }
10803
10804 // Add offsetParent borders
10805 parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
10806 parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
10807 }
10808
10809 // Subtract parent offsets and element margins
10810 // note: when an element has margin: auto the offsetLeft and marginLeft
10811 // are the same in Safari causing offset.left to incorrectly be 0
10812 return {
10813 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
10814 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
10815 };
10816 },
10817
10818 offsetParent: function() {
10819 return this.map( function() {
10820 var offsetParent = this.offsetParent;
10821
10822 while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) &&
10823 jQuery.css( offsetParent, "position" ) === "static" ) ) {
10824 offsetParent = offsetParent.offsetParent;
10825 }
10826 return offsetParent || documentElement;
10827 } );
10828 }
10829} );
10830
10831// Create scrollLeft and scrollTop methods
10832jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
10833 var top = /Y/.test( prop );
10834
10835 jQuery.fn[ method ] = function( val ) {
10836 return access( this, function( elem, method, val ) {
10837 var win = getWindow( elem );
10838
10839 if ( val === undefined ) {
10840 return win ? ( prop in win ) ? win[ prop ] :
10841 win.document.documentElement[ method ] :
10842 elem[ method ];
10843 }
10844
10845 if ( win ) {
10846 win.scrollTo(
10847 !top ? val : jQuery( win ).scrollLeft(),
10848 top ? val : jQuery( win ).scrollTop()
10849 );
10850
10851 } else {
10852 elem[ method ] = val;
10853 }
10854 }, method, val, arguments.length, null );
10855 };
10856} );
10857
10858// Support: Safari<7-8+, Chrome<37-44+
10859// Add the top/left cssHooks using jQuery.fn.position
10860// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
10861// getComputedStyle returns percent when specified for top/left/bottom/right
10862// rather than make the css module depend on the offset module, we just check for it here
10863jQuery.each( [ "top", "left" ], function( i, prop ) {
10864 jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
10865 function( elem, computed ) {
10866 if ( computed ) {
10867 computed = curCSS( elem, prop );
10868
10869 // if curCSS returns percentage, fallback to offset
10870 return rnumnonpx.test( computed ) ?
10871 jQuery( elem ).position()[ prop ] + "px" :
10872 computed;
10873 }
10874 }
10875 );
10876} );
10877
10878
10879// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
10880jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
10881 jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
10882 function( defaultExtra, funcName ) {
10883
10884 // margin is only for outerHeight, outerWidth
10885 jQuery.fn[ funcName ] = function( margin, value ) {
10886 var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
10887 extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
10888
10889 return access( this, function( elem, type, value ) {
10890 var doc;
10891
10892 if ( jQuery.isWindow( elem ) ) {
10893
10894 // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
10895 // isn't a whole lot we can do. See pull request at this URL for discussion:
10896 // https://github.com/jquery/jquery/pull/764
10897 return elem.document.documentElement[ "client" + name ];
10898 }
10899
10900 // Get document width or height
10901 if ( elem.nodeType === 9 ) {
10902 doc = elem.documentElement;
10903
10904 // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
10905 // whichever is greatest
10906 // unfortunately, this causes bug #3838 in IE6/8 only,
10907 // but there is currently no good, small way to fix it.
10908 return Math.max(
10909 elem.body[ "scroll" + name ], doc[ "scroll" + name ],
10910 elem.body[ "offset" + name ], doc[ "offset" + name ],
10911 doc[ "client" + name ]
10912 );
10913 }
10914
10915 return value === undefined ?
10916
10917 // Get width or height on the element, requesting but not forcing parseFloat
10918 jQuery.css( elem, type, extra ) :
10919
10920 // Set width or height on the element
10921 jQuery.style( elem, type, value, extra );
10922 }, type, chainable ? margin : undefined, chainable, null );
10923 };
10924 } );
10925} );
10926
10927
10928jQuery.fn.extend( {
10929
10930 bind: function( types, data, fn ) {
10931 return this.on( types, null, data, fn );
10932 },
10933 unbind: function( types, fn ) {
10934 return this.off( types, null, fn );
10935 },
10936
10937 delegate: function( selector, types, data, fn ) {
10938 return this.on( types, selector, data, fn );
10939 },
10940 undelegate: function( selector, types, fn ) {
10941
10942 // ( namespace ) or ( selector, types [, fn] )
10943 return arguments.length === 1 ?
10944 this.off( selector, "**" ) :
10945 this.off( types, selector || "**", fn );
10946 }
10947} );
10948
10949// The number of elements contained in the matched element set
10950jQuery.fn.size = function() {
10951 return this.length;
10952};
10953
10954jQuery.fn.andSelf = jQuery.fn.addBack;
10955
10956
10957
10958
10959// Register as a named AMD module, since jQuery can be concatenated with other
10960// files that may use define, but not via a proper concatenation script that
10961// understands anonymous AMD modules. A named AMD is safest and most robust
10962// way to register. Lowercase jquery is used because AMD module names are
10963// derived from file names, and jQuery is normally delivered in a lowercase
10964// file name. Do this after creating the global so that if an AMD module wants
10965// to call noConflict to hide this version of jQuery, it will work.
10966
10967// Note that for maximum portability, libraries that are not jQuery should
10968// declare themselves as anonymous modules, and avoid setting a global if an
10969// AMD loader is present. jQuery is a special case. For more information, see
10970// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
10971
10972if ( typeof define === "function" && define.amd ) {
10973 define( "jquery", [], function() {
10974 return jQuery;
10975 } );
10976}
10977
10978
10979
10980var
10981
10982 // Map over jQuery in case of overwrite
10983 _jQuery = window.jQuery,
10984
10985 // Map over the $ in case of overwrite
10986 _$ = window.$;
10987
10988jQuery.noConflict = function( deep ) {
10989 if ( window.$ === jQuery ) {
10990 window.$ = _$;
10991 }
10992
10993 if ( deep && window.jQuery === jQuery ) {
10994 window.jQuery = _jQuery;
10995 }
10996
10997 return jQuery;
10998};
10999
11000// Expose jQuery and $ identifiers, even in
11001// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
11002// and CommonJS for browser emulators (#13566)
11003if ( !noGlobal ) {
11004 window.jQuery = window.$ = jQuery;
11005}
11006
11007return jQuery;
11008}));
11009/* jshint node: true */
11010
11011/**
11012 * Unobtrusive scripting adapter for jQuery
11013 * https://github.com/rails/jquery-ujs
11014 *
11015 * Requires jQuery 1.8.0 or later.
11016 *
11017 * Released under the MIT license
11018 *
11019 */
11020
11021(function() {
11022 'use strict';
11023
11024 var jqueryUjsInit = function($, undefined) {
11025
11026 // Cut down on the number of issues from people inadvertently including jquery_ujs twice
11027 // by detecting and raising an error when it happens.
11028 if ( $.rails !== undefined ) {
11029 $.error('jquery-ujs has already been loaded!');
11030 }
11031
11032 // Shorthand to make it a little easier to call public rails functions from within rails.js
11033 var rails;
11034 var $document = $(document);
11035
11036 $.rails = rails = {
11037 // Link elements bound by jquery-ujs
11038 linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote]:not([disabled]), a[data-disable-with], a[data-disable]',
11039
11040 // Button elements bound by jquery-ujs
11041 buttonClickSelector: 'button[data-remote]:not([form]):not(form button), button[data-confirm]:not([form]):not(form button)',
11042
11043 // Select elements bound by jquery-ujs
11044 inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]',
11045
11046 // Form elements bound by jquery-ujs
11047 formSubmitSelector: 'form:not([data-turbo=true])',
11048
11049 // Form input elements bound by jquery-ujs
11050 formInputClickSelector: 'form:not([data-turbo=true]) input[type=submit], form:not([data-turbo=true]) input[type=image], form:not([data-turbo=true]) button[type=submit], form:not([data-turbo=true]) button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])',
11051
11052 // Form input elements disabled during form submission
11053 disableSelector: 'input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled',
11054
11055 // Form input elements re-enabled after form submission
11056 enableSelector: 'input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled',
11057
11058 // Form required input elements
11059 requiredInputSelector: 'input[name][required]:not([disabled]), textarea[name][required]:not([disabled])',
11060
11061 // Form file input elements
11062 fileInputSelector: 'input[name][type=file]:not([disabled])',
11063
11064 // Link onClick disable selector with possible reenable after remote submission
11065 linkDisableSelector: 'a[data-disable-with], a[data-disable]',
11066
11067 // Button onClick disable selector with possible reenable after remote submission
11068 buttonDisableSelector: 'button[data-remote][data-disable-with], button[data-remote][data-disable]',
11069
11070 // Up-to-date Cross-Site Request Forgery token
11071 csrfToken: function() {
11072 return $('meta[name=csrf-token]').attr('content');
11073 },
11074
11075 // URL param that must contain the CSRF token
11076 csrfParam: function() {
11077 return $('meta[name=csrf-param]').attr('content');
11078 },
11079
11080 // Make sure that every Ajax request sends the CSRF token
11081 CSRFProtection: function(xhr) {
11082 var token = rails.csrfToken();
11083 if (token) xhr.setRequestHeader('X-CSRF-Token', token);
11084 },
11085
11086 // Make sure that all forms have actual up-to-date tokens (cached forms contain old ones)
11087 refreshCSRFTokens: function(){
11088 $('form input[name="' + rails.csrfParam() + '"]').val(rails.csrfToken());
11089 },
11090
11091 // Triggers an event on an element and returns false if the event result is false
11092 fire: function(obj, name, data) {
11093 var event = $.Event(name);
11094 obj.trigger(event, data);
11095 return event.result !== false;
11096 },
11097
11098 // Default confirm dialog, may be overridden with custom confirm dialog in $.rails.confirm
11099 confirm: function(message) {
11100 return confirm(message);
11101 },
11102
11103 // Default ajax function, may be overridden with custom function in $.rails.ajax
11104 ajax: function(options) {
11105 return $.ajax(options);
11106 },
11107
11108 // Default way to get an element's href. May be overridden at $.rails.href.
11109 href: function(element) {
11110 return element[0].href;
11111 },
11112
11113 // Checks "data-remote" if true to handle the request through a XHR request.
11114 isRemote: function(element) {
11115 return element.data('remote') !== undefined && element.data('remote') !== false;
11116 },
11117
11118 // Submits "remote" forms and links with ajax
11119 handleRemote: function(element) {
11120 var method, url, data, withCredentials, dataType, options;
11121
11122 if (rails.fire(element, 'ajax:before')) {
11123 withCredentials = element.data('with-credentials') || null;
11124 dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType);
11125
11126 if (element.is('form')) {
11127 method = element.data('ujs:submit-button-formmethod') || element.attr('method');
11128 url = element.data('ujs:submit-button-formaction') || element.attr('action');
11129 data = $(element[0]).serializeArray();
11130 // memoized value from clicked submit button
11131 var button = element.data('ujs:submit-button');
11132 if (button) {
11133 data.push(button);
11134 element.data('ujs:submit-button', null);
11135 }
11136 element.data('ujs:submit-button-formmethod', null);
11137 element.data('ujs:submit-button-formaction', null);
11138 } else if (element.is(rails.inputChangeSelector)) {
11139 method = element.data('method');
11140 url = element.data('url');
11141 data = element.serialize();
11142 if (element.data('params')) data = data + '&' + element.data('params');
11143 } else if (element.is(rails.buttonClickSelector)) {
11144 method = element.data('method') || 'get';
11145 url = element.data('url');
11146 data = element.serialize();
11147 if (element.data('params')) data = data + '&' + element.data('params');
11148 } else {
11149 method = element.data('method');
11150 url = rails.href(element);
11151 data = element.data('params') || null;
11152 }
11153
11154 options = {
11155 type: method || 'GET', data: data, dataType: dataType,
11156 // stopping the "ajax:beforeSend" event will cancel the ajax request
11157 beforeSend: function(xhr, settings) {
11158 if (settings.dataType === undefined) {
11159 xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script);
11160 }
11161 if (rails.fire(element, 'ajax:beforeSend', [xhr, settings])) {
11162 element.trigger('ajax:send', xhr);
11163 } else {
11164 return false;
11165 }
11166 },
11167 success: function(data, status, xhr) {
11168 element.trigger('ajax:success', [data, status, xhr]);
11169 },
11170 complete: function(xhr, status) {
11171 element.trigger('ajax:complete', [xhr, status]);
11172 },
11173 error: function(xhr, status, error) {
11174 element.trigger('ajax:error', [xhr, status, error]);
11175 },
11176 crossDomain: rails.isCrossDomain(url)
11177 };
11178
11179 // There is no withCredentials for IE6-8 when
11180 // "Enable native XMLHTTP support" is disabled
11181 if (withCredentials) {
11182 options.xhrFields = {
11183 withCredentials: withCredentials
11184 };
11185 }
11186
11187 // Only pass url to `ajax` options if not blank
11188 if (url) { options.url = url; }
11189
11190 return rails.ajax(options);
11191 } else {
11192 return false;
11193 }
11194 },
11195
11196 // Determines if the request is a cross domain request.
11197 isCrossDomain: function(url) {
11198 var originAnchor = document.createElement('a');
11199 originAnchor.href = location.href;
11200 var urlAnchor = document.createElement('a');
11201
11202 try {
11203 urlAnchor.href = url;
11204 // This is a workaround to a IE bug.
11205 urlAnchor.href = urlAnchor.href;
11206
11207 // If URL protocol is false or is a string containing a single colon
11208 // *and* host are false, assume it is not a cross-domain request
11209 // (should only be the case for IE7 and IE compatibility mode).
11210 // Otherwise, evaluate protocol and host of the URL against the origin
11211 // protocol and host.
11212 return !(((!urlAnchor.protocol || urlAnchor.protocol === ':') && !urlAnchor.host) ||
11213 (originAnchor.protocol + '//' + originAnchor.host ===
11214 urlAnchor.protocol + '//' + urlAnchor.host));
11215 } catch (e) {
11216 // If there is an error parsing the URL, assume it is crossDomain.
11217 return true;
11218 }
11219 },
11220
11221 // Handles "data-method" on links such as:
11222 // <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>
11223 handleMethod: function(link) {
11224 var href = rails.href(link),
11225 method = link.data('method'),
11226 target = link.attr('target'),
11227 csrfToken = rails.csrfToken(),
11228 csrfParam = rails.csrfParam(),
11229 form = $('<form method="post" action="' + href + '"></form>'),
11230 metadataInput = '<input name="_method" value="' + method + '" type="hidden" />';
11231
11232 if (csrfParam !== undefined && csrfToken !== undefined && !rails.isCrossDomain(href)) {
11233 metadataInput += '<input name="' + csrfParam + '" value="' + csrfToken + '" type="hidden" />';
11234 }
11235
11236 if (target) { form.attr('target', target); }
11237
11238 form.hide().append(metadataInput).appendTo('body');
11239 form.submit();
11240 },
11241
11242 // Helper function that returns form elements that match the specified CSS selector
11243 // If form is actually a "form" element this will return associated elements outside the from that have
11244 // the html form attribute set
11245 formElements: function(form, selector) {
11246 return form.is('form') ? $(form[0].elements).filter(selector) : form.find(selector);
11247 },
11248
11249 /* Disables form elements:
11250 - Caches element value in 'ujs:enable-with' data store
11251 - Replaces element text with value of 'data-disable-with' attribute
11252 - Sets disabled property to true
11253 */
11254 disableFormElements: function(form) {
11255 rails.formElements(form, rails.disableSelector).each(function() {
11256 rails.disableFormElement($(this));
11257 });
11258 },
11259
11260 disableFormElement: function(element) {
11261 var method, replacement;
11262
11263 method = element.is('button') ? 'html' : 'val';
11264 replacement = element.data('disable-with');
11265
11266 if (replacement !== undefined) {
11267 element.data('ujs:enable-with', element[method]());
11268 element[method](replacement);
11269 }
11270
11271 element.prop('disabled', true);
11272 element.data('ujs:disabled', true);
11273 },
11274
11275 /* Re-enables disabled form elements:
11276 - Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
11277 - Sets disabled property to false
11278 */
11279 enableFormElements: function(form) {
11280 rails.formElements(form, rails.enableSelector).each(function() {
11281 rails.enableFormElement($(this));
11282 });
11283 },
11284
11285 enableFormElement: function(element) {
11286 var method = element.is('button') ? 'html' : 'val';
11287 if (element.data('ujs:enable-with') !== undefined) {
11288 element[method](element.data('ujs:enable-with'));
11289 element.removeData('ujs:enable-with'); // clean up cache
11290 }
11291 element.prop('disabled', false);
11292 element.removeData('ujs:disabled');
11293 },
11294
11295 /* For 'data-confirm' attribute:
11296 - Fires `confirm` event
11297 - Shows the confirmation dialog
11298 - Fires the `confirm:complete` event
11299
11300 Returns `true` if no function stops the chain and user chose yes; `false` otherwise.
11301 Attaching a handler to the element's `confirm` event that returns a `falsy` value cancels the confirmation dialog.
11302 Attaching a handler to the element's `confirm:complete` event that returns a `falsy` value makes this function
11303 return false. The `confirm:complete` event is fired whether or not the user answered true or false to the dialog.
11304 */
11305 allowAction: function(element) {
11306 var message = element.data('confirm'),
11307 answer = false, callback;
11308 if (!message) { return true; }
11309
11310 if (rails.fire(element, 'confirm')) {
11311 try {
11312 answer = rails.confirm(message);
11313 } catch (e) {
11314 (console.error || console.log).call(console, e.stack || e);
11315 }
11316 callback = rails.fire(element, 'confirm:complete', [answer]);
11317 }
11318 return answer && callback;
11319 },
11320
11321 // Helper function which checks for blank inputs in a form that match the specified CSS selector
11322 blankInputs: function(form, specifiedSelector, nonBlank) {
11323 var foundInputs = $(),
11324 input,
11325 valueToCheck,
11326 radiosForNameWithNoneSelected,
11327 radioName,
11328 selector = specifiedSelector || 'input,textarea',
11329 requiredInputs = form.find(selector),
11330 checkedRadioButtonNames = {};
11331
11332 requiredInputs.each(function() {
11333 input = $(this);
11334 if (input.is('input[type=radio]')) {
11335
11336 // Don't count unchecked required radio as blank if other radio with same name is checked,
11337 // regardless of whether same-name radio input has required attribute or not. The spec
11338 // states https://www.w3.org/TR/html5/forms.html#the-required-attribute
11339 radioName = input.attr('name');
11340
11341 // Skip if we've already seen the radio with this name.
11342 if (!checkedRadioButtonNames[radioName]) {
11343
11344 // If none checked
11345 if (form.find('input[type=radio]:checked[name="' + radioName + '"]').length === 0) {
11346 radiosForNameWithNoneSelected = form.find(
11347 'input[type=radio][name="' + radioName + '"]');
11348 foundInputs = foundInputs.add(radiosForNameWithNoneSelected);
11349 }
11350
11351 // We only need to check each name once.
11352 checkedRadioButtonNames[radioName] = radioName;
11353 }
11354 } else {
11355 valueToCheck = input.is('input[type=checkbox],input[type=radio]') ? input.is(':checked') : !!input.val();
11356 if (valueToCheck === nonBlank) {
11357 foundInputs = foundInputs.add(input);
11358 }
11359 }
11360 });
11361 return foundInputs.length ? foundInputs : false;
11362 },
11363
11364 // Helper function which checks for non-blank inputs in a form that match the specified CSS selector
11365 nonBlankInputs: function(form, specifiedSelector) {
11366 return rails.blankInputs(form, specifiedSelector, true); // true specifies nonBlank
11367 },
11368
11369 // Helper function, needed to provide consistent behavior in IE
11370 stopEverything: function(e) {
11371 $(e.target).trigger('ujs:everythingStopped');
11372 e.stopImmediatePropagation();
11373 return false;
11374 },
11375
11376 // Replace element's html with the 'data-disable-with' after storing original html
11377 // and prevent clicking on it
11378 disableElement: function(element) {
11379 var replacement = element.data('disable-with');
11380
11381 if (replacement !== undefined) {
11382 element.data('ujs:enable-with', element.html()); // store enabled state
11383 element.html(replacement);
11384 }
11385
11386 element.on('click.railsDisable', function(e) { // prevent further clicking
11387 return rails.stopEverything(e);
11388 });
11389 element.data('ujs:disabled', true);
11390 },
11391
11392 // Restore element to its original state which was disabled by 'disableElement' above
11393 enableElement: function(element) {
11394 if (element.data('ujs:enable-with') !== undefined) {
11395 element.html(element.data('ujs:enable-with')); // set to old enabled state
11396 element.removeData('ujs:enable-with'); // clean up cache
11397 }
11398 element.off('click.railsDisable'); // enable element
11399 element.removeData('ujs:disabled');
11400 }
11401 };
11402
11403 if (rails.fire($document, 'rails:attachBindings')) {
11404
11405 $.ajaxPrefilter(function(options, originalOptions, xhr){ if ( !options.crossDomain ) { rails.CSRFProtection(xhr); }});
11406
11407 // This event works the same as the load event, except that it fires every
11408 // time the page is loaded.
11409 //
11410 // See https://github.com/rails/jquery-ujs/issues/357
11411 // See https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching
11412 $(window).on('pageshow.rails', function () {
11413 $($.rails.enableSelector).each(function () {
11414 var element = $(this);
11415
11416 if (element.data('ujs:disabled')) {
11417 $.rails.enableFormElement(element);
11418 }
11419 });
11420
11421 $($.rails.linkDisableSelector).each(function () {
11422 var element = $(this);
11423
11424 if (element.data('ujs:disabled')) {
11425 $.rails.enableElement(element);
11426 }
11427 });
11428 });
11429
11430 $document.on('ajax:complete', rails.linkDisableSelector, function() {
11431 rails.enableElement($(this));
11432 });
11433
11434 $document.on('ajax:complete', rails.buttonDisableSelector, function() {
11435 rails.enableFormElement($(this));
11436 });
11437
11438 $document.on('click.rails', rails.linkClickSelector, function(e) {
11439 var link = $(this), method = link.data('method'), data = link.data('params'), metaClick = e.metaKey || e.ctrlKey;
11440 if (!rails.allowAction(link)) return rails.stopEverything(e);
11441
11442 if (!metaClick && link.is(rails.linkDisableSelector)) rails.disableElement(link);
11443
11444 if (rails.isRemote(link)) {
11445 if (metaClick && (!method || method === 'GET') && !data) { return true; }
11446
11447 var handleRemote = rails.handleRemote(link);
11448 // Response from rails.handleRemote() will either be false or a deferred object promise.
11449 if (handleRemote === false) {
11450 rails.enableElement(link);
11451 } else {
11452 handleRemote.fail( function() { rails.enableElement(link); } );
11453 }
11454 return false;
11455
11456 } else if (method) {
11457 rails.handleMethod(link);
11458 return false;
11459 }
11460 });
11461
11462 $document.on('click.rails', rails.buttonClickSelector, function(e) {
11463 var button = $(this);
11464
11465 if (!rails.allowAction(button) || !rails.isRemote(button)) return rails.stopEverything(e);
11466
11467 if (button.is(rails.buttonDisableSelector)) rails.disableFormElement(button);
11468
11469 var handleRemote = rails.handleRemote(button);
11470 // Response from rails.handleRemote() will either be false or a deferred object promise.
11471 if (handleRemote === false) {
11472 rails.enableFormElement(button);
11473 } else {
11474 handleRemote.fail( function() { rails.enableFormElement(button); } );
11475 }
11476 return false;
11477 });
11478
11479 $document.on('change.rails', rails.inputChangeSelector, function(e) {
11480 var link = $(this);
11481 if (!rails.allowAction(link) || !rails.isRemote(link)) return rails.stopEverything(e);
11482
11483 rails.handleRemote(link);
11484 return false;
11485 });
11486
11487 $document.on('submit.rails', rails.formSubmitSelector, function(e) {
11488 var form = $(this),
11489 remote = rails.isRemote(form),
11490 blankRequiredInputs,
11491 nonBlankFileInputs;
11492
11493 if (!rails.allowAction(form)) return rails.stopEverything(e);
11494
11495 // Skip other logic when required values are missing or file upload is present
11496 if (form.attr('novalidate') === undefined) {
11497 if (form.data('ujs:formnovalidate-button') === undefined) {
11498 blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector, false);
11499 if (blankRequiredInputs && rails.fire(form, 'ajax:aborted:required', [blankRequiredInputs])) {
11500 return rails.stopEverything(e);
11501 }
11502 } else {
11503 // Clear the formnovalidate in case the next button click is not on a formnovalidate button
11504 // Not strictly necessary to do here, since it is also reset on each button click, but just to be certain
11505 form.data('ujs:formnovalidate-button', undefined);
11506 }
11507 }
11508
11509 if (remote) {
11510 nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector);
11511 if (nonBlankFileInputs) {
11512 // Slight timeout so that the submit button gets properly serialized
11513 // (make it easy for event handler to serialize form without disabled values)
11514 setTimeout(function(){ rails.disableFormElements(form); }, 13);
11515 var aborted = rails.fire(form, 'ajax:aborted:file', [nonBlankFileInputs]);
11516
11517 // Re-enable form elements if event bindings return false (canceling normal form submission)
11518 if (!aborted) { setTimeout(function(){ rails.enableFormElements(form); }, 13); }
11519
11520 return aborted;
11521 }
11522
11523 rails.handleRemote(form);
11524 return false;
11525
11526 } else {
11527 // Slight timeout so that the submit button gets properly serialized
11528 setTimeout(function(){ rails.disableFormElements(form); }, 13);
11529 }
11530 });
11531
11532 $document.on('click.rails', rails.formInputClickSelector, function(event) {
11533 var button = $(this);
11534
11535 if (!rails.allowAction(button)) return rails.stopEverything(event);
11536
11537 // Register the pressed submit button
11538 var name = button.attr('name'),
11539 data = name ? {name:name, value:button.val()} : null;
11540
11541 var form = button.closest('form');
11542 if (form.length === 0) {
11543 form = $('#' + button.attr('form'));
11544 }
11545 form.data('ujs:submit-button', data);
11546
11547 // Save attributes from button
11548 form.data('ujs:formnovalidate-button', button.attr('formnovalidate'));
11549 form.data('ujs:submit-button-formaction', button.attr('formaction'));
11550 form.data('ujs:submit-button-formmethod', button.attr('formmethod'));
11551 });
11552
11553 $document.on('ajax:send.rails', rails.formSubmitSelector, function(event) {
11554 if (this === event.target) rails.disableFormElements($(this));
11555 });
11556
11557 $document.on('ajax:complete.rails', rails.formSubmitSelector, function(event) {
11558 if (this === event.target) rails.enableFormElements($(this));
11559 });
11560
11561 $(function(){
11562 rails.refreshCSRFTokens();
11563 });
11564 }
11565
11566 };
11567
11568 if (window.jQuery) {
11569 jqueryUjsInit(jQuery);
11570 } else if (typeof exports === 'object' && typeof module === 'object') {
11571 module.exports = jqueryUjsInit;
11572 }
11573})();
11574( function( factory ) {
11575 "use strict";
11576
11577 if ( typeof define === "function" && define.amd ) {
11578
11579 // AMD. Register as an anonymous module.
11580 define( [ "jquery" ], factory );
11581 } else {
11582
11583 // Browser globals
11584 factory( jQuery );
11585 }
11586} )( function( $ ) {
11587"use strict";
11588
11589$.ui = $.ui || {};
11590
11591return $.ui.version = "1.14.1";
11592
11593} );
11594
11595
11596/*!
11597 * jQuery UI :data 1.14.1
11598 * https://jqueryui.com
11599 *
11600 * Copyright OpenJS Foundation and other contributors
11601 * Released under the MIT license.
11602 * https://jquery.org/license
11603 */
11604
11605//>>label: :data Selector
11606//>>group: Core
11607//>>description: Selects elements which have data stored under the specified key.
11608//>>docs: https://api.jqueryui.com/data-selector/
11609
11610( function( factory ) {
11611 "use strict";
11612
11613 if ( typeof define === "function" && define.amd ) {
11614
11615 // AMD. Register as an anonymous module.
11616 define( [ "jquery", "./version" ], factory );
11617 } else {
11618
11619 // Browser globals
11620 factory( jQuery );
11621 }
11622} )( function( $ ) {
11623"use strict";
11624
11625return $.extend( $.expr.pseudos, {
11626 data: $.expr.createPseudo( function( dataName ) {
11627 return function( elem ) {
11628 return !!$.data( elem, dataName );
11629 };
11630 } )
11631} );
11632} );
11633
11634
11635/*!
11636 * jQuery UI Disable Selection 1.14.1
11637 * https://jqueryui.com
11638 *
11639 * Copyright OpenJS Foundation and other contributors
11640 * Released under the MIT license.
11641 * https://jquery.org/license
11642 */
11643
11644//>>label: disableSelection
11645//>>group: Core
11646//>>description: Disable selection of text content within the set of matched elements.
11647//>>docs: https://api.jqueryui.com/disableSelection/
11648
11649// This file is deprecated
11650( function( factory ) {
11651 "use strict";
11652
11653 if ( typeof define === "function" && define.amd ) {
11654
11655 // AMD. Register as an anonymous module.
11656 define( [ "jquery", "./version" ], factory );
11657 } else {
11658
11659 // Browser globals
11660 factory( jQuery );
11661 }
11662} )( function( $ ) {
11663"use strict";
11664
11665return $.fn.extend( {
11666 disableSelection: ( function() {
11667 var eventType = "onselectstart" in document.createElement( "div" ) ?
11668 "selectstart" :
11669 "mousedown";
11670
11671 return function() {
11672 return this.on( eventType + ".ui-disableSelection", function( event ) {
11673 event.preventDefault();
11674 } );
11675 };
11676 } )(),
11677
11678 enableSelection: function() {
11679 return this.off( ".ui-disableSelection" );
11680 }
11681} );
11682
11683} );
11684
11685( function( factory ) {
11686 "use strict";
11687
11688 if ( typeof define === "function" && define.amd ) {
11689
11690 // AMD. Register as an anonymous module.
11691 define( [ "jquery", "./version" ], factory );
11692 } else {
11693
11694 // Browser globals
11695 factory( jQuery );
11696 }
11697} )( function( $ ) {
11698 "use strict";
11699
11700// Create a local jQuery because jQuery Color relies on it and the
11701// global may not exist with AMD and a custom build (#10199).
11702// This module is a noop if used as a regular AMD module.
11703// eslint-disable-next-line no-unused-vars
11704var jQuery = $;
11705
11706} );
11707/*!
11708 * jQuery Color Animations v3.0.0
11709 * https://github.com/jquery/jquery-color
11710 *
11711 * Copyright OpenJS Foundation and other contributors
11712 * Released under the MIT license.
11713 * https://jquery.org/license
11714 *
11715 * Date: Wed May 15 16:49:44 2024 +0200
11716 */
11717
11718( function( root, factory ) {
11719 "use strict";
11720
11721 if ( typeof define === "function" && define.amd ) {
11722
11723 // AMD. Register as an anonymous module.
11724 define( [ "jquery" ], factory );
11725 } else if ( typeof exports === "object" ) {
11726 module.exports = factory( require( "jquery" ) );
11727 } else {
11728 factory( root.jQuery );
11729 }
11730} )( this, function( jQuery, undefined ) {
11731 "use strict";
11732
11733 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " +
11734 "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
11735
11736 class2type = {},
11737 toString = class2type.toString,
11738
11739 // plusequals test for += 100 -= 100
11740 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
11741
11742 // a set of RE's that can match strings and generate color tuples.
11743 stringParsers = [ {
11744 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
11745 parse: function( execResult ) {
11746 return [
11747 execResult[ 1 ],
11748 execResult[ 2 ],
11749 execResult[ 3 ],
11750 execResult[ 4 ]
11751 ];
11752 }
11753 }, {
11754 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
11755 parse: function( execResult ) {
11756 return [
11757 execResult[ 1 ] * 2.55,
11758 execResult[ 2 ] * 2.55,
11759 execResult[ 3 ] * 2.55,
11760 execResult[ 4 ]
11761 ];
11762 }
11763 }, {
11764
11765 // this regex ignores A-F because it's compared against an already lowercased string
11766 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/,
11767 parse: function( execResult ) {
11768 return [
11769 parseInt( execResult[ 1 ], 16 ),
11770 parseInt( execResult[ 2 ], 16 ),
11771 parseInt( execResult[ 3 ], 16 ),
11772 execResult[ 4 ] ?
11773 ( parseInt( execResult[ 4 ], 16 ) / 255 ).toFixed( 2 ) :
11774 1
11775 ];
11776 }
11777 }, {
11778
11779 // this regex ignores A-F because it's compared against an already lowercased string
11780 re: /#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/,
11781 parse: function( execResult ) {
11782 return [
11783 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
11784 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
11785 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ),
11786 execResult[ 4 ] ?
11787 ( parseInt( execResult[ 4 ] + execResult[ 4 ], 16 ) / 255 )
11788 .toFixed( 2 ) :
11789 1
11790 ];
11791 }
11792 }, {
11793 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
11794 space: "hsla",
11795 parse: function( execResult ) {
11796 return [
11797 execResult[ 1 ],
11798 execResult[ 2 ] / 100,
11799 execResult[ 3 ] / 100,
11800 execResult[ 4 ]
11801 ];
11802 }
11803 } ],
11804
11805 // jQuery.Color( )
11806 color = jQuery.Color = function( color, green, blue, alpha ) {
11807 return new jQuery.Color.fn.parse( color, green, blue, alpha );
11808 },
11809 spaces = {
11810 rgba: {
11811 props: {
11812 red: {
11813 idx: 0,
11814 type: "byte"
11815 },
11816 green: {
11817 idx: 1,
11818 type: "byte"
11819 },
11820 blue: {
11821 idx: 2,
11822 type: "byte"
11823 }
11824 }
11825 },
11826
11827 hsla: {
11828 props: {
11829 hue: {
11830 idx: 0,
11831 type: "degrees"
11832 },
11833 saturation: {
11834 idx: 1,
11835 type: "percent"
11836 },
11837 lightness: {
11838 idx: 2,
11839 type: "percent"
11840 }
11841 }
11842 }
11843 },
11844 propTypes = {
11845 "byte": {
11846 floor: true,
11847 max: 255
11848 },
11849 "percent": {
11850 max: 1
11851 },
11852 "degrees": {
11853 mod: 360,
11854 floor: true
11855 }
11856 },
11857
11858 // colors = jQuery.Color.names
11859 colors,
11860
11861 // local aliases of functions called often
11862 each = jQuery.each;
11863
11864// define cache name and alpha properties
11865// for rgba and hsla spaces
11866each( spaces, function( spaceName, space ) {
11867 space.cache = "_" + spaceName;
11868 space.props.alpha = {
11869 idx: 3,
11870 type: "percent",
11871 def: 1
11872 };
11873} );
11874
11875// Populate the class2type map
11876jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
11877 function( _i, name ) {
11878 class2type[ "[object " + name + "]" ] = name.toLowerCase();
11879 } );
11880
11881function getType( obj ) {
11882 if ( obj == null ) {
11883 return obj + "";
11884 }
11885
11886 return typeof obj === "object" ?
11887 class2type[ toString.call( obj ) ] || "object" :
11888 typeof obj;
11889}
11890
11891function clamp( value, prop, allowEmpty ) {
11892 var type = propTypes[ prop.type ] || {};
11893
11894 if ( value == null ) {
11895 return ( allowEmpty || !prop.def ) ? null : prop.def;
11896 }
11897
11898 // ~~ is an short way of doing floor for positive numbers
11899 value = type.floor ? ~~value : parseFloat( value );
11900
11901 if ( type.mod ) {
11902
11903 // we add mod before modding to make sure that negatives values
11904 // get converted properly: -10 -> 350
11905 return ( value + type.mod ) % type.mod;
11906 }
11907
11908 // for now all property types without mod have min and max
11909 return Math.min( type.max, Math.max( 0, value ) );
11910}
11911
11912function stringParse( string ) {
11913 var inst = color(),
11914 rgba = inst._rgba = [];
11915
11916 string = string.toLowerCase();
11917
11918 each( stringParsers, function( _i, parser ) {
11919 var parsed,
11920 match = parser.re.exec( string ),
11921 values = match && parser.parse( match ),
11922 spaceName = parser.space || "rgba";
11923
11924 if ( values ) {
11925 parsed = inst[ spaceName ]( values );
11926
11927 // if this was an rgba parse the assignment might happen twice
11928 // oh well....
11929 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
11930 rgba = inst._rgba = parsed._rgba;
11931
11932 // exit each( stringParsers ) here because we matched
11933 return false;
11934 }
11935 } );
11936
11937 // Found a stringParser that handled it
11938 if ( rgba.length ) {
11939
11940 // if this came from a parsed string, force "transparent" when alpha is 0
11941 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
11942 if ( rgba.join() === "0,0,0,0" ) {
11943 jQuery.extend( rgba, colors.transparent );
11944 }
11945 return inst;
11946 }
11947
11948 // named colors
11949 return colors[ string ];
11950}
11951
11952color.fn = jQuery.extend( color.prototype, {
11953 parse: function( red, green, blue, alpha ) {
11954 if ( red === undefined ) {
11955 this._rgba = [ null, null, null, null ];
11956 return this;
11957 }
11958 if ( red.jquery || red.nodeType ) {
11959 red = jQuery( red ).css( green );
11960 green = undefined;
11961 }
11962
11963 var inst = this,
11964 type = getType( red ),
11965 rgba = this._rgba = [];
11966
11967 // more than 1 argument specified - assume ( red, green, blue, alpha )
11968 if ( green !== undefined ) {
11969 red = [ red, green, blue, alpha ];
11970 type = "array";
11971 }
11972
11973 if ( type === "string" ) {
11974 return this.parse( stringParse( red ) || colors._default );
11975 }
11976
11977 if ( type === "array" ) {
11978 each( spaces.rgba.props, function( _key, prop ) {
11979 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
11980 } );
11981 return this;
11982 }
11983
11984 if ( type === "object" ) {
11985 if ( red instanceof color ) {
11986 each( spaces, function( _spaceName, space ) {
11987 if ( red[ space.cache ] ) {
11988 inst[ space.cache ] = red[ space.cache ].slice();
11989 }
11990 } );
11991 } else {
11992 each( spaces, function( _spaceName, space ) {
11993 var cache = space.cache;
11994 each( space.props, function( key, prop ) {
11995
11996 // if the cache doesn't exist, and we know how to convert
11997 if ( !inst[ cache ] && space.to ) {
11998
11999 // if the value was null, we don't need to copy it
12000 // if the key was alpha, we don't need to copy it either
12001 if ( key === "alpha" || red[ key ] == null ) {
12002 return;
12003 }
12004 inst[ cache ] = space.to( inst._rgba );
12005 }
12006
12007 // this is the only case where we allow nulls for ALL properties.
12008 // call clamp with alwaysAllowEmpty
12009 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
12010 } );
12011
12012 // everything defined but alpha?
12013 if ( inst[ cache ] && jQuery.inArray(
12014 null,
12015 inst[ cache ].slice( 0, 3 )
12016 ) < 0 ) {
12017
12018 // use the default of 1
12019 if ( inst[ cache ][ 3 ] == null ) {
12020 inst[ cache ][ 3 ] = 1;
12021 }
12022
12023 if ( space.from ) {
12024 inst._rgba = space.from( inst[ cache ] );
12025 }
12026 }
12027 } );
12028 }
12029 return this;
12030 }
12031 },
12032 is: function( compare ) {
12033 var is = color( compare ),
12034 same = true,
12035 inst = this;
12036
12037 each( spaces, function( _, space ) {
12038 var localCache,
12039 isCache = is[ space.cache ];
12040 if ( isCache ) {
12041 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
12042 each( space.props, function( _, prop ) {
12043 if ( isCache[ prop.idx ] != null ) {
12044 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
12045 return same;
12046 }
12047 } );
12048 }
12049 return same;
12050 } );
12051 return same;
12052 },
12053 _space: function() {
12054 var used = [],
12055 inst = this;
12056 each( spaces, function( spaceName, space ) {
12057 if ( inst[ space.cache ] ) {
12058 used.push( spaceName );
12059 }
12060 } );
12061 return used.pop();
12062 },
12063 transition: function( other, distance ) {
12064 var end = color( other ),
12065 spaceName = end._space(),
12066 space = spaces[ spaceName ],
12067 startColor = this.alpha() === 0 ? color( "transparent" ) : this,
12068 start = startColor[ space.cache ] || space.to( startColor._rgba ),
12069 result = start.slice();
12070
12071 end = end[ space.cache ];
12072 each( space.props, function( _key, prop ) {
12073 var index = prop.idx,
12074 startValue = start[ index ],
12075 endValue = end[ index ],
12076 type = propTypes[ prop.type ] || {};
12077
12078 // if null, don't override start value
12079 if ( endValue === null ) {
12080 return;
12081 }
12082
12083 // if null - use end
12084 if ( startValue === null ) {
12085 result[ index ] = endValue;
12086 } else {
12087 if ( type.mod ) {
12088 if ( endValue - startValue > type.mod / 2 ) {
12089 startValue += type.mod;
12090 } else if ( startValue - endValue > type.mod / 2 ) {
12091 startValue -= type.mod;
12092 }
12093 }
12094 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
12095 }
12096 } );
12097 return this[ spaceName ]( result );
12098 },
12099 blend: function( opaque ) {
12100
12101 // if we are already opaque - return ourself
12102 if ( this._rgba[ 3 ] === 1 ) {
12103 return this;
12104 }
12105
12106 var rgb = this._rgba.slice(),
12107 a = rgb.pop(),
12108 blend = color( opaque )._rgba;
12109
12110 return color( jQuery.map( rgb, function( v, i ) {
12111 return ( 1 - a ) * blend[ i ] + a * v;
12112 } ) );
12113 },
12114 toRgbaString: function() {
12115 var prefix = "rgba(",
12116 rgba = jQuery.map( this._rgba, function( v, i ) {
12117 if ( v != null ) {
12118 return v;
12119 }
12120 return i > 2 ? 1 : 0;
12121 } );
12122
12123 if ( rgba[ 3 ] === 1 ) {
12124 rgba.pop();
12125 prefix = "rgb(";
12126 }
12127
12128 return prefix + rgba.join( ", " ) + ")";
12129 },
12130 toHslaString: function() {
12131 var prefix = "hsla(",
12132 hsla = jQuery.map( this.hsla(), function( v, i ) {
12133 if ( v == null ) {
12134 v = i > 2 ? 1 : 0;
12135 }
12136
12137 // catch 1 and 2
12138 if ( i && i < 3 ) {
12139 v = Math.round( v * 100 ) + "%";
12140 }
12141 return v;
12142 } );
12143
12144 if ( hsla[ 3 ] === 1 ) {
12145 hsla.pop();
12146 prefix = "hsl(";
12147 }
12148 return prefix + hsla.join( ", " ) + ")";
12149 },
12150 toHexString: function( includeAlpha ) {
12151 var rgba = this._rgba.slice(),
12152 alpha = rgba.pop();
12153
12154 if ( includeAlpha ) {
12155 rgba.push( ~~( alpha * 255 ) );
12156 }
12157
12158 return "#" + jQuery.map( rgba, function( v ) {
12159
12160 // default to 0 when nulls exist
12161 return ( "0" + ( v || 0 ).toString( 16 ) ).substr( -2 );
12162 } ).join( "" );
12163 },
12164 toString: function() {
12165 return this.toRgbaString();
12166 }
12167} );
12168color.fn.parse.prototype = color.fn;
12169
12170// hsla conversions adapted from:
12171// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
12172
12173function hue2rgb( p, q, h ) {
12174 h = ( h + 1 ) % 1;
12175 if ( h * 6 < 1 ) {
12176 return p + ( q - p ) * h * 6;
12177 }
12178 if ( h * 2 < 1 ) {
12179 return q;
12180 }
12181 if ( h * 3 < 2 ) {
12182 return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
12183 }
12184 return p;
12185}
12186
12187spaces.hsla.to = function( rgba ) {
12188 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
12189 return [ null, null, null, rgba[ 3 ] ];
12190 }
12191 var r = rgba[ 0 ] / 255,
12192 g = rgba[ 1 ] / 255,
12193 b = rgba[ 2 ] / 255,
12194 a = rgba[ 3 ],
12195 max = Math.max( r, g, b ),
12196 min = Math.min( r, g, b ),
12197 diff = max - min,
12198 add = max + min,
12199 l = add * 0.5,
12200 h, s;
12201
12202 if ( min === max ) {
12203 h = 0;
12204 } else if ( r === max ) {
12205 h = ( 60 * ( g - b ) / diff ) + 360;
12206 } else if ( g === max ) {
12207 h = ( 60 * ( b - r ) / diff ) + 120;
12208 } else {
12209 h = ( 60 * ( r - g ) / diff ) + 240;
12210 }
12211
12212 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
12213 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
12214 if ( diff === 0 ) {
12215 s = 0;
12216 } else if ( l <= 0.5 ) {
12217 s = diff / add;
12218 } else {
12219 s = diff / ( 2 - add );
12220 }
12221 return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];
12222};
12223
12224spaces.hsla.from = function( hsla ) {
12225 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
12226 return [ null, null, null, hsla[ 3 ] ];
12227 }
12228 var h = hsla[ 0 ] / 360,
12229 s = hsla[ 1 ],
12230 l = hsla[ 2 ],
12231 a = hsla[ 3 ],
12232 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
12233 p = 2 * l - q;
12234
12235 return [
12236 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
12237 Math.round( hue2rgb( p, q, h ) * 255 ),
12238 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
12239 a
12240 ];
12241};
12242
12243
12244each( spaces, function( spaceName, space ) {
12245 var props = space.props,
12246 cache = space.cache,
12247 to = space.to,
12248 from = space.from;
12249
12250 // makes rgba() and hsla()
12251 color.fn[ spaceName ] = function( value ) {
12252
12253 // generate a cache for this space if it doesn't exist
12254 if ( to && !this[ cache ] ) {
12255 this[ cache ] = to( this._rgba );
12256 }
12257 if ( value === undefined ) {
12258 return this[ cache ].slice();
12259 }
12260
12261 var ret,
12262 type = getType( value ),
12263 arr = ( type === "array" || type === "object" ) ? value : arguments,
12264 local = this[ cache ].slice();
12265
12266 each( props, function( key, prop ) {
12267 var val = arr[ type === "object" ? key : prop.idx ];
12268 if ( val == null ) {
12269 val = local[ prop.idx ];
12270 }
12271 local[ prop.idx ] = clamp( val, prop );
12272 } );
12273
12274 if ( from ) {
12275 ret = color( from( local ) );
12276 ret[ cache ] = local;
12277 return ret;
12278 } else {
12279 return color( local );
12280 }
12281 };
12282
12283 // makes red() green() blue() alpha() hue() saturation() lightness()
12284 each( props, function( key, prop ) {
12285
12286 // alpha is included in more than one space
12287 if ( color.fn[ key ] ) {
12288 return;
12289 }
12290 color.fn[ key ] = function( value ) {
12291 var local, cur, match, fn,
12292 vtype = getType( value );
12293
12294 if ( key === "alpha" ) {
12295 fn = this._hsla ? "hsla" : "rgba";
12296 } else {
12297 fn = spaceName;
12298 }
12299 local = this[ fn ]();
12300 cur = local[ prop.idx ];
12301
12302 if ( vtype === "undefined" ) {
12303 return cur;
12304 }
12305
12306 if ( vtype === "function" ) {
12307 value = value.call( this, cur );
12308 vtype = getType( value );
12309 }
12310 if ( value == null && prop.empty ) {
12311 return this;
12312 }
12313 if ( vtype === "string" ) {
12314 match = rplusequals.exec( value );
12315 if ( match ) {
12316 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
12317 }
12318 }
12319 local[ prop.idx ] = value;
12320 return this[ fn ]( local );
12321 };
12322 } );
12323} );
12324
12325// add cssHook and .fx.step function for each named hook.
12326// accept a space separated string of properties
12327color.hook = function( hook ) {
12328 var hooks = hook.split( " " );
12329 each( hooks, function( _i, hook ) {
12330 jQuery.cssHooks[ hook ] = {
12331 set: function( elem, value ) {
12332 var parsed;
12333
12334 if ( value !== "transparent" &&
12335 ( getType( value ) !== "string" ||
12336 ( parsed = stringParse( value ) ) ) ) {
12337 value = color( parsed || value );
12338 value = value.toRgbaString();
12339 }
12340 elem.style[ hook ] = value;
12341 }
12342 };
12343 jQuery.fx.step[ hook ] = function( fx ) {
12344 if ( !fx.colorInit ) {
12345 fx.start = color( fx.elem, hook );
12346 fx.end = color( fx.end );
12347 fx.colorInit = true;
12348 }
12349 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
12350 };
12351 } );
12352
12353};
12354
12355color.hook( stepHooks );
12356
12357jQuery.cssHooks.borderColor = {
12358 expand: function( value ) {
12359 var expanded = {};
12360
12361 each( [ "Top", "Right", "Bottom", "Left" ], function( _i, part ) {
12362 expanded[ "border" + part + "Color" ] = value;
12363 } );
12364 return expanded;
12365 }
12366};
12367
12368// Basic color names only.
12369// Usage of any of the other color names requires adding yourself or including
12370// jquery.color.svg-names.js.
12371colors = jQuery.Color.names = {
12372
12373 // 4.1. Basic color keywords
12374 aqua: "#00ffff",
12375 black: "#000000",
12376 blue: "#0000ff",
12377 fuchsia: "#ff00ff",
12378 gray: "#808080",
12379 green: "#008000",
12380 lime: "#00ff00",
12381 maroon: "#800000",
12382 navy: "#000080",
12383 olive: "#808000",
12384 purple: "#800080",
12385 red: "#ff0000",
12386 silver: "#c0c0c0",
12387 teal: "#008080",
12388 white: "#ffffff",
12389 yellow: "#ffff00",
12390
12391 // 4.2.3. "transparent" color keyword
12392 transparent: [ null, null, null, 0 ],
12393
12394 _default: "#ffffff"
12395};
12396
12397} );
12398
12399
12400
12401
12402/*!
12403 * jQuery UI Effects 1.14.1
12404 * https://jqueryui.com
12405 *
12406 * Copyright OpenJS Foundation and other contributors
12407 * Released under the MIT license.
12408 * https://jquery.org/license
12409 */
12410
12411//>>label: Effects Core
12412//>>group: Effects
12413/* eslint-disable max-len */
12414//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.
12415/* eslint-enable max-len */
12416//>>docs: https://api.jqueryui.com/category/effects-core/
12417//>>demos: https://jqueryui.com/effect/
12418
12419( function( factory ) {
12420 "use strict";
12421
12422 if ( typeof define === "function" && define.amd ) {
12423
12424 // AMD. Register as an anonymous module.
12425 define( [
12426 "jquery",
12427 "./jquery-var-for-color",
12428 "./vendor/jquery-color/jquery.color",
12429 "./version"
12430 ], factory );
12431 } else {
12432
12433 // Browser globals
12434 factory( jQuery );
12435 }
12436} )( function( $ ) {
12437"use strict";
12438
12439var dataSpace = "ui-effects-",
12440 dataSpaceStyle = "ui-effects-style",
12441 dataSpaceAnimated = "ui-effects-animated";
12442
12443$.effects = {
12444 effect: {}
12445};
12446
12447/******************************************************************************/
12448/****************************** CLASS ANIMATIONS ******************************/
12449/******************************************************************************/
12450( function() {
12451
12452var classAnimationActions = [ "add", "remove", "toggle" ],
12453 shorthandStyles = {
12454 border: 1,
12455 borderBottom: 1,
12456 borderColor: 1,
12457 borderLeft: 1,
12458 borderRight: 1,
12459 borderTop: 1,
12460 borderWidth: 1,
12461 margin: 1,
12462 padding: 1
12463 };
12464
12465$.each(
12466 [ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ],
12467 function( _, prop ) {
12468 $.fx.step[ prop ] = function( fx ) {
12469 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
12470 jQuery.style( fx.elem, prop, fx.end );
12471 fx.setAttr = true;
12472 }
12473 };
12474 }
12475);
12476
12477function camelCase( string ) {
12478 return string.replace( /-([\da-z])/gi, function( all, letter ) {
12479 return letter.toUpperCase();
12480 } );
12481}
12482
12483function getElementStyles( elem ) {
12484 var key, len,
12485 style = elem.ownerDocument.defaultView.getComputedStyle( elem ),
12486 styles = {};
12487
12488 len = style.length;
12489 while ( len-- ) {
12490 key = style[ len ];
12491 if ( typeof style[ key ] === "string" ) {
12492 styles[ camelCase( key ) ] = style[ key ];
12493 }
12494 }
12495
12496 return styles;
12497}
12498
12499function styleDifference( oldStyle, newStyle ) {
12500 var diff = {},
12501 name, value;
12502
12503 for ( name in newStyle ) {
12504 value = newStyle[ name ];
12505 if ( oldStyle[ name ] !== value ) {
12506 if ( !shorthandStyles[ name ] ) {
12507 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
12508 diff[ name ] = value;
12509 }
12510 }
12511 }
12512 }
12513
12514 return diff;
12515}
12516
12517$.effects.animateClass = function( value, duration, easing, callback ) {
12518 var o = $.speed( duration, easing, callback );
12519
12520 return this.queue( function() {
12521 var animated = $( this ),
12522 baseClass = animated.attr( "class" ) || "",
12523 applyClassChange,
12524 allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
12525
12526 // Map the animated objects to store the original styles.
12527 allAnimations = allAnimations.map( function() {
12528 var el = $( this );
12529 return {
12530 el: el,
12531 start: getElementStyles( this )
12532 };
12533 } );
12534
12535 // Apply class change
12536 applyClassChange = function() {
12537 $.each( classAnimationActions, function( i, action ) {
12538 if ( value[ action ] ) {
12539 animated[ action + "Class" ]( value[ action ] );
12540 }
12541 } );
12542 };
12543 applyClassChange();
12544
12545 // Map all animated objects again - calculate new styles and diff
12546 allAnimations = allAnimations.map( function() {
12547 this.end = getElementStyles( this.el[ 0 ] );
12548 this.diff = styleDifference( this.start, this.end );
12549 return this;
12550 } );
12551
12552 // Apply original class
12553 animated.attr( "class", baseClass );
12554
12555 // Map all animated objects again - this time collecting a promise
12556 allAnimations = allAnimations.map( function() {
12557 var styleInfo = this,
12558 dfd = $.Deferred(),
12559 opts = $.extend( {}, o, {
12560 queue: false,
12561 complete: function() {
12562 dfd.resolve( styleInfo );
12563 }
12564 } );
12565
12566 this.el.animate( this.diff, opts );
12567 return dfd.promise();
12568 } );
12569
12570 // Once all animations have completed:
12571 $.when.apply( $, allAnimations.get() ).done( function() {
12572
12573 // Set the final class
12574 applyClassChange();
12575
12576 // For each animated element,
12577 // clear all css properties that were animated
12578 $.each( arguments, function() {
12579 var el = this.el;
12580 $.each( this.diff, function( key ) {
12581 el.css( key, "" );
12582 } );
12583 } );
12584
12585 // This is guarnteed to be there if you use jQuery.speed()
12586 // it also handles dequeuing the next anim...
12587 o.complete.call( animated[ 0 ] );
12588 } );
12589 } );
12590};
12591
12592$.fn.extend( {
12593 addClass: ( function( orig ) {
12594 return function( classNames, speed, easing, callback ) {
12595 return speed ?
12596 $.effects.animateClass.call( this,
12597 { add: classNames }, speed, easing, callback ) :
12598 orig.apply( this, arguments );
12599 };
12600 } )( $.fn.addClass ),
12601
12602 removeClass: ( function( orig ) {
12603 return function( classNames, speed, easing, callback ) {
12604 return arguments.length > 1 ?
12605 $.effects.animateClass.call( this,
12606 { remove: classNames }, speed, easing, callback ) :
12607 orig.apply( this, arguments );
12608 };
12609 } )( $.fn.removeClass ),
12610
12611 toggleClass: ( function( orig ) {
12612 return function( classNames, force, speed, easing, callback ) {
12613 if ( typeof force === "boolean" || force === undefined ) {
12614 if ( !speed ) {
12615
12616 // Without speed parameter
12617 return orig.apply( this, arguments );
12618 } else {
12619 return $.effects.animateClass.call( this,
12620 ( force ? { add: classNames } : { remove: classNames } ),
12621 speed, easing, callback );
12622 }
12623 } else {
12624
12625 // Without force parameter
12626 return $.effects.animateClass.call( this,
12627 { toggle: classNames }, force, speed, easing );
12628 }
12629 };
12630 } )( $.fn.toggleClass ),
12631
12632 switchClass: function( remove, add, speed, easing, callback ) {
12633 return $.effects.animateClass.call( this, {
12634 add: add,
12635 remove: remove
12636 }, speed, easing, callback );
12637 }
12638} );
12639
12640} )();
12641
12642/******************************************************************************/
12643/*********************************** EFFECTS **********************************/
12644/******************************************************************************/
12645
12646( function() {
12647
12648if ( $.expr && $.expr.pseudos && $.expr.pseudos.animated ) {
12649 $.expr.pseudos.animated = ( function( orig ) {
12650 return function( elem ) {
12651 return !!$( elem ).data( dataSpaceAnimated ) || orig( elem );
12652 };
12653 } )( $.expr.pseudos.animated );
12654}
12655
12656if ( $.uiBackCompat === true ) {
12657 $.extend( $.effects, {
12658
12659 // Saves a set of properties in a data storage
12660 save: function( element, set ) {
12661 var i = 0, length = set.length;
12662 for ( ; i < length; i++ ) {
12663 if ( set[ i ] !== null ) {
12664 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
12665 }
12666 }
12667 },
12668
12669 // Restores a set of previously saved properties from a data storage
12670 restore: function( element, set ) {
12671 var val, i = 0, length = set.length;
12672 for ( ; i < length; i++ ) {
12673 if ( set[ i ] !== null ) {
12674 val = element.data( dataSpace + set[ i ] );
12675 element.css( set[ i ], val );
12676 }
12677 }
12678 },
12679
12680 setMode: function( el, mode ) {
12681 if ( mode === "toggle" ) {
12682 mode = el.is( ":hidden" ) ? "show" : "hide";
12683 }
12684 return mode;
12685 },
12686
12687 // Wraps the element around a wrapper that copies position properties
12688 createWrapper: function( element ) {
12689
12690 // If the element is already wrapped, return it
12691 if ( element.parent().is( ".ui-effects-wrapper" ) ) {
12692 return element.parent();
12693 }
12694
12695 // Wrap the element
12696 var props = {
12697 width: element.outerWidth( true ),
12698 height: element.outerHeight( true ),
12699 "float": element.css( "float" )
12700 },
12701 wrapper = $( "<div></div>" )
12702 .addClass( "ui-effects-wrapper" )
12703 .css( {
12704 fontSize: "100%",
12705 background: "transparent",
12706 border: "none",
12707 margin: 0,
12708 padding: 0
12709 } ),
12710
12711 // Store the size in case width/height are defined in % - Fixes #5245
12712 size = {
12713 width: element.width(),
12714 height: element.height()
12715 },
12716 active = document.activeElement;
12717
12718 // Support: Firefox
12719 // Firefox incorrectly exposes anonymous content
12720 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
12721 try {
12722 // eslint-disable-next-line no-unused-expressions
12723 active.id;
12724 } catch ( e ) {
12725 active = document.body;
12726 }
12727
12728 element.wrap( wrapper );
12729
12730 // Fixes #7595 - Elements lose focus when wrapped.
12731 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
12732 $( active ).trigger( "focus" );
12733 }
12734
12735 // Hotfix for jQuery 1.4 since some change in wrap() seems to actually
12736 // lose the reference to the wrapped element
12737 wrapper = element.parent();
12738
12739 // Transfer positioning properties to the wrapper
12740 if ( element.css( "position" ) === "static" ) {
12741 wrapper.css( { position: "relative" } );
12742 element.css( { position: "relative" } );
12743 } else {
12744 $.extend( props, {
12745 position: element.css( "position" ),
12746 zIndex: element.css( "z-index" )
12747 } );
12748 $.each( [ "top", "left", "bottom", "right" ], function( i, pos ) {
12749 props[ pos ] = element.css( pos );
12750 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
12751 props[ pos ] = "auto";
12752 }
12753 } );
12754 element.css( {
12755 position: "relative",
12756 top: 0,
12757 left: 0,
12758 right: "auto",
12759 bottom: "auto"
12760 } );
12761 }
12762 element.css( size );
12763
12764 return wrapper.css( props ).show();
12765 },
12766
12767 removeWrapper: function( element ) {
12768 var active = document.activeElement;
12769
12770 if ( element.parent().is( ".ui-effects-wrapper" ) ) {
12771 element.parent().replaceWith( element );
12772
12773 // Fixes #7595 - Elements lose focus when wrapped.
12774 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
12775 $( active ).trigger( "focus" );
12776 }
12777 }
12778
12779 return element;
12780 }
12781 } );
12782}
12783
12784$.extend( $.effects, {
12785 version: "1.14.1",
12786
12787 define: function( name, mode, effect ) {
12788 if ( !effect ) {
12789 effect = mode;
12790 mode = "effect";
12791 }
12792
12793 $.effects.effect[ name ] = effect;
12794 $.effects.effect[ name ].mode = mode;
12795
12796 return effect;
12797 },
12798
12799 scaledDimensions: function( element, percent, direction ) {
12800 if ( percent === 0 ) {
12801 return {
12802 height: 0,
12803 width: 0,
12804 outerHeight: 0,
12805 outerWidth: 0
12806 };
12807 }
12808
12809 var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1,
12810 y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1;
12811
12812 return {
12813 height: element.height() * y,
12814 width: element.width() * x,
12815 outerHeight: element.outerHeight() * y,
12816 outerWidth: element.outerWidth() * x
12817 };
12818
12819 },
12820
12821 clipToBox: function( animation ) {
12822 return {
12823 width: animation.clip.right - animation.clip.left,
12824 height: animation.clip.bottom - animation.clip.top,
12825 left: animation.clip.left,
12826 top: animation.clip.top
12827 };
12828 },
12829
12830 // Injects recently queued functions to be first in line (after "inprogress")
12831 unshift: function( element, queueLength, count ) {
12832 var queue = element.queue();
12833
12834 if ( queueLength > 1 ) {
12835 queue.splice.apply( queue,
12836 [ 1, 0 ].concat( queue.splice( queueLength, count ) ) );
12837 }
12838 element.dequeue();
12839 },
12840
12841 saveStyle: function( element ) {
12842 element.data( dataSpaceStyle, element[ 0 ].style.cssText );
12843 },
12844
12845 restoreStyle: function( element ) {
12846 element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || "";
12847 element.removeData( dataSpaceStyle );
12848 },
12849
12850 mode: function( element, mode ) {
12851 var hidden = element.is( ":hidden" );
12852
12853 if ( mode === "toggle" ) {
12854 mode = hidden ? "show" : "hide";
12855 }
12856 if ( hidden ? mode === "hide" : mode === "show" ) {
12857 mode = "none";
12858 }
12859 return mode;
12860 },
12861
12862 // Translates a [top,left] array into a baseline value
12863 getBaseline: function( origin, original ) {
12864 var y, x;
12865
12866 switch ( origin[ 0 ] ) {
12867 case "top":
12868 y = 0;
12869 break;
12870 case "middle":
12871 y = 0.5;
12872 break;
12873 case "bottom":
12874 y = 1;
12875 break;
12876 default:
12877 y = origin[ 0 ] / original.height;
12878 }
12879
12880 switch ( origin[ 1 ] ) {
12881 case "left":
12882 x = 0;
12883 break;
12884 case "center":
12885 x = 0.5;
12886 break;
12887 case "right":
12888 x = 1;
12889 break;
12890 default:
12891 x = origin[ 1 ] / original.width;
12892 }
12893
12894 return {
12895 x: x,
12896 y: y
12897 };
12898 },
12899
12900 // Creates a placeholder element so that the original element can be made absolute
12901 createPlaceholder: function( element ) {
12902 var placeholder,
12903 cssPosition = element.css( "position" ),
12904 position = element.position();
12905
12906 // Lock in margins first to account for form elements, which
12907 // will change margin if you explicitly set height
12908 // see: https://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380
12909 // Support: Safari
12910 element.css( {
12911 marginTop: element.css( "marginTop" ),
12912 marginBottom: element.css( "marginBottom" ),
12913 marginLeft: element.css( "marginLeft" ),
12914 marginRight: element.css( "marginRight" )
12915 } )
12916 .outerWidth( element.outerWidth() )
12917 .outerHeight( element.outerHeight() );
12918
12919 if ( /^(static|relative)/.test( cssPosition ) ) {
12920 cssPosition = "absolute";
12921
12922 placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( {
12923
12924 // Convert inline to inline block to account for inline elements
12925 // that turn to inline block based on content (like img)
12926 display: /^(inline|ruby)/.test( element.css( "display" ) ) ?
12927 "inline-block" :
12928 "block",
12929 visibility: "hidden",
12930
12931 // Margins need to be set to account for margin collapse
12932 marginTop: element.css( "marginTop" ),
12933 marginBottom: element.css( "marginBottom" ),
12934 marginLeft: element.css( "marginLeft" ),
12935 marginRight: element.css( "marginRight" ),
12936 "float": element.css( "float" )
12937 } )
12938 .outerWidth( element.outerWidth() )
12939 .outerHeight( element.outerHeight() )
12940 .addClass( "ui-effects-placeholder" );
12941
12942 element.data( dataSpace + "placeholder", placeholder );
12943 }
12944
12945 element.css( {
12946 position: cssPosition,
12947 left: position.left,
12948 top: position.top
12949 } );
12950
12951 return placeholder;
12952 },
12953
12954 removePlaceholder: function( element ) {
12955 var dataKey = dataSpace + "placeholder",
12956 placeholder = element.data( dataKey );
12957
12958 if ( placeholder ) {
12959 placeholder.remove();
12960 element.removeData( dataKey );
12961 }
12962 },
12963
12964 // Removes a placeholder if it exists and restores
12965 // properties that were modified during placeholder creation
12966 cleanUp: function( element ) {
12967 $.effects.restoreStyle( element );
12968 $.effects.removePlaceholder( element );
12969 },
12970
12971 setTransition: function( element, list, factor, value ) {
12972 value = value || {};
12973 $.each( list, function( i, x ) {
12974 var unit = element.cssUnit( x );
12975 if ( unit[ 0 ] > 0 ) {
12976 value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
12977 }
12978 } );
12979 return value;
12980 }
12981} );
12982
12983// Return an effect options object for the given parameters:
12984function _normalizeArguments( effect, options, speed, callback ) {
12985
12986 // Allow passing all options as the first parameter
12987 if ( $.isPlainObject( effect ) ) {
12988 options = effect;
12989 effect = effect.effect;
12990 }
12991
12992 // Convert to an object
12993 effect = { effect: effect };
12994
12995 // Catch (effect, null, ...)
12996 if ( options == null ) {
12997 options = {};
12998 }
12999
13000 // Catch (effect, callback)
13001 if ( typeof options === "function" ) {
13002 callback = options;
13003 speed = null;
13004 options = {};
13005 }
13006
13007 // Catch (effect, speed, ?)
13008 if ( typeof options === "number" || $.fx.speeds[ options ] ) {
13009 callback = speed;
13010 speed = options;
13011 options = {};
13012 }
13013
13014 // Catch (effect, options, callback)
13015 if ( typeof speed === "function" ) {
13016 callback = speed;
13017 speed = null;
13018 }
13019
13020 // Add options to effect
13021 if ( options ) {
13022 $.extend( effect, options );
13023 }
13024
13025 speed = speed || options.duration;
13026 effect.duration = $.fx.off ? 0 :
13027 typeof speed === "number" ? speed :
13028 speed in $.fx.speeds ? $.fx.speeds[ speed ] :
13029 $.fx.speeds._default;
13030
13031 effect.complete = callback || options.complete;
13032
13033 return effect;
13034}
13035
13036function standardAnimationOption( option ) {
13037
13038 // Valid standard speeds (nothing, number, named speed)
13039 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
13040 return true;
13041 }
13042
13043 // Invalid strings - treat as "normal" speed
13044 if ( typeof option === "string" && !$.effects.effect[ option ] ) {
13045 return true;
13046 }
13047
13048 // Complete callback
13049 if ( typeof option === "function" ) {
13050 return true;
13051 }
13052
13053 // Options hash (but not naming an effect)
13054 if ( typeof option === "object" && !option.effect ) {
13055 return true;
13056 }
13057
13058 // Didn't match any standard API
13059 return false;
13060}
13061
13062$.fn.extend( {
13063 effect: function( /* effect, options, speed, callback */ ) {
13064 var args = _normalizeArguments.apply( this, arguments ),
13065 effectMethod = $.effects.effect[ args.effect ],
13066 defaultMode = effectMethod.mode,
13067 queue = args.queue,
13068 queueName = queue || "fx",
13069 complete = args.complete,
13070 mode = args.mode,
13071 modes = [],
13072 prefilter = function( next ) {
13073 var el = $( this ),
13074 normalizedMode = $.effects.mode( el, mode ) || defaultMode;
13075
13076 // Sentinel for duck-punching the :animated pseudo-selector
13077 el.data( dataSpaceAnimated, true );
13078
13079 // Save effect mode for later use,
13080 // we can't just call $.effects.mode again later,
13081 // as the .show() below destroys the initial state
13082 modes.push( normalizedMode );
13083
13084 // See $.uiBackCompat inside of run() for removal of defaultMode in 1.14
13085 if ( defaultMode && ( normalizedMode === "show" ||
13086 ( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) {
13087 el.show();
13088 }
13089
13090 if ( !defaultMode || normalizedMode !== "none" ) {
13091 $.effects.saveStyle( el );
13092 }
13093
13094 if ( typeof next === "function" ) {
13095 next();
13096 }
13097 };
13098
13099 if ( $.fx.off || !effectMethod ) {
13100
13101 // Delegate to the original method (e.g., .show()) if possible
13102 if ( mode ) {
13103 return this[ mode ]( args.duration, complete );
13104 } else {
13105 return this.each( function() {
13106 if ( complete ) {
13107 complete.call( this );
13108 }
13109 } );
13110 }
13111 }
13112
13113 function run( next ) {
13114 var elem = $( this );
13115
13116 function cleanup() {
13117 elem.removeData( dataSpaceAnimated );
13118
13119 $.effects.cleanUp( elem );
13120
13121 if ( args.mode === "hide" ) {
13122 elem.hide();
13123 }
13124
13125 done();
13126 }
13127
13128 function done() {
13129 if ( typeof complete === "function" ) {
13130 complete.call( elem[ 0 ] );
13131 }
13132
13133 if ( typeof next === "function" ) {
13134 next();
13135 }
13136 }
13137
13138 // Override mode option on a per element basis,
13139 // as toggle can be either show or hide depending on element state
13140 args.mode = modes.shift();
13141
13142 if ( $.uiBackCompat === true && !defaultMode ) {
13143 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
13144
13145 // Call the core method to track "olddisplay" properly
13146 elem[ mode ]();
13147 done();
13148 } else {
13149 effectMethod.call( elem[ 0 ], args, done );
13150 }
13151 } else {
13152 if ( args.mode === "none" ) {
13153
13154 // Call the core method to track "olddisplay" properly
13155 elem[ mode ]();
13156 done();
13157 } else {
13158 effectMethod.call( elem[ 0 ], args, cleanup );
13159 }
13160 }
13161 }
13162
13163 // Run prefilter on all elements first to ensure that
13164 // any showing or hiding happens before placeholder creation,
13165 // which ensures that any layout changes are correctly captured.
13166 return queue === false ?
13167 this.each( prefilter ).each( run ) :
13168 this.queue( queueName, prefilter ).queue( queueName, run );
13169 },
13170
13171 show: ( function( orig ) {
13172 return function( option ) {
13173 if ( standardAnimationOption( option ) ) {
13174 return orig.apply( this, arguments );
13175 } else {
13176 var args = _normalizeArguments.apply( this, arguments );
13177 args.mode = "show";
13178 return this.effect.call( this, args );
13179 }
13180 };
13181 } )( $.fn.show ),
13182
13183 hide: ( function( orig ) {
13184 return function( option ) {
13185 if ( standardAnimationOption( option ) ) {
13186 return orig.apply( this, arguments );
13187 } else {
13188 var args = _normalizeArguments.apply( this, arguments );
13189 args.mode = "hide";
13190 return this.effect.call( this, args );
13191 }
13192 };
13193 } )( $.fn.hide ),
13194
13195 toggle: ( function( orig ) {
13196 return function( option ) {
13197 if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
13198 return orig.apply( this, arguments );
13199 } else {
13200 var args = _normalizeArguments.apply( this, arguments );
13201 args.mode = "toggle";
13202 return this.effect.call( this, args );
13203 }
13204 };
13205 } )( $.fn.toggle ),
13206
13207 cssUnit: function( key ) {
13208 var style = this.css( key ),
13209 val = [];
13210
13211 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
13212 if ( style.indexOf( unit ) > 0 ) {
13213 val = [ parseFloat( style ), unit ];
13214 }
13215 } );
13216 return val;
13217 },
13218
13219 cssClip: function( clipObj ) {
13220 if ( clipObj ) {
13221 return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " +
13222 clipObj.bottom + "px " + clipObj.left + "px)" );
13223 }
13224 return parseClip( this.css( "clip" ), this );
13225 },
13226
13227 transfer: function( options, done ) {
13228 var element = $( this ),
13229 target = $( options.to ),
13230 targetFixed = target.css( "position" ) === "fixed",
13231 body = $( "body" ),
13232 fixTop = targetFixed ? body.scrollTop() : 0,
13233 fixLeft = targetFixed ? body.scrollLeft() : 0,
13234 endPosition = target.offset(),
13235 animation = {
13236 top: endPosition.top - fixTop,
13237 left: endPosition.left - fixLeft,
13238 height: target.innerHeight(),
13239 width: target.innerWidth()
13240 },
13241 startPosition = element.offset(),
13242 transfer = $( "<div class='ui-effects-transfer'></div>" );
13243
13244 transfer
13245 .appendTo( "body" )
13246 .addClass( options.className )
13247 .css( {
13248 top: startPosition.top - fixTop,
13249 left: startPosition.left - fixLeft,
13250 height: element.innerHeight(),
13251 width: element.innerWidth(),
13252 position: targetFixed ? "fixed" : "absolute"
13253 } )
13254 .animate( animation, options.duration, options.easing, function() {
13255 transfer.remove();
13256 if ( typeof done === "function" ) {
13257 done();
13258 }
13259 } );
13260 }
13261} );
13262
13263function parseClip( str, element ) {
13264 var outerWidth = element.outerWidth(),
13265 outerHeight = element.outerHeight(),
13266 clipRegex = /^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/,
13267 values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ];
13268
13269 return {
13270 top: parseFloat( values[ 1 ] ) || 0,
13271 right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ),
13272 bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ),
13273 left: parseFloat( values[ 4 ] ) || 0
13274 };
13275}
13276
13277$.fx.step.clip = function( fx ) {
13278 if ( !fx.clipInit ) {
13279 fx.start = $( fx.elem ).cssClip();
13280 if ( typeof fx.end === "string" ) {
13281 fx.end = parseClip( fx.end, fx.elem );
13282 }
13283 fx.clipInit = true;
13284 }
13285
13286 $( fx.elem ).cssClip( {
13287 top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,
13288 right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,
13289 bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,
13290 left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left
13291 } );
13292};
13293
13294} )();
13295
13296/******************************************************************************/
13297/*********************************** EASING ***********************************/
13298/******************************************************************************/
13299
13300( function() {
13301
13302// Based on easing equations from Robert Penner (http://robertpenner.com/easing)
13303
13304var baseEasings = {};
13305
13306$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
13307 baseEasings[ name ] = function( p ) {
13308 return Math.pow( p, i + 2 );
13309 };
13310} );
13311
13312$.extend( baseEasings, {
13313 Sine: function( p ) {
13314 return 1 - Math.cos( p * Math.PI / 2 );
13315 },
13316 Circ: function( p ) {
13317 return 1 - Math.sqrt( 1 - p * p );
13318 },
13319 Elastic: function( p ) {
13320 return p === 0 || p === 1 ? p :
13321 -Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );
13322 },
13323 Back: function( p ) {
13324 return p * p * ( 3 * p - 2 );
13325 },
13326 Bounce: function( p ) {
13327 var pow2,
13328 bounce = 4;
13329
13330 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
13331 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
13332 }
13333} );
13334
13335$.each( baseEasings, function( name, easeIn ) {
13336 $.easing[ "easeIn" + name ] = easeIn;
13337 $.easing[ "easeOut" + name ] = function( p ) {
13338 return 1 - easeIn( 1 - p );
13339 };
13340 $.easing[ "easeInOut" + name ] = function( p ) {
13341 return p < 0.5 ?
13342 easeIn( p * 2 ) / 2 :
13343 1 - easeIn( p * -2 + 2 ) / 2;
13344 };
13345} );
13346
13347} )();
13348
13349return $.effects;
13350
13351} );
13352
13353
13354/*!
13355 * jQuery UI Focusable 1.14.1
13356 * https://jqueryui.com
13357 *
13358 * Copyright OpenJS Foundation and other contributors
13359 * Released under the MIT license.
13360 * https://jquery.org/license
13361 */
13362
13363//>>label: :focusable Selector
13364//>>group: Core
13365//>>description: Selects elements which can be focused.
13366//>>docs: https://api.jqueryui.com/focusable-selector/
13367
13368( function( factory ) {
13369 "use strict";
13370
13371 if ( typeof define === "function" && define.amd ) {
13372
13373 // AMD. Register as an anonymous module.
13374 define( [ "jquery", "./version" ], factory );
13375 } else {
13376
13377 // Browser globals
13378 factory( jQuery );
13379 }
13380} )( function( $ ) {
13381"use strict";
13382
13383// Selectors
13384$.ui.focusable = function( element, hasTabindex ) {
13385 var map, mapName, img, focusableIfVisible, fieldset,
13386 nodeName = element.nodeName.toLowerCase();
13387
13388 if ( "area" === nodeName ) {
13389 map = element.parentNode;
13390 mapName = map.name;
13391 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
13392 return false;
13393 }
13394 img = $( "img[usemap='#" + mapName + "']" );
13395 return img.length > 0 && img.is( ":visible" );
13396 }
13397
13398 if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
13399 focusableIfVisible = !element.disabled;
13400
13401 if ( focusableIfVisible ) {
13402
13403 // Form controls within a disabled fieldset are disabled.
13404 // However, controls within the fieldset's legend do not get disabled.
13405 // Since controls generally aren't placed inside legends, we skip
13406 // this portion of the check.
13407 fieldset = $( element ).closest( "fieldset" )[ 0 ];
13408 if ( fieldset ) {
13409 focusableIfVisible = !fieldset.disabled;
13410 }
13411 }
13412 } else if ( "a" === nodeName ) {
13413 focusableIfVisible = element.href || hasTabindex;
13414 } else {
13415 focusableIfVisible = hasTabindex;
13416 }
13417
13418 return focusableIfVisible && $( element ).is( ":visible" ) &&
13419 $( element ).css( "visibility" ) === "visible";
13420};
13421
13422$.extend( $.expr.pseudos, {
13423 focusable: function( element ) {
13424 return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
13425 }
13426} );
13427
13428return $.ui.focusable;
13429
13430} );
13431
13432
13433/*!
13434 * jQuery UI Form Reset Mixin 1.14.1
13435 * https://jqueryui.com
13436 *
13437 * Copyright OpenJS Foundation and other contributors
13438 * Released under the MIT license.
13439 * https://jquery.org/license
13440 */
13441
13442//>>label: Form Reset Mixin
13443//>>group: Core
13444//>>description: Refresh input widgets when their form is reset
13445//>>docs: https://api.jqueryui.com/form-reset-mixin/
13446
13447( function( factory ) {
13448 "use strict";
13449
13450 if ( typeof define === "function" && define.amd ) {
13451
13452 // AMD. Register as an anonymous module.
13453 define( [
13454 "jquery",
13455 "./version"
13456 ], factory );
13457 } else {
13458
13459 // Browser globals
13460 factory( jQuery );
13461 }
13462} )( function( $ ) {
13463"use strict";
13464
13465return $.ui.formResetMixin = {
13466 _formResetHandler: function() {
13467 var form = $( this );
13468
13469 // Wait for the form reset to actually happen before refreshing
13470 setTimeout( function() {
13471 var instances = form.data( "ui-form-reset-instances" );
13472 $.each( instances, function() {
13473 this.refresh();
13474 } );
13475 } );
13476 },
13477
13478 _bindFormResetHandler: function() {
13479 this.form = $( this.element.prop( "form" ) );
13480 if ( !this.form.length ) {
13481 return;
13482 }
13483
13484 var instances = this.form.data( "ui-form-reset-instances" ) || [];
13485 if ( !instances.length ) {
13486
13487 // We don't use _on() here because we use a single event handler per form
13488 this.form.on( "reset.ui-form-reset", this._formResetHandler );
13489 }
13490 instances.push( this );
13491 this.form.data( "ui-form-reset-instances", instances );
13492 },
13493
13494 _unbindFormResetHandler: function() {
13495 if ( !this.form.length ) {
13496 return;
13497 }
13498
13499 var instances = this.form.data( "ui-form-reset-instances" );
13500 instances.splice( $.inArray( this, instances ), 1 );
13501 if ( instances.length ) {
13502 this.form.data( "ui-form-reset-instances", instances );
13503 } else {
13504 this.form
13505 .removeData( "ui-form-reset-instances" )
13506 .off( "reset.ui-form-reset" );
13507 }
13508 }
13509};
13510
13511} );
13512
13513
13514/*!
13515 * jQuery UI Legacy jQuery Core patches 1.14.1
13516 * https://jqueryui.com
13517 *
13518 * Copyright OpenJS Foundation and other contributors
13519 * Released under the MIT license.
13520 * https://jquery.org/license
13521 *
13522 */
13523
13524//>>label: Legacy jQuery Core patches
13525//>>group: Core
13526//>>description: Backport `.even()`, `.odd()` and `$.escapeSelector` to older jQuery Core versions (deprecated)
13527
13528( function( factory ) {
13529"use strict";
13530
13531 if ( typeof define === "function" && define.amd ) {
13532
13533 // AMD. Register as an anonymous module.
13534 define( [ "jquery", "./version" ], factory );
13535 } else {
13536
13537 // Browser globals
13538 factory( jQuery );
13539 }
13540} )( function( $ ) {
13541"use strict";
13542
13543// Support: jQuery 2.2.x or older.
13544// This method has been defined in jQuery 3.0.0.
13545// Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js
13546if ( !$.escapeSelector ) {
13547 $.escapeSelector = function( id ) {
13548 return CSS.escape( id + "" );
13549 };
13550}
13551
13552// Support: jQuery 3.4.x or older
13553// These methods have been defined in jQuery 3.5.0.
13554if ( !$.fn.even || !$.fn.odd ) {
13555 $.fn.extend( {
13556 even: function() {
13557 return this.filter( function( i ) {
13558 return i % 2 === 0;
13559 } );
13560 },
13561 odd: function() {
13562 return this.filter( function( i ) {
13563 return i % 2 === 1;
13564 } );
13565 }
13566 } );
13567}
13568
13569} );
13570
13571
13572/*!
13573 * jQuery UI Keycode 1.14.1
13574 * https://jqueryui.com
13575 *
13576 * Copyright OpenJS Foundation and other contributors
13577 * Released under the MIT license.
13578 * https://jquery.org/license
13579 */
13580
13581//>>label: Keycode
13582//>>group: Core
13583//>>description: Provide keycodes as keynames
13584//>>docs: https://api.jqueryui.com/jQuery.ui.keyCode/
13585
13586( function( factory ) {
13587 "use strict";
13588
13589 if ( typeof define === "function" && define.amd ) {
13590
13591 // AMD. Register as an anonymous module.
13592 define( [ "jquery", "./version" ], factory );
13593 } else {
13594
13595 // Browser globals
13596 factory( jQuery );
13597 }
13598} )( function( $ ) {
13599"use strict";
13600
13601return $.ui.keyCode = {
13602 BACKSPACE: 8,
13603 COMMA: 188,
13604 DELETE: 46,
13605 DOWN: 40,
13606 END: 35,
13607 ENTER: 13,
13608 ESCAPE: 27,
13609 HOME: 36,
13610 LEFT: 37,
13611 PAGE_DOWN: 34,
13612 PAGE_UP: 33,
13613 PERIOD: 190,
13614 RIGHT: 39,
13615 SPACE: 32,
13616 TAB: 9,
13617 UP: 38
13618};
13619
13620} );
13621
13622
13623/*!
13624 * jQuery UI Labels 1.14.1
13625 * https://jqueryui.com
13626 *
13627 * Copyright OpenJS Foundation and other contributors
13628 * Released under the MIT license.
13629 * https://jquery.org/license
13630 */
13631
13632//>>label: labels
13633//>>group: Core
13634//>>description: Find all the labels associated with a given input
13635//>>docs: https://api.jqueryui.com/labels/
13636
13637( function( factory ) {
13638 "use strict";
13639
13640 if ( typeof define === "function" && define.amd ) {
13641
13642 // AMD. Register as an anonymous module.
13643 define( [ "jquery", "./version" ], factory );
13644 } else {
13645
13646 // Browser globals
13647 factory( jQuery );
13648 }
13649} )( function( $ ) {
13650"use strict";
13651
13652return $.fn.labels = function() {
13653 var ancestor, selector, id, labels, ancestors;
13654
13655 if ( !this.length ) {
13656 return this.pushStack( [] );
13657 }
13658
13659 // Check control.labels first
13660 if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
13661 return this.pushStack( this[ 0 ].labels );
13662 }
13663
13664 // If `control.labels` is empty - e.g. inside of document fragments - find
13665 // the labels manually
13666 labels = this.eq( 0 ).parents( "label" );
13667
13668 // Look for the label based on the id
13669 id = this.attr( "id" );
13670 if ( id ) {
13671
13672 // We don't search against the document in case the element
13673 // is disconnected from the DOM
13674 ancestor = this.eq( 0 ).parents().last();
13675
13676 // Get a full set of top level ancestors
13677 ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
13678
13679 // Create a selector for the label based on the id
13680 selector = "label[for='" + CSS.escape( id ) + "']";
13681
13682 labels = labels.add( ancestors.find( selector ).addBack( selector ) );
13683
13684 }
13685
13686 // Return whatever we have found for labels
13687 return this.pushStack( labels );
13688};
13689
13690} );
13691
13692( function( factory ) {
13693 "use strict";
13694
13695 if ( typeof define === "function" && define.amd ) {
13696
13697 // AMD. Register as an anonymous module.
13698 define( [ "jquery", "./version" ], factory );
13699 } else {
13700
13701 // Browser globals
13702 factory( jQuery );
13703 }
13704} )( function( $ ) {
13705"use strict";
13706
13707// $.ui.plugin is deprecated. Use $.widget() extensions instead.
13708return $.ui.plugin = {
13709 add: function( module, option, set ) {
13710 var i,
13711 proto = $.ui[ module ].prototype;
13712 for ( i in set ) {
13713 proto.plugins[ i ] = proto.plugins[ i ] || [];
13714 proto.plugins[ i ].push( [ option, set[ i ] ] );
13715 }
13716 },
13717 call: function( instance, name, args, allowDisconnected ) {
13718 var i,
13719 set = instance.plugins[ name ];
13720
13721 if ( !set ) {
13722 return;
13723 }
13724
13725 if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
13726 instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
13727 return;
13728 }
13729
13730 for ( i = 0; i < set.length; i++ ) {
13731 if ( instance.options[ set[ i ][ 0 ] ] ) {
13732 set[ i ][ 1 ].apply( instance.element, args );
13733 }
13734 }
13735 }
13736};
13737
13738} );
13739
13740
13741/*!
13742 * jQuery UI Position 1.14.1
13743 * https://jqueryui.com
13744 *
13745 * Copyright OpenJS Foundation and other contributors
13746 * Released under the MIT license.
13747 * https://jquery.org/license
13748 *
13749 * https://api.jqueryui.com/position/
13750 */
13751
13752//>>label: Position
13753//>>group: Core
13754//>>description: Positions elements relative to other elements.
13755//>>docs: https://api.jqueryui.com/position/
13756//>>demos: https://jqueryui.com/position/
13757
13758( function( factory ) {
13759 "use strict";
13760
13761 if ( typeof define === "function" && define.amd ) {
13762
13763 // AMD. Register as an anonymous module.
13764 define( [ "jquery", "./version" ], factory );
13765 } else {
13766
13767 // Browser globals
13768 factory( jQuery );
13769 }
13770} )( function( $ ) {
13771"use strict";
13772
13773( function() {
13774var cachedScrollbarWidth,
13775 max = Math.max,
13776 abs = Math.abs,
13777 rhorizontal = /left|center|right/,
13778 rvertical = /top|center|bottom/,
13779 roffset = /[\+\-]\d+(\.[\d]+)?%?/,
13780 rposition = /^\w+/,
13781 rpercent = /%$/,
13782 _position = $.fn.position;
13783
13784function getOffsets( offsets, width, height ) {
13785 return [
13786 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
13787 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
13788 ];
13789}
13790
13791function parseCss( element, property ) {
13792 return parseInt( $.css( element, property ), 10 ) || 0;
13793}
13794
13795function isWindow( obj ) {
13796 return obj != null && obj === obj.window;
13797}
13798
13799function getDimensions( elem ) {
13800 var raw = elem[ 0 ];
13801 if ( raw.nodeType === 9 ) {
13802 return {
13803 width: elem.width(),
13804 height: elem.height(),
13805 offset: { top: 0, left: 0 }
13806 };
13807 }
13808 if ( isWindow( raw ) ) {
13809 return {
13810 width: elem.width(),
13811 height: elem.height(),
13812 offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
13813 };
13814 }
13815 if ( raw.preventDefault ) {
13816 return {
13817 width: 0,
13818 height: 0,
13819 offset: { top: raw.pageY, left: raw.pageX }
13820 };
13821 }
13822 return {
13823 width: elem.outerWidth(),
13824 height: elem.outerHeight(),
13825 offset: elem.offset()
13826 };
13827}
13828
13829$.position = {
13830 scrollbarWidth: function() {
13831 if ( cachedScrollbarWidth !== undefined ) {
13832 return cachedScrollbarWidth;
13833 }
13834 var w1, w2,
13835 div = $( "<div style=" +
13836 "'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" +
13837 "<div style='height:300px;width:auto;'></div></div>" ),
13838 innerDiv = div.children()[ 0 ];
13839
13840 $( "body" ).append( div );
13841 w1 = innerDiv.offsetWidth;
13842 div.css( "overflow", "scroll" );
13843
13844 w2 = innerDiv.offsetWidth;
13845
13846 if ( w1 === w2 ) {
13847 w2 = div[ 0 ].clientWidth;
13848 }
13849
13850 div.remove();
13851
13852 return ( cachedScrollbarWidth = w1 - w2 );
13853 },
13854 getScrollInfo: function( within ) {
13855 var overflowX = within.isWindow || within.isDocument ? "" :
13856 within.element.css( "overflow-x" ),
13857 overflowY = within.isWindow || within.isDocument ? "" :
13858 within.element.css( "overflow-y" ),
13859 hasOverflowX = overflowX === "scroll" ||
13860 ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
13861 hasOverflowY = overflowY === "scroll" ||
13862 ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
13863 return {
13864 width: hasOverflowY ? $.position.scrollbarWidth() : 0,
13865 height: hasOverflowX ? $.position.scrollbarWidth() : 0
13866 };
13867 },
13868 getWithinInfo: function( element ) {
13869 var withinElement = $( element || window ),
13870 isElemWindow = isWindow( withinElement[ 0 ] ),
13871 isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
13872 hasOffset = !isElemWindow && !isDocument;
13873 return {
13874 element: withinElement,
13875 isWindow: isElemWindow,
13876 isDocument: isDocument,
13877 offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
13878 scrollLeft: withinElement.scrollLeft(),
13879 scrollTop: withinElement.scrollTop(),
13880 width: withinElement.outerWidth(),
13881 height: withinElement.outerHeight()
13882 };
13883 }
13884};
13885
13886$.fn.position = function( options ) {
13887 if ( !options || !options.of ) {
13888 return _position.apply( this, arguments );
13889 }
13890
13891 // Make a copy, we don't want to modify arguments
13892 options = $.extend( {}, options );
13893
13894 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
13895
13896 // Make sure string options are treated as CSS selectors
13897 target = typeof options.of === "string" ?
13898 $( document ).find( options.of ) :
13899 $( options.of ),
13900
13901 within = $.position.getWithinInfo( options.within ),
13902 scrollInfo = $.position.getScrollInfo( within ),
13903 collision = ( options.collision || "flip" ).split( " " ),
13904 offsets = {};
13905
13906 dimensions = getDimensions( target );
13907 if ( target[ 0 ].preventDefault ) {
13908
13909 // Force left top to allow flipping
13910 options.at = "left top";
13911 }
13912 targetWidth = dimensions.width;
13913 targetHeight = dimensions.height;
13914 targetOffset = dimensions.offset;
13915
13916 // Clone to reuse original targetOffset later
13917 basePosition = $.extend( {}, targetOffset );
13918
13919 // Force my and at to have valid horizontal and vertical positions
13920 // if a value is missing or invalid, it will be converted to center
13921 $.each( [ "my", "at" ], function() {
13922 var pos = ( options[ this ] || "" ).split( " " ),
13923 horizontalOffset,
13924 verticalOffset;
13925
13926 if ( pos.length === 1 ) {
13927 pos = rhorizontal.test( pos[ 0 ] ) ?
13928 pos.concat( [ "center" ] ) :
13929 rvertical.test( pos[ 0 ] ) ?
13930 [ "center" ].concat( pos ) :
13931 [ "center", "center" ];
13932 }
13933 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
13934 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
13935
13936 // Calculate offsets
13937 horizontalOffset = roffset.exec( pos[ 0 ] );
13938 verticalOffset = roffset.exec( pos[ 1 ] );
13939 offsets[ this ] = [
13940 horizontalOffset ? horizontalOffset[ 0 ] : 0,
13941 verticalOffset ? verticalOffset[ 0 ] : 0
13942 ];
13943
13944 // Reduce to just the positions without the offsets
13945 options[ this ] = [
13946 rposition.exec( pos[ 0 ] )[ 0 ],
13947 rposition.exec( pos[ 1 ] )[ 0 ]
13948 ];
13949 } );
13950
13951 // Normalize collision option
13952 if ( collision.length === 1 ) {
13953 collision[ 1 ] = collision[ 0 ];
13954 }
13955
13956 if ( options.at[ 0 ] === "right" ) {
13957 basePosition.left += targetWidth;
13958 } else if ( options.at[ 0 ] === "center" ) {
13959 basePosition.left += targetWidth / 2;
13960 }
13961
13962 if ( options.at[ 1 ] === "bottom" ) {
13963 basePosition.top += targetHeight;
13964 } else if ( options.at[ 1 ] === "center" ) {
13965 basePosition.top += targetHeight / 2;
13966 }
13967
13968 atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
13969 basePosition.left += atOffset[ 0 ];
13970 basePosition.top += atOffset[ 1 ];
13971
13972 return this.each( function() {
13973 var collisionPosition, using,
13974 elem = $( this ),
13975 elemWidth = elem.outerWidth(),
13976 elemHeight = elem.outerHeight(),
13977 marginLeft = parseCss( this, "marginLeft" ),
13978 marginTop = parseCss( this, "marginTop" ),
13979 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
13980 scrollInfo.width,
13981 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
13982 scrollInfo.height,
13983 position = $.extend( {}, basePosition ),
13984 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
13985
13986 if ( options.my[ 0 ] === "right" ) {
13987 position.left -= elemWidth;
13988 } else if ( options.my[ 0 ] === "center" ) {
13989 position.left -= elemWidth / 2;
13990 }
13991
13992 if ( options.my[ 1 ] === "bottom" ) {
13993 position.top -= elemHeight;
13994 } else if ( options.my[ 1 ] === "center" ) {
13995 position.top -= elemHeight / 2;
13996 }
13997
13998 position.left += myOffset[ 0 ];
13999 position.top += myOffset[ 1 ];
14000
14001 collisionPosition = {
14002 marginLeft: marginLeft,
14003 marginTop: marginTop
14004 };
14005
14006 $.each( [ "left", "top" ], function( i, dir ) {
14007 if ( $.ui.position[ collision[ i ] ] ) {
14008 $.ui.position[ collision[ i ] ][ dir ]( position, {
14009 targetWidth: targetWidth,
14010 targetHeight: targetHeight,
14011 elemWidth: elemWidth,
14012 elemHeight: elemHeight,
14013 collisionPosition: collisionPosition,
14014 collisionWidth: collisionWidth,
14015 collisionHeight: collisionHeight,
14016 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
14017 my: options.my,
14018 at: options.at,
14019 within: within,
14020 elem: elem
14021 } );
14022 }
14023 } );
14024
14025 if ( options.using ) {
14026
14027 // Adds feedback as second argument to using callback, if present
14028 using = function( props ) {
14029 var left = targetOffset.left - position.left,
14030 right = left + targetWidth - elemWidth,
14031 top = targetOffset.top - position.top,
14032 bottom = top + targetHeight - elemHeight,
14033 feedback = {
14034 target: {
14035 element: target,
14036 left: targetOffset.left,
14037 top: targetOffset.top,
14038 width: targetWidth,
14039 height: targetHeight
14040 },
14041 element: {
14042 element: elem,
14043 left: position.left,
14044 top: position.top,
14045 width: elemWidth,
14046 height: elemHeight
14047 },
14048 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
14049 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
14050 };
14051 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
14052 feedback.horizontal = "center";
14053 }
14054 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
14055 feedback.vertical = "middle";
14056 }
14057 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
14058 feedback.important = "horizontal";
14059 } else {
14060 feedback.important = "vertical";
14061 }
14062 options.using.call( this, props, feedback );
14063 };
14064 }
14065
14066 elem.offset( $.extend( position, { using: using } ) );
14067 } );
14068};
14069
14070$.ui.position = {
14071 fit: {
14072 left: function( position, data ) {
14073 var within = data.within,
14074 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
14075 outerWidth = within.width,
14076 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
14077 overLeft = withinOffset - collisionPosLeft,
14078 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
14079 newOverRight;
14080
14081 // Element is wider than within
14082 if ( data.collisionWidth > outerWidth ) {
14083
14084 // Element is initially over the left side of within
14085 if ( overLeft > 0 && overRight <= 0 ) {
14086 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
14087 withinOffset;
14088 position.left += overLeft - newOverRight;
14089
14090 // Element is initially over right side of within
14091 } else if ( overRight > 0 && overLeft <= 0 ) {
14092 position.left = withinOffset;
14093
14094 // Element is initially over both left and right sides of within
14095 } else {
14096 if ( overLeft > overRight ) {
14097 position.left = withinOffset + outerWidth - data.collisionWidth;
14098 } else {
14099 position.left = withinOffset;
14100 }
14101 }
14102
14103 // Too far left -> align with left edge
14104 } else if ( overLeft > 0 ) {
14105 position.left += overLeft;
14106
14107 // Too far right -> align with right edge
14108 } else if ( overRight > 0 ) {
14109 position.left -= overRight;
14110
14111 // Adjust based on position and margin
14112 } else {
14113 position.left = max( position.left - collisionPosLeft, position.left );
14114 }
14115 },
14116 top: function( position, data ) {
14117 var within = data.within,
14118 withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
14119 outerHeight = data.within.height,
14120 collisionPosTop = position.top - data.collisionPosition.marginTop,
14121 overTop = withinOffset - collisionPosTop,
14122 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
14123 newOverBottom;
14124
14125 // Element is taller than within
14126 if ( data.collisionHeight > outerHeight ) {
14127
14128 // Element is initially over the top of within
14129 if ( overTop > 0 && overBottom <= 0 ) {
14130 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
14131 withinOffset;
14132 position.top += overTop - newOverBottom;
14133
14134 // Element is initially over bottom of within
14135 } else if ( overBottom > 0 && overTop <= 0 ) {
14136 position.top = withinOffset;
14137
14138 // Element is initially over both top and bottom of within
14139 } else {
14140 if ( overTop > overBottom ) {
14141 position.top = withinOffset + outerHeight - data.collisionHeight;
14142 } else {
14143 position.top = withinOffset;
14144 }
14145 }
14146
14147 // Too far up -> align with top
14148 } else if ( overTop > 0 ) {
14149 position.top += overTop;
14150
14151 // Too far down -> align with bottom edge
14152 } else if ( overBottom > 0 ) {
14153 position.top -= overBottom;
14154
14155 // Adjust based on position and margin
14156 } else {
14157 position.top = max( position.top - collisionPosTop, position.top );
14158 }
14159 }
14160 },
14161 flip: {
14162 left: function( position, data ) {
14163 var within = data.within,
14164 withinOffset = within.offset.left + within.scrollLeft,
14165 outerWidth = within.width,
14166 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
14167 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
14168 overLeft = collisionPosLeft - offsetLeft,
14169 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
14170 myOffset = data.my[ 0 ] === "left" ?
14171 -data.elemWidth :
14172 data.my[ 0 ] === "right" ?
14173 data.elemWidth :
14174 0,
14175 atOffset = data.at[ 0 ] === "left" ?
14176 data.targetWidth :
14177 data.at[ 0 ] === "right" ?
14178 -data.targetWidth :
14179 0,
14180 offset = -2 * data.offset[ 0 ],
14181 newOverRight,
14182 newOverLeft;
14183
14184 if ( overLeft < 0 ) {
14185 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
14186 outerWidth - withinOffset;
14187 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
14188 position.left += myOffset + atOffset + offset;
14189 }
14190 } else if ( overRight > 0 ) {
14191 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
14192 atOffset + offset - offsetLeft;
14193 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
14194 position.left += myOffset + atOffset + offset;
14195 }
14196 }
14197 },
14198 top: function( position, data ) {
14199 var within = data.within,
14200 withinOffset = within.offset.top + within.scrollTop,
14201 outerHeight = within.height,
14202 offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
14203 collisionPosTop = position.top - data.collisionPosition.marginTop,
14204 overTop = collisionPosTop - offsetTop,
14205 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
14206 top = data.my[ 1 ] === "top",
14207 myOffset = top ?
14208 -data.elemHeight :
14209 data.my[ 1 ] === "bottom" ?
14210 data.elemHeight :
14211 0,
14212 atOffset = data.at[ 1 ] === "top" ?
14213 data.targetHeight :
14214 data.at[ 1 ] === "bottom" ?
14215 -data.targetHeight :
14216 0,
14217 offset = -2 * data.offset[ 1 ],
14218 newOverTop,
14219 newOverBottom;
14220 if ( overTop < 0 ) {
14221 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
14222 outerHeight - withinOffset;
14223 if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
14224 position.top += myOffset + atOffset + offset;
14225 }
14226 } else if ( overBottom > 0 ) {
14227 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
14228 offset - offsetTop;
14229 if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
14230 position.top += myOffset + atOffset + offset;
14231 }
14232 }
14233 }
14234 },
14235 flipfit: {
14236 left: function() {
14237 $.ui.position.flip.left.apply( this, arguments );
14238 $.ui.position.fit.left.apply( this, arguments );
14239 },
14240 top: function() {
14241 $.ui.position.flip.top.apply( this, arguments );
14242 $.ui.position.fit.top.apply( this, arguments );
14243 }
14244 }
14245};
14246
14247} )();
14248
14249return $.ui.position;
14250
14251} );
14252
14253
14254/*!
14255 * jQuery UI Scroll Parent 1.14.1
14256 * https://jqueryui.com
14257 *
14258 * Copyright OpenJS Foundation and other contributors
14259 * Released under the MIT license.
14260 * https://jquery.org/license
14261 */
14262
14263//>>label: scrollParent
14264//>>group: Core
14265//>>description: Get the closest ancestor element that is scrollable.
14266//>>docs: https://api.jqueryui.com/scrollParent/
14267
14268( function( factory ) {
14269 "use strict";
14270
14271 if ( typeof define === "function" && define.amd ) {
14272
14273 // AMD. Register as an anonymous module.
14274 define( [ "jquery", "./version" ], factory );
14275 } else {
14276
14277 // Browser globals
14278 factory( jQuery );
14279 }
14280} )( function( $ ) {
14281"use strict";
14282
14283return $.fn.scrollParent = function( includeHidden ) {
14284 var position = this.css( "position" ),
14285 excludeStaticParent = position === "absolute",
14286 overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
14287 scrollParent = this.parents().filter( function() {
14288 var parent = $( this );
14289 if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
14290 return false;
14291 }
14292 return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
14293 parent.css( "overflow-x" ) );
14294 } ).eq( 0 );
14295
14296 return position === "fixed" || !scrollParent.length ?
14297 $( this[ 0 ].ownerDocument || document ) :
14298 scrollParent;
14299};
14300
14301} );
14302
14303
14304
14305/*!
14306 * jQuery UI Tabbable 1.14.1
14307 * https://jqueryui.com
14308 *
14309 * Copyright OpenJS Foundation and other contributors
14310 * Released under the MIT license.
14311 * https://jquery.org/license
14312 */
14313
14314//>>label: :tabbable Selector
14315//>>group: Core
14316//>>description: Selects elements which can be tabbed to.
14317//>>docs: https://api.jqueryui.com/tabbable-selector/
14318
14319( function( factory ) {
14320 "use strict";
14321
14322 if ( typeof define === "function" && define.amd ) {
14323
14324 // AMD. Register as an anonymous module.
14325 define( [ "jquery", "./version", "./focusable" ], factory );
14326 } else {
14327
14328 // Browser globals
14329 factory( jQuery );
14330 }
14331} )( function( $ ) {
14332"use strict";
14333
14334return $.extend( $.expr.pseudos, {
14335 tabbable: function( element ) {
14336 var tabIndex = $.attr( element, "tabindex" ),
14337 hasTabindex = tabIndex != null;
14338 return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
14339 }
14340} );
14341
14342} );
14343
14344
14345/*!
14346 * jQuery UI Unique ID 1.14.1
14347 * https://jqueryui.com
14348 *
14349 * Copyright OpenJS Foundation and other contributors
14350 * Released under the MIT license.
14351 * https://jquery.org/license
14352 */
14353
14354//>>label: uniqueId
14355//>>group: Core
14356//>>description: Functions to generate and remove uniqueId's
14357//>>docs: https://api.jqueryui.com/uniqueId/
14358
14359( function( factory ) {
14360 "use strict";
14361
14362 if ( typeof define === "function" && define.amd ) {
14363
14364 // AMD. Register as an anonymous module.
14365 define( [ "jquery", "./version" ], factory );
14366 } else {
14367
14368 // Browser globals
14369 factory( jQuery );
14370 }
14371} )( function( $ ) {
14372"use strict";
14373
14374return $.fn.extend( {
14375 uniqueId: ( function() {
14376 var uuid = 0;
14377
14378 return function() {
14379 return this.each( function() {
14380 if ( !this.id ) {
14381 this.id = "ui-id-" + ( ++uuid );
14382 }
14383 } );
14384 };
14385 } )(),
14386
14387 removeUniqueId: function() {
14388 return this.each( function() {
14389 if ( /^ui-id-\d+$/.test( this.id ) ) {
14390 $( this ).removeAttr( "id" );
14391 }
14392 } );
14393 }
14394} );
14395
14396} );
14397
14398
14399/*!
14400 * jQuery UI Widget 1.14.1
14401 * https://jqueryui.com
14402 *
14403 * Copyright OpenJS Foundation and other contributors
14404 * Released under the MIT license.
14405 * https://jquery.org/license
14406 */
14407
14408//>>label: Widget
14409//>>group: Core
14410//>>description: Provides a factory for creating stateful widgets with a common API.
14411//>>docs: https://api.jqueryui.com/jQuery.widget/
14412//>>demos: https://jqueryui.com/widget/
14413
14414( function( factory ) {
14415 "use strict";
14416
14417 if ( typeof define === "function" && define.amd ) {
14418
14419 // AMD. Register as an anonymous module.
14420 define( [ "jquery", "./version" ], factory );
14421 } else {
14422
14423 // Browser globals
14424 factory( jQuery );
14425 }
14426} )( function( $ ) {
14427"use strict";
14428
14429var widgetUuid = 0;
14430var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
14431var widgetSlice = Array.prototype.slice;
14432
14433$.cleanData = ( function( orig ) {
14434 return function( elems ) {
14435 var events, elem, i;
14436 for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
14437
14438 // Only trigger remove when necessary to save time
14439 events = $._data( elem, "events" );
14440 if ( events && events.remove ) {
14441 $( elem ).triggerHandler( "remove" );
14442 }
14443 }
14444 orig( elems );
14445 };
14446} )( $.cleanData );
14447
14448$.widget = function( name, base, prototype ) {
14449 var existingConstructor, constructor, basePrototype;
14450
14451 // ProxiedPrototype allows the provided prototype to remain unmodified
14452 // so that it can be used as a mixin for multiple widgets (#8876)
14453 var proxiedPrototype = {};
14454
14455 var namespace = name.split( "." )[ 0 ];
14456 name = name.split( "." )[ 1 ];
14457 if ( name === "__proto__" || name === "constructor" ) {
14458 return $.error( "Invalid widget name: " + name );
14459 }
14460 var fullName = namespace + "-" + name;
14461
14462 if ( !prototype ) {
14463 prototype = base;
14464 base = $.Widget;
14465 }
14466
14467 if ( Array.isArray( prototype ) ) {
14468 prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
14469 }
14470
14471 // Create selector for plugin
14472 $.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
14473 return !!$.data( elem, fullName );
14474 };
14475
14476 $[ namespace ] = $[ namespace ] || {};
14477 existingConstructor = $[ namespace ][ name ];
14478 constructor = $[ namespace ][ name ] = function( options, element ) {
14479
14480 // Allow instantiation without "new" keyword
14481 if ( !this || !this._createWidget ) {
14482 return new constructor( options, element );
14483 }
14484
14485 // Allow instantiation without initializing for simple inheritance
14486 // must use "new" keyword (the code above always passes args)
14487 if ( arguments.length ) {
14488 this._createWidget( options, element );
14489 }
14490 };
14491
14492 // Extend with the existing constructor to carry over any static properties
14493 $.extend( constructor, existingConstructor, {
14494 version: prototype.version,
14495
14496 // Copy the object used to create the prototype in case we need to
14497 // redefine the widget later
14498 _proto: $.extend( {}, prototype ),
14499
14500 // Track widgets that inherit from this widget in case this widget is
14501 // redefined after a widget inherits from it
14502 _childConstructors: []
14503 } );
14504
14505 basePrototype = new base();
14506
14507 // We need to make the options hash a property directly on the new instance
14508 // otherwise we'll modify the options hash on the prototype that we're
14509 // inheriting from
14510 basePrototype.options = $.widget.extend( {}, basePrototype.options );
14511 $.each( prototype, function( prop, value ) {
14512 if ( typeof value !== "function" ) {
14513 proxiedPrototype[ prop ] = value;
14514 return;
14515 }
14516 proxiedPrototype[ prop ] = ( function() {
14517 function _super() {
14518 return base.prototype[ prop ].apply( this, arguments );
14519 }
14520
14521 function _superApply( args ) {
14522 return base.prototype[ prop ].apply( this, args );
14523 }
14524
14525 return function() {
14526 var __super = this._super;
14527 var __superApply = this._superApply;
14528 var returnValue;
14529
14530 this._super = _super;
14531 this._superApply = _superApply;
14532
14533 returnValue = value.apply( this, arguments );
14534
14535 this._super = __super;
14536 this._superApply = __superApply;
14537
14538 return returnValue;
14539 };
14540 } )();
14541 } );
14542 constructor.prototype = $.widget.extend( basePrototype, {
14543
14544 // TODO: remove support for widgetEventPrefix
14545 // always use the name + a colon as the prefix, e.g., draggable:start
14546 // don't prefix for widgets that aren't DOM-based
14547 widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
14548 }, proxiedPrototype, {
14549 constructor: constructor,
14550 namespace: namespace,
14551 widgetName: name,
14552 widgetFullName: fullName
14553 } );
14554
14555 // If this widget is being redefined then we need to find all widgets that
14556 // are inheriting from it and redefine all of them so that they inherit from
14557 // the new version of this widget. We're essentially trying to replace one
14558 // level in the prototype chain.
14559 if ( existingConstructor ) {
14560 $.each( existingConstructor._childConstructors, function( i, child ) {
14561 var childPrototype = child.prototype;
14562
14563 // Redefine the child widget using the same prototype that was
14564 // originally used, but inherit from the new version of the base
14565 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
14566 child._proto );
14567 } );
14568
14569 // Remove the list of existing child constructors from the old constructor
14570 // so the old child constructors can be garbage collected
14571 delete existingConstructor._childConstructors;
14572 } else {
14573 base._childConstructors.push( constructor );
14574 }
14575
14576 $.widget.bridge( name, constructor );
14577
14578 return constructor;
14579};
14580
14581$.widget.extend = function( target ) {
14582 var input = widgetSlice.call( arguments, 1 );
14583 var inputIndex = 0;
14584 var inputLength = input.length;
14585 var key;
14586 var value;
14587
14588 for ( ; inputIndex < inputLength; inputIndex++ ) {
14589 for ( key in input[ inputIndex ] ) {
14590 value = input[ inputIndex ][ key ];
14591 if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) {
14592
14593 // Clone objects
14594 if ( $.isPlainObject( value ) ) {
14595 target[ key ] = $.isPlainObject( target[ key ] ) ?
14596 $.widget.extend( {}, target[ key ], value ) :
14597
14598 // Don't extend strings, arrays, etc. with objects
14599 $.widget.extend( {}, value );
14600
14601 // Copy everything else by reference
14602 } else {
14603 target[ key ] = value;
14604 }
14605 }
14606 }
14607 }
14608 return target;
14609};
14610
14611$.widget.bridge = function( name, object ) {
14612 var fullName = object.prototype.widgetFullName || name;
14613 $.fn[ name ] = function( options ) {
14614 var isMethodCall = typeof options === "string";
14615 var args = widgetSlice.call( arguments, 1 );
14616 var returnValue = this;
14617
14618 if ( isMethodCall ) {
14619
14620 // If this is an empty collection, we need to have the instance method
14621 // return undefined instead of the jQuery instance
14622 if ( !this.length && options === "instance" ) {
14623 returnValue = undefined;
14624 } else {
14625 this.each( function() {
14626 var methodValue;
14627 var instance = $.data( this, fullName );
14628
14629 if ( options === "instance" ) {
14630 returnValue = instance;
14631 return false;
14632 }
14633
14634 if ( !instance ) {
14635 return $.error( "cannot call methods on " + name +
14636 " prior to initialization; " +
14637 "attempted to call method '" + options + "'" );
14638 }
14639
14640 if ( typeof instance[ options ] !== "function" ||
14641 options.charAt( 0 ) === "_" ) {
14642 return $.error( "no such method '" + options + "' for " + name +
14643 " widget instance" );
14644 }
14645
14646 methodValue = instance[ options ].apply( instance, args );
14647
14648 if ( methodValue !== instance && methodValue !== undefined ) {
14649 returnValue = methodValue && methodValue.jquery ?
14650 returnValue.pushStack( methodValue.get() ) :
14651 methodValue;
14652 return false;
14653 }
14654 } );
14655 }
14656 } else {
14657
14658 // Allow multiple hashes to be passed on init
14659 if ( args.length ) {
14660 options = $.widget.extend.apply( null, [ options ].concat( args ) );
14661 }
14662
14663 this.each( function() {
14664 var instance = $.data( this, fullName );
14665 if ( instance ) {
14666 instance.option( options || {} );
14667 if ( instance._init ) {
14668 instance._init();
14669 }
14670 } else {
14671 $.data( this, fullName, new object( options, this ) );
14672 }
14673 } );
14674 }
14675
14676 return returnValue;
14677 };
14678};
14679
14680$.Widget = function( /* options, element */ ) {};
14681$.Widget._childConstructors = [];
14682
14683$.Widget.prototype = {
14684 widgetName: "widget",
14685 widgetEventPrefix: "",
14686 defaultElement: "<div>",
14687
14688 options: {
14689 classes: {},
14690 disabled: false,
14691
14692 // Callbacks
14693 create: null
14694 },
14695
14696 _createWidget: function( options, element ) {
14697 element = $( element || this.defaultElement || this )[ 0 ];
14698 this.element = $( element );
14699 this.uuid = widgetUuid++;
14700 this.eventNamespace = "." + this.widgetName + this.uuid;
14701
14702 this.bindings = $();
14703 this.hoverable = $();
14704 this.focusable = $();
14705 this.classesElementLookup = {};
14706
14707 if ( element !== this ) {
14708 $.data( element, this.widgetFullName, this );
14709 this._on( true, this.element, {
14710 remove: function( event ) {
14711 if ( event.target === element ) {
14712 this.destroy();
14713 }
14714 }
14715 } );
14716 this.document = $( element.style ?
14717
14718 // Element within the document
14719 element.ownerDocument :
14720
14721 // Element is window or document
14722 element.document || element );
14723 this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
14724 }
14725
14726 this.options = $.widget.extend( {},
14727 this.options,
14728 this._getCreateOptions(),
14729 options );
14730
14731 this._create();
14732
14733 if ( this.options.disabled ) {
14734 this._setOptionDisabled( this.options.disabled );
14735 }
14736
14737 this._trigger( "create", null, this._getCreateEventData() );
14738 this._init();
14739 },
14740
14741 _getCreateOptions: function() {
14742 return {};
14743 },
14744
14745 _getCreateEventData: $.noop,
14746
14747 _create: $.noop,
14748
14749 _init: $.noop,
14750
14751 destroy: function() {
14752 var that = this;
14753
14754 this._destroy();
14755 $.each( this.classesElementLookup, function( key, value ) {
14756 that._removeClass( value, key );
14757 } );
14758
14759 // We can probably remove the unbind calls in 2.0
14760 // all event bindings should go through this._on()
14761 this.element
14762 .off( this.eventNamespace )
14763 .removeData( this.widgetFullName );
14764 this.widget()
14765 .off( this.eventNamespace )
14766 .removeAttr( "aria-disabled" );
14767
14768 // Clean up events and states
14769 this.bindings.off( this.eventNamespace );
14770 },
14771
14772 _destroy: $.noop,
14773
14774 widget: function() {
14775 return this.element;
14776 },
14777
14778 option: function( key, value ) {
14779 var options = key;
14780 var parts;
14781 var curOption;
14782 var i;
14783
14784 if ( arguments.length === 0 ) {
14785
14786 // Don't return a reference to the internal hash
14787 return $.widget.extend( {}, this.options );
14788 }
14789
14790 if ( typeof key === "string" ) {
14791
14792 // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
14793 options = {};
14794 parts = key.split( "." );
14795 key = parts.shift();
14796 if ( parts.length ) {
14797 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
14798 for ( i = 0; i < parts.length - 1; i++ ) {
14799 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
14800 curOption = curOption[ parts[ i ] ];
14801 }
14802 key = parts.pop();
14803 if ( arguments.length === 1 ) {
14804 return curOption[ key ] === undefined ? null : curOption[ key ];
14805 }
14806 curOption[ key ] = value;
14807 } else {
14808 if ( arguments.length === 1 ) {
14809 return this.options[ key ] === undefined ? null : this.options[ key ];
14810 }
14811 options[ key ] = value;
14812 }
14813 }
14814
14815 this._setOptions( options );
14816
14817 return this;
14818 },
14819
14820 _setOptions: function( options ) {
14821 var key;
14822
14823 for ( key in options ) {
14824 this._setOption( key, options[ key ] );
14825 }
14826
14827 return this;
14828 },
14829
14830 _setOption: function( key, value ) {
14831 if ( key === "classes" ) {
14832 this._setOptionClasses( value );
14833 }
14834
14835 this.options[ key ] = value;
14836
14837 if ( key === "disabled" ) {
14838 this._setOptionDisabled( value );
14839 }
14840
14841 return this;
14842 },
14843
14844 _setOptionClasses: function( value ) {
14845 var classKey, elements, currentElements;
14846
14847 for ( classKey in value ) {
14848 currentElements = this.classesElementLookup[ classKey ];
14849 if ( value[ classKey ] === this.options.classes[ classKey ] ||
14850 !currentElements ||
14851 !currentElements.length ) {
14852 continue;
14853 }
14854
14855 // We are doing this to create a new jQuery object because the _removeClass() call
14856 // on the next line is going to destroy the reference to the current elements being
14857 // tracked. We need to save a copy of this collection so that we can add the new classes
14858 // below.
14859 elements = $( currentElements.get() );
14860 this._removeClass( currentElements, classKey );
14861
14862 // We don't use _addClass() here, because that uses this.options.classes
14863 // for generating the string of classes. We want to use the value passed in from
14864 // _setOption(), this is the new value of the classes option which was passed to
14865 // _setOption(). We pass this value directly to _classes().
14866 elements.addClass( this._classes( {
14867 element: elements,
14868 keys: classKey,
14869 classes: value,
14870 add: true
14871 } ) );
14872 }
14873 },
14874
14875 _setOptionDisabled: function( value ) {
14876 this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
14877
14878 // If the widget is becoming disabled, then nothing is interactive
14879 if ( value ) {
14880 this._removeClass( this.hoverable, null, "ui-state-hover" );
14881 this._removeClass( this.focusable, null, "ui-state-focus" );
14882 }
14883 },
14884
14885 enable: function() {
14886 return this._setOptions( { disabled: false } );
14887 },
14888
14889 disable: function() {
14890 return this._setOptions( { disabled: true } );
14891 },
14892
14893 _classes: function( options ) {
14894 var full = [];
14895 var that = this;
14896
14897 options = $.extend( {
14898 element: this.element,
14899 classes: this.options.classes || {}
14900 }, options );
14901
14902 function bindRemoveEvent() {
14903 var nodesToBind = [];
14904
14905 options.element.each( function( _, element ) {
14906 var isTracked = $.map( that.classesElementLookup, function( elements ) {
14907 return elements;
14908 } )
14909 .some( function( elements ) {
14910 return elements.is( element );
14911 } );
14912
14913 if ( !isTracked ) {
14914 nodesToBind.push( element );
14915 }
14916 } );
14917
14918 that._on( $( nodesToBind ), {
14919 remove: "_untrackClassesElement"
14920 } );
14921 }
14922
14923 function processClassString( classes, checkOption ) {
14924 var current, i;
14925 for ( i = 0; i < classes.length; i++ ) {
14926 current = that.classesElementLookup[ classes[ i ] ] || $();
14927 if ( options.add ) {
14928 bindRemoveEvent();
14929 current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) );
14930 } else {
14931 current = $( current.not( options.element ).get() );
14932 }
14933 that.classesElementLookup[ classes[ i ] ] = current;
14934 full.push( classes[ i ] );
14935 if ( checkOption && options.classes[ classes[ i ] ] ) {
14936 full.push( options.classes[ classes[ i ] ] );
14937 }
14938 }
14939 }
14940
14941 if ( options.keys ) {
14942 processClassString( options.keys.match( /\S+/g ) || [], true );
14943 }
14944 if ( options.extra ) {
14945 processClassString( options.extra.match( /\S+/g ) || [] );
14946 }
14947
14948 return full.join( " " );
14949 },
14950
14951 _untrackClassesElement: function( event ) {
14952 var that = this;
14953 $.each( that.classesElementLookup, function( key, value ) {
14954 if ( $.inArray( event.target, value ) !== -1 ) {
14955 that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
14956 }
14957 } );
14958
14959 this._off( $( event.target ) );
14960 },
14961
14962 _removeClass: function( element, keys, extra ) {
14963 return this._toggleClass( element, keys, extra, false );
14964 },
14965
14966 _addClass: function( element, keys, extra ) {
14967 return this._toggleClass( element, keys, extra, true );
14968 },
14969
14970 _toggleClass: function( element, keys, extra, add ) {
14971 add = ( typeof add === "boolean" ) ? add : extra;
14972 var shift = ( typeof element === "string" || element === null ),
14973 options = {
14974 extra: shift ? keys : extra,
14975 keys: shift ? element : keys,
14976 element: shift ? this.element : element,
14977 add: add
14978 };
14979 options.element.toggleClass( this._classes( options ), add );
14980 return this;
14981 },
14982
14983 _on: function( suppressDisabledCheck, element, handlers ) {
14984 var delegateElement;
14985 var instance = this;
14986
14987 // No suppressDisabledCheck flag, shuffle arguments
14988 if ( typeof suppressDisabledCheck !== "boolean" ) {
14989 handlers = element;
14990 element = suppressDisabledCheck;
14991 suppressDisabledCheck = false;
14992 }
14993
14994 // No element argument, shuffle and use this.element
14995 if ( !handlers ) {
14996 handlers = element;
14997 element = this.element;
14998 delegateElement = this.widget();
14999 } else {
15000 element = delegateElement = $( element );
15001 this.bindings = this.bindings.add( element );
15002 }
15003
15004 $.each( handlers, function( event, handler ) {
15005 function handlerProxy() {
15006
15007 // Allow widgets to customize the disabled handling
15008 // - disabled as an array instead of boolean
15009 // - disabled class as method for disabling individual parts
15010 if ( !suppressDisabledCheck &&
15011 ( instance.options.disabled === true ||
15012 $( this ).hasClass( "ui-state-disabled" ) ) ) {
15013 return;
15014 }
15015 return ( typeof handler === "string" ? instance[ handler ] : handler )
15016 .apply( instance, arguments );
15017 }
15018
15019 // Copy the guid so direct unbinding works
15020 if ( typeof handler !== "string" ) {
15021 handlerProxy.guid = handler.guid =
15022 handler.guid || handlerProxy.guid || $.guid++;
15023 }
15024
15025 var match = event.match( /^([\w:-]*)\s*(.*)$/ );
15026 var eventName = match[ 1 ] + instance.eventNamespace;
15027 var selector = match[ 2 ];
15028
15029 if ( selector ) {
15030 delegateElement.on( eventName, selector, handlerProxy );
15031 } else {
15032 element.on( eventName, handlerProxy );
15033 }
15034 } );
15035 },
15036
15037 _off: function( element, eventName ) {
15038 eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
15039 this.eventNamespace;
15040 element.off( eventName );
15041
15042 // Clear the stack to avoid memory leaks (#10056)
15043 this.bindings = $( this.bindings.not( element ).get() );
15044 this.focusable = $( this.focusable.not( element ).get() );
15045 this.hoverable = $( this.hoverable.not( element ).get() );
15046 },
15047
15048 _delay: function( handler, delay ) {
15049 function handlerProxy() {
15050 return ( typeof handler === "string" ? instance[ handler ] : handler )
15051 .apply( instance, arguments );
15052 }
15053 var instance = this;
15054 return setTimeout( handlerProxy, delay || 0 );
15055 },
15056
15057 _hoverable: function( element ) {
15058 this.hoverable = this.hoverable.add( element );
15059 this._on( element, {
15060 mouseenter: function( event ) {
15061 this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
15062 },
15063 mouseleave: function( event ) {
15064 this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
15065 }
15066 } );
15067 },
15068
15069 _focusable: function( element ) {
15070 this.focusable = this.focusable.add( element );
15071 this._on( element, {
15072 focusin: function( event ) {
15073 this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
15074 },
15075 focusout: function( event ) {
15076 this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
15077 }
15078 } );
15079 },
15080
15081 _trigger: function( type, event, data ) {
15082 var prop, orig;
15083 var callback = this.options[ type ];
15084
15085 data = data || {};
15086 event = $.Event( event );
15087 event.type = ( type === this.widgetEventPrefix ?
15088 type :
15089 this.widgetEventPrefix + type ).toLowerCase();
15090
15091 // The original event may come from any element
15092 // so we need to reset the target on the new event
15093 event.target = this.element[ 0 ];
15094
15095 // Copy original event properties over to the new event
15096 orig = event.originalEvent;
15097 if ( orig ) {
15098 for ( prop in orig ) {
15099 if ( !( prop in event ) ) {
15100 event[ prop ] = orig[ prop ];
15101 }
15102 }
15103 }
15104
15105 this.element.trigger( event, data );
15106 return !( typeof callback === "function" &&
15107 callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
15108 event.isDefaultPrevented() );
15109 }
15110};
15111
15112$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
15113 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
15114 if ( typeof options === "string" ) {
15115 options = { effect: options };
15116 }
15117
15118 var hasOptions;
15119 var effectName = !options ?
15120 method :
15121 options === true || typeof options === "number" ?
15122 defaultEffect :
15123 options.effect || defaultEffect;
15124
15125 options = options || {};
15126 if ( typeof options === "number" ) {
15127 options = { duration: options };
15128 } else if ( options === true ) {
15129 options = {};
15130 }
15131
15132 hasOptions = !$.isEmptyObject( options );
15133 options.complete = callback;
15134
15135 if ( options.delay ) {
15136 element.delay( options.delay );
15137 }
15138
15139 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
15140 element[ method ]( options );
15141 } else if ( effectName !== method && element[ effectName ] ) {
15142 element[ effectName ]( options.duration, options.easing, callback );
15143 } else {
15144 element.queue( function( next ) {
15145 $( this )[ method ]();
15146 if ( callback ) {
15147 callback.call( element[ 0 ] );
15148 }
15149 next();
15150 } );
15151 }
15152 };
15153} );
15154
15155return $.widget;
15156
15157} );
15158
15159
15160
15161/*!
15162 * jQuery UI Effects Blind 1.14.1
15163 * https://jqueryui.com
15164 *
15165 * Copyright OpenJS Foundation and other contributors
15166 * Released under the MIT license.
15167 * https://jquery.org/license
15168 */
15169
15170//>>label: Blind Effect
15171//>>group: Effects
15172//>>description: Blinds the element.
15173//>>docs: https://api.jqueryui.com/blind-effect/
15174//>>demos: https://jqueryui.com/effect/
15175
15176( function( factory ) {
15177 "use strict";
15178
15179 if ( typeof define === "function" && define.amd ) {
15180
15181 // AMD. Register as an anonymous module.
15182 define( [
15183 "jquery",
15184 "../version",
15185 "../effect"
15186 ], factory );
15187 } else {
15188
15189 // Browser globals
15190 factory( jQuery );
15191 }
15192} )( function( $ ) {
15193"use strict";
15194
15195return $.effects.define( "blind", "hide", function( options, done ) {
15196 var map = {
15197 up: [ "bottom", "top" ],
15198 vertical: [ "bottom", "top" ],
15199 down: [ "top", "bottom" ],
15200 left: [ "right", "left" ],
15201 horizontal: [ "right", "left" ],
15202 right: [ "left", "right" ]
15203 },
15204 element = $( this ),
15205 direction = options.direction || "up",
15206 start = element.cssClip(),
15207 animate = { clip: $.extend( {}, start ) },
15208 placeholder = $.effects.createPlaceholder( element );
15209
15210 animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];
15211
15212 if ( options.mode === "show" ) {
15213 element.cssClip( animate.clip );
15214 if ( placeholder ) {
15215 placeholder.css( $.effects.clipToBox( animate ) );
15216 }
15217
15218 animate.clip = start;
15219 }
15220
15221 if ( placeholder ) {
15222 placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );
15223 }
15224
15225 element.animate( animate, {
15226 queue: false,
15227 duration: options.duration,
15228 easing: options.easing,
15229 complete: done
15230 } );
15231} );
15232
15233} );
15234
15235
15236
15237/*!
15238 * jQuery UI Effects Bounce 1.14.1
15239 * https://jqueryui.com
15240 *
15241 * Copyright OpenJS Foundation and other contributors
15242 * Released under the MIT license.
15243 * https://jquery.org/license
15244 */
15245
15246//>>label: Bounce Effect
15247//>>group: Effects
15248//>>description: Bounces an element horizontally or vertically n times.
15249//>>docs: https://api.jqueryui.com/bounce-effect/
15250//>>demos: https://jqueryui.com/effect/
15251
15252( function( factory ) {
15253 "use strict";
15254
15255 if ( typeof define === "function" && define.amd ) {
15256
15257 // AMD. Register as an anonymous module.
15258 define( [
15259 "jquery",
15260 "../version",
15261 "../effect"
15262 ], factory );
15263 } else {
15264
15265 // Browser globals
15266 factory( jQuery );
15267 }
15268} )( function( $ ) {
15269"use strict";
15270
15271return $.effects.define( "bounce", function( options, done ) {
15272 var upAnim, downAnim, refValue,
15273 element = $( this ),
15274
15275 // Defaults:
15276 mode = options.mode,
15277 hide = mode === "hide",
15278 show = mode === "show",
15279 direction = options.direction || "up",
15280 distance = options.distance,
15281 times = options.times || 5,
15282
15283 // Number of internal animations
15284 anims = times * 2 + ( show || hide ? 1 : 0 ),
15285 speed = options.duration / anims,
15286 easing = options.easing,
15287
15288 // Utility:
15289 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
15290 motion = ( direction === "up" || direction === "left" ),
15291 i = 0,
15292
15293 queuelen = element.queue().length;
15294
15295 $.effects.createPlaceholder( element );
15296
15297 refValue = element.css( ref );
15298
15299 // Default distance for the BIGGEST bounce is the outer Distance / 3
15300 if ( !distance ) {
15301 distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
15302 }
15303
15304 if ( show ) {
15305 downAnim = { opacity: 1 };
15306 downAnim[ ref ] = refValue;
15307
15308 // If we are showing, force opacity 0 and set the initial position
15309 // then do the "first" animation
15310 element
15311 .css( "opacity", 0 )
15312 .css( ref, motion ? -distance * 2 : distance * 2 )
15313 .animate( downAnim, speed, easing );
15314 }
15315
15316 // Start at the smallest distance if we are hiding
15317 if ( hide ) {
15318 distance = distance / Math.pow( 2, times - 1 );
15319 }
15320
15321 downAnim = {};
15322 downAnim[ ref ] = refValue;
15323
15324 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
15325 for ( ; i < times; i++ ) {
15326 upAnim = {};
15327 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
15328
15329 element
15330 .animate( upAnim, speed, easing )
15331 .animate( downAnim, speed, easing );
15332
15333 distance = hide ? distance * 2 : distance / 2;
15334 }
15335
15336 // Last Bounce when Hiding
15337 if ( hide ) {
15338 upAnim = { opacity: 0 };
15339 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
15340
15341 element.animate( upAnim, speed, easing );
15342 }
15343
15344 element.queue( done );
15345
15346 $.effects.unshift( element, queuelen, anims + 1 );
15347} );
15348
15349} );
15350
15351
15352
15353/*!
15354 * jQuery UI Effects Clip 1.14.1
15355 * https://jqueryui.com
15356 *
15357 * Copyright OpenJS Foundation and other contributors
15358 * Released under the MIT license.
15359 * https://jquery.org/license
15360 */
15361
15362//>>label: Clip Effect
15363//>>group: Effects
15364//>>description: Clips the element on and off like an old TV.
15365//>>docs: https://api.jqueryui.com/clip-effect/
15366//>>demos: https://jqueryui.com/effect/
15367
15368( function( factory ) {
15369 "use strict";
15370
15371 if ( typeof define === "function" && define.amd ) {
15372
15373 // AMD. Register as an anonymous module.
15374 define( [
15375 "jquery",
15376 "../version",
15377 "../effect"
15378 ], factory );
15379 } else {
15380
15381 // Browser globals
15382 factory( jQuery );
15383 }
15384} )( function( $ ) {
15385"use strict";
15386
15387return $.effects.define( "clip", "hide", function( options, done ) {
15388 var start,
15389 animate = {},
15390 element = $( this ),
15391 direction = options.direction || "vertical",
15392 both = direction === "both",
15393 horizontal = both || direction === "horizontal",
15394 vertical = both || direction === "vertical";
15395
15396 start = element.cssClip();
15397 animate.clip = {
15398 top: vertical ? ( start.bottom - start.top ) / 2 : start.top,
15399 right: horizontal ? ( start.right - start.left ) / 2 : start.right,
15400 bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,
15401 left: horizontal ? ( start.right - start.left ) / 2 : start.left
15402 };
15403
15404 $.effects.createPlaceholder( element );
15405
15406 if ( options.mode === "show" ) {
15407 element.cssClip( animate.clip );
15408 animate.clip = start;
15409 }
15410
15411 element.animate( animate, {
15412 queue: false,
15413 duration: options.duration,
15414 easing: options.easing,
15415 complete: done
15416 } );
15417
15418} );
15419
15420} );
15421
15422
15423
15424/*!
15425 * jQuery UI Effects Drop 1.14.1
15426 * https://jqueryui.com
15427 *
15428 * Copyright OpenJS Foundation and other contributors
15429 * Released under the MIT license.
15430 * https://jquery.org/license
15431 */
15432
15433//>>label: Drop Effect
15434//>>group: Effects
15435//>>description: Moves an element in one direction and hides it at the same time.
15436//>>docs: https://api.jqueryui.com/drop-effect/
15437//>>demos: https://jqueryui.com/effect/
15438
15439( function( factory ) {
15440 "use strict";
15441
15442 if ( typeof define === "function" && define.amd ) {
15443
15444 // AMD. Register as an anonymous module.
15445 define( [
15446 "jquery",
15447 "../version",
15448 "../effect"
15449 ], factory );
15450 } else {
15451
15452 // Browser globals
15453 factory( jQuery );
15454 }
15455} )( function( $ ) {
15456"use strict";
15457
15458return $.effects.define( "drop", "hide", function( options, done ) {
15459
15460 var distance,
15461 element = $( this ),
15462 mode = options.mode,
15463 show = mode === "show",
15464 direction = options.direction || "left",
15465 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
15466 motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=",
15467 oppositeMotion = ( motion === "+=" ) ? "-=" : "+=",
15468 animation = {
15469 opacity: 0
15470 };
15471
15472 $.effects.createPlaceholder( element );
15473
15474 distance = options.distance ||
15475 element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
15476
15477 animation[ ref ] = motion + distance;
15478
15479 if ( show ) {
15480 element.css( animation );
15481
15482 animation[ ref ] = oppositeMotion + distance;
15483 animation.opacity = 1;
15484 }
15485
15486 // Animate
15487 element.animate( animation, {
15488 queue: false,
15489 duration: options.duration,
15490 easing: options.easing,
15491 complete: done
15492 } );
15493} );
15494
15495} );
15496
15497
15498
15499/*!
15500 * jQuery UI Effects Explode 1.14.1
15501 * https://jqueryui.com
15502 *
15503 * Copyright OpenJS Foundation and other contributors
15504 * Released under the MIT license.
15505 * https://jquery.org/license
15506 */
15507
15508//>>label: Explode Effect
15509//>>group: Effects
15510/* eslint-disable max-len */
15511//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness.
15512/* eslint-enable max-len */
15513//>>docs: https://api.jqueryui.com/explode-effect/
15514//>>demos: https://jqueryui.com/effect/
15515
15516( function( factory ) {
15517 "use strict";
15518
15519 if ( typeof define === "function" && define.amd ) {
15520
15521 // AMD. Register as an anonymous module.
15522 define( [
15523 "jquery",
15524 "../version",
15525 "../effect"
15526 ], factory );
15527 } else {
15528
15529 // Browser globals
15530 factory( jQuery );
15531 }
15532} )( function( $ ) {
15533"use strict";
15534
15535return $.effects.define( "explode", "hide", function( options, done ) {
15536
15537 var i, j, left, top, mx, my,
15538 rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,
15539 cells = rows,
15540 element = $( this ),
15541 mode = options.mode,
15542 show = mode === "show",
15543
15544 // Show and then visibility:hidden the element before calculating offset
15545 offset = element.show().css( "visibility", "hidden" ).offset(),
15546
15547 // Width and height of a piece
15548 width = Math.ceil( element.outerWidth() / cells ),
15549 height = Math.ceil( element.outerHeight() / rows ),
15550 pieces = [];
15551
15552 // Children animate complete:
15553 function childComplete() {
15554 pieces.push( this );
15555 if ( pieces.length === rows * cells ) {
15556 animComplete();
15557 }
15558 }
15559
15560 // Clone the element for each row and cell.
15561 for ( i = 0; i < rows; i++ ) { // ===>
15562 top = offset.top + i * height;
15563 my = i - ( rows - 1 ) / 2;
15564
15565 for ( j = 0; j < cells; j++ ) { // |||
15566 left = offset.left + j * width;
15567 mx = j - ( cells - 1 ) / 2;
15568
15569 // Create a clone of the now hidden main element that will be absolute positioned
15570 // within a wrapper div off the -left and -top equal to size of our pieces
15571 element
15572 .clone()
15573 .appendTo( "body" )
15574 .wrap( "<div></div>" )
15575 .css( {
15576 position: "absolute",
15577 visibility: "visible",
15578 left: -j * width,
15579 top: -i * height
15580 } )
15581
15582 // Select the wrapper - make it overflow: hidden and absolute positioned based on
15583 // where the original was located +left and +top equal to the size of pieces
15584 .parent()
15585 .addClass( "ui-effects-explode" )
15586 .css( {
15587 position: "absolute",
15588 overflow: "hidden",
15589 width: width,
15590 height: height,
15591 left: left + ( show ? mx * width : 0 ),
15592 top: top + ( show ? my * height : 0 ),
15593 opacity: show ? 0 : 1
15594 } )
15595 .animate( {
15596 left: left + ( show ? 0 : mx * width ),
15597 top: top + ( show ? 0 : my * height ),
15598 opacity: show ? 1 : 0
15599 }, options.duration || 500, options.easing, childComplete );
15600 }
15601 }
15602
15603 function animComplete() {
15604 element.css( {
15605 visibility: "visible"
15606 } );
15607 $( pieces ).remove();
15608 done();
15609 }
15610} );
15611
15612} );
15613
15614
15615
15616/*!
15617 * jQuery UI Effects Fade 1.14.1
15618 * https://jqueryui.com
15619 *
15620 * Copyright OpenJS Foundation and other contributors
15621 * Released under the MIT license.
15622 * https://jquery.org/license
15623 */
15624
15625//>>label: Fade Effect
15626//>>group: Effects
15627//>>description: Fades the element.
15628//>>docs: https://api.jqueryui.com/fade-effect/
15629//>>demos: https://jqueryui.com/effect/
15630
15631( function( factory ) {
15632 "use strict";
15633
15634 if ( typeof define === "function" && define.amd ) {
15635
15636 // AMD. Register as an anonymous module.
15637 define( [
15638 "jquery",
15639 "../version",
15640 "../effect"
15641 ], factory );
15642 } else {
15643
15644 // Browser globals
15645 factory( jQuery );
15646 }
15647} )( function( $ ) {
15648"use strict";
15649
15650return $.effects.define( "fade", "toggle", function( options, done ) {
15651 var show = options.mode === "show";
15652
15653 $( this )
15654 .css( "opacity", show ? 0 : 1 )
15655 .animate( {
15656 opacity: show ? 1 : 0
15657 }, {
15658 queue: false,
15659 duration: options.duration,
15660 easing: options.easing,
15661 complete: done
15662 } );
15663} );
15664
15665} );
15666
15667
15668
15669/*!
15670 * jQuery UI Effects Fold 1.14.1
15671 * https://jqueryui.com
15672 *
15673 * Copyright OpenJS Foundation and other contributors
15674 * Released under the MIT license.
15675 * https://jquery.org/license
15676 */
15677
15678//>>label: Fold Effect
15679//>>group: Effects
15680//>>description: Folds an element first horizontally and then vertically.
15681//>>docs: https://api.jqueryui.com/fold-effect/
15682//>>demos: https://jqueryui.com/effect/
15683
15684( function( factory ) {
15685 "use strict";
15686
15687 if ( typeof define === "function" && define.amd ) {
15688
15689 // AMD. Register as an anonymous module.
15690 define( [
15691 "jquery",
15692 "../version",
15693 "../effect"
15694 ], factory );
15695 } else {
15696
15697 // Browser globals
15698 factory( jQuery );
15699 }
15700} )( function( $ ) {
15701"use strict";
15702
15703return $.effects.define( "fold", "hide", function( options, done ) {
15704
15705 // Create element
15706 var element = $( this ),
15707 mode = options.mode,
15708 show = mode === "show",
15709 hide = mode === "hide",
15710 size = options.size || 15,
15711 percent = /([0-9]+)%/.exec( size ),
15712 horizFirst = !!options.horizFirst,
15713 ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ],
15714 duration = options.duration / 2,
15715
15716 placeholder = $.effects.createPlaceholder( element ),
15717
15718 start = element.cssClip(),
15719 animation1 = { clip: $.extend( {}, start ) },
15720 animation2 = { clip: $.extend( {}, start ) },
15721
15722 distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],
15723
15724 queuelen = element.queue().length;
15725
15726 if ( percent ) {
15727 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
15728 }
15729 animation1.clip[ ref[ 0 ] ] = size;
15730 animation2.clip[ ref[ 0 ] ] = size;
15731 animation2.clip[ ref[ 1 ] ] = 0;
15732
15733 if ( show ) {
15734 element.cssClip( animation2.clip );
15735 if ( placeholder ) {
15736 placeholder.css( $.effects.clipToBox( animation2 ) );
15737 }
15738
15739 animation2.clip = start;
15740 }
15741
15742 // Animate
15743 element
15744 .queue( function( next ) {
15745 if ( placeholder ) {
15746 placeholder
15747 .animate( $.effects.clipToBox( animation1 ), duration, options.easing )
15748 .animate( $.effects.clipToBox( animation2 ), duration, options.easing );
15749 }
15750
15751 next();
15752 } )
15753 .animate( animation1, duration, options.easing )
15754 .animate( animation2, duration, options.easing )
15755 .queue( done );
15756
15757 $.effects.unshift( element, queuelen, 4 );
15758} );
15759
15760} );
15761
15762
15763
15764/*!
15765 * jQuery UI Effects Highlight 1.14.1
15766 * https://jqueryui.com
15767 *
15768 * Copyright OpenJS Foundation and other contributors
15769 * Released under the MIT license.
15770 * https://jquery.org/license
15771 */
15772
15773//>>label: Highlight Effect
15774//>>group: Effects
15775//>>description: Highlights the background of an element in a defined color for a custom duration.
15776//>>docs: https://api.jqueryui.com/highlight-effect/
15777//>>demos: https://jqueryui.com/effect/
15778
15779( function( factory ) {
15780 "use strict";
15781
15782 if ( typeof define === "function" && define.amd ) {
15783
15784 // AMD. Register as an anonymous module.
15785 define( [
15786 "jquery",
15787 "../version",
15788 "../effect"
15789 ], factory );
15790 } else {
15791
15792 // Browser globals
15793 factory( jQuery );
15794 }
15795} )( function( $ ) {
15796"use strict";
15797
15798return $.effects.define( "highlight", "show", function( options, done ) {
15799 var element = $( this ),
15800 animation = {
15801 backgroundColor: element.css( "backgroundColor" )
15802 };
15803
15804 if ( options.mode === "hide" ) {
15805 animation.opacity = 0;
15806 }
15807
15808 $.effects.saveStyle( element );
15809
15810 element
15811 .css( {
15812 backgroundImage: "none",
15813 backgroundColor: options.color || "#ffff99"
15814 } )
15815 .animate( animation, {
15816 queue: false,
15817 duration: options.duration,
15818 easing: options.easing,
15819 complete: done
15820 } );
15821} );
15822
15823} );
15824
15825
15826
15827/*!
15828 * jQuery UI Effects Size 1.14.1
15829 * https://jqueryui.com
15830 *
15831 * Copyright OpenJS Foundation and other contributors
15832 * Released under the MIT license.
15833 * https://jquery.org/license
15834 */
15835
15836//>>label: Size Effect
15837//>>group: Effects
15838//>>description: Resize an element to a specified width and height.
15839//>>docs: https://api.jqueryui.com/size-effect/
15840//>>demos: https://jqueryui.com/effect/
15841
15842( function( factory ) {
15843 "use strict";
15844
15845 if ( typeof define === "function" && define.amd ) {
15846
15847 // AMD. Register as an anonymous module.
15848 define( [
15849 "jquery",
15850 "../version",
15851 "../effect"
15852 ], factory );
15853 } else {
15854
15855 // Browser globals
15856 factory( jQuery );
15857 }
15858} )( function( $ ) {
15859"use strict";
15860
15861return $.effects.define( "size", function( options, done ) {
15862
15863 // Create element
15864 var baseline, factor, temp,
15865 element = $( this ),
15866
15867 // Copy for children
15868 cProps = [ "fontSize" ],
15869 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
15870 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
15871
15872 // Set options
15873 mode = options.mode,
15874 restore = mode !== "effect",
15875 scale = options.scale || "both",
15876 origin = options.origin || [ "middle", "center" ],
15877 position = element.css( "position" ),
15878 pos = element.position(),
15879 original = $.effects.scaledDimensions( element ),
15880 from = options.from || original,
15881 to = options.to || $.effects.scaledDimensions( element, 0 );
15882
15883 $.effects.createPlaceholder( element );
15884
15885 if ( mode === "show" ) {
15886 temp = from;
15887 from = to;
15888 to = temp;
15889 }
15890
15891 // Set scaling factor
15892 factor = {
15893 from: {
15894 y: from.height / original.height,
15895 x: from.width / original.width
15896 },
15897 to: {
15898 y: to.height / original.height,
15899 x: to.width / original.width
15900 }
15901 };
15902
15903 // Scale the css box
15904 if ( scale === "box" || scale === "both" ) {
15905
15906 // Vertical props scaling
15907 if ( factor.from.y !== factor.to.y ) {
15908 from = $.effects.setTransition( element, vProps, factor.from.y, from );
15909 to = $.effects.setTransition( element, vProps, factor.to.y, to );
15910 }
15911
15912 // Horizontal props scaling
15913 if ( factor.from.x !== factor.to.x ) {
15914 from = $.effects.setTransition( element, hProps, factor.from.x, from );
15915 to = $.effects.setTransition( element, hProps, factor.to.x, to );
15916 }
15917 }
15918
15919 // Scale the content
15920 if ( scale === "content" || scale === "both" ) {
15921
15922 // Vertical props scaling
15923 if ( factor.from.y !== factor.to.y ) {
15924 from = $.effects.setTransition( element, cProps, factor.from.y, from );
15925 to = $.effects.setTransition( element, cProps, factor.to.y, to );
15926 }
15927 }
15928
15929 // Adjust the position properties based on the provided origin points
15930 if ( origin ) {
15931 baseline = $.effects.getBaseline( origin, original );
15932 from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;
15933 from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;
15934 to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;
15935 to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;
15936 }
15937 delete from.outerHeight;
15938 delete from.outerWidth;
15939 element.css( from );
15940
15941 // Animate the children if desired
15942 if ( scale === "content" || scale === "both" ) {
15943
15944 vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps );
15945 hProps = hProps.concat( [ "marginLeft", "marginRight" ] );
15946
15947 // Only animate children with width attributes specified
15948 // TODO: is this right? should we include anything with css width specified as well
15949 element.find( "*[width]" ).each( function() {
15950 var child = $( this ),
15951 childOriginal = $.effects.scaledDimensions( child ),
15952 childFrom = {
15953 height: childOriginal.height * factor.from.y,
15954 width: childOriginal.width * factor.from.x,
15955 outerHeight: childOriginal.outerHeight * factor.from.y,
15956 outerWidth: childOriginal.outerWidth * factor.from.x
15957 },
15958 childTo = {
15959 height: childOriginal.height * factor.to.y,
15960 width: childOriginal.width * factor.to.x,
15961 outerHeight: childOriginal.height * factor.to.y,
15962 outerWidth: childOriginal.width * factor.to.x
15963 };
15964
15965 // Vertical props scaling
15966 if ( factor.from.y !== factor.to.y ) {
15967 childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );
15968 childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );
15969 }
15970
15971 // Horizontal props scaling
15972 if ( factor.from.x !== factor.to.x ) {
15973 childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );
15974 childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );
15975 }
15976
15977 if ( restore ) {
15978 $.effects.saveStyle( child );
15979 }
15980
15981 // Animate children
15982 child.css( childFrom );
15983 child.animate( childTo, options.duration, options.easing, function() {
15984
15985 // Restore children
15986 if ( restore ) {
15987 $.effects.restoreStyle( child );
15988 }
15989 } );
15990 } );
15991 }
15992
15993 // Animate
15994 element.animate( to, {
15995 queue: false,
15996 duration: options.duration,
15997 easing: options.easing,
15998 complete: function() {
15999
16000 var offset = element.offset();
16001
16002 if ( to.opacity === 0 ) {
16003 element.css( "opacity", from.opacity );
16004 }
16005
16006 if ( !restore ) {
16007 element
16008 .css( "position", position === "static" ? "relative" : position )
16009 .offset( offset );
16010
16011 // Need to save style here so that automatic style restoration
16012 // doesn't restore to the original styles from before the animation.
16013 $.effects.saveStyle( element );
16014 }
16015
16016 done();
16017 }
16018 } );
16019
16020} );
16021
16022} );
16023
16024
16025
16026
16027/*!
16028 * jQuery UI Effects Scale 1.14.1
16029 * https://jqueryui.com
16030 *
16031 * Copyright OpenJS Foundation and other contributors
16032 * Released under the MIT license.
16033 * https://jquery.org/license
16034 */
16035
16036//>>label: Scale Effect
16037//>>group: Effects
16038//>>description: Grows or shrinks an element and its content.
16039//>>docs: https://api.jqueryui.com/scale-effect/
16040//>>demos: https://jqueryui.com/effect/
16041
16042( function( factory ) {
16043 "use strict";
16044
16045 if ( typeof define === "function" && define.amd ) {
16046
16047 // AMD. Register as an anonymous module.
16048 define( [
16049 "jquery",
16050 "../version",
16051 "../effect",
16052 "./effect-size"
16053 ], factory );
16054 } else {
16055
16056 // Browser globals
16057 factory( jQuery );
16058 }
16059} )( function( $ ) {
16060"use strict";
16061
16062return $.effects.define( "scale", function( options, done ) {
16063
16064 // Create element
16065 var el = $( this ),
16066 mode = options.mode,
16067 percent = parseInt( options.percent, 10 ) ||
16068 ( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ),
16069
16070 newOptions = $.extend( true, {
16071 from: $.effects.scaledDimensions( el ),
16072 to: $.effects.scaledDimensions( el, percent, options.direction || "both" ),
16073 origin: options.origin || [ "middle", "center" ]
16074 }, options );
16075
16076 // Fade option to support puff
16077 if ( options.fade ) {
16078 newOptions.from.opacity = 1;
16079 newOptions.to.opacity = 0;
16080 }
16081
16082 $.effects.effect.size.call( this, newOptions, done );
16083} );
16084
16085} );
16086
16087
16088
16089
16090/*!
16091 * jQuery UI Effects Puff 1.14.1
16092 * https://jqueryui.com
16093 *
16094 * Copyright OpenJS Foundation and other contributors
16095 * Released under the MIT license.
16096 * https://jquery.org/license
16097 */
16098
16099//>>label: Puff Effect
16100//>>group: Effects
16101//>>description: Creates a puff effect by scaling the element up and hiding it at the same time.
16102//>>docs: https://api.jqueryui.com/puff-effect/
16103//>>demos: https://jqueryui.com/effect/
16104
16105( function( factory ) {
16106 "use strict";
16107
16108 if ( typeof define === "function" && define.amd ) {
16109
16110 // AMD. Register as an anonymous module.
16111 define( [
16112 "jquery",
16113 "../version",
16114 "../effect",
16115 "./effect-scale"
16116 ], factory );
16117 } else {
16118
16119 // Browser globals
16120 factory( jQuery );
16121 }
16122} )( function( $ ) {
16123"use strict";
16124
16125return $.effects.define( "puff", "hide", function( options, done ) {
16126 var newOptions = $.extend( true, {}, options, {
16127 fade: true,
16128 percent: parseInt( options.percent, 10 ) || 150
16129 } );
16130
16131 $.effects.effect.scale.call( this, newOptions, done );
16132} );
16133
16134} );
16135
16136
16137
16138/*!
16139 * jQuery UI Effects Pulsate 1.14.1
16140 * https://jqueryui.com
16141 *
16142 * Copyright OpenJS Foundation and other contributors
16143 * Released under the MIT license.
16144 * https://jquery.org/license
16145 */
16146
16147//>>label: Pulsate Effect
16148//>>group: Effects
16149//>>description: Pulsates an element n times by changing the opacity to zero and back.
16150//>>docs: https://api.jqueryui.com/pulsate-effect/
16151//>>demos: https://jqueryui.com/effect/
16152
16153( function( factory ) {
16154 "use strict";
16155
16156 if ( typeof define === "function" && define.amd ) {
16157
16158 // AMD. Register as an anonymous module.
16159 define( [
16160 "jquery",
16161 "../version",
16162 "../effect"
16163 ], factory );
16164 } else {
16165
16166 // Browser globals
16167 factory( jQuery );
16168 }
16169} )( function( $ ) {
16170"use strict";
16171
16172return $.effects.define( "pulsate", "show", function( options, done ) {
16173 var element = $( this ),
16174 mode = options.mode,
16175 show = mode === "show",
16176 hide = mode === "hide",
16177 showhide = show || hide,
16178
16179 // Showing or hiding leaves off the "last" animation
16180 anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
16181 duration = options.duration / anims,
16182 animateTo = 0,
16183 i = 1,
16184 queuelen = element.queue().length;
16185
16186 if ( show || !element.is( ":visible" ) ) {
16187 element.css( "opacity", 0 ).show();
16188 animateTo = 1;
16189 }
16190
16191 // Anims - 1 opacity "toggles"
16192 for ( ; i < anims; i++ ) {
16193 element.animate( { opacity: animateTo }, duration, options.easing );
16194 animateTo = 1 - animateTo;
16195 }
16196
16197 element.animate( { opacity: animateTo }, duration, options.easing );
16198
16199 element.queue( done );
16200
16201 $.effects.unshift( element, queuelen, anims + 1 );
16202} );
16203
16204} );
16205
16206
16207
16208/*!
16209 * jQuery UI Effects Shake 1.14.1
16210 * https://jqueryui.com
16211 *
16212 * Copyright OpenJS Foundation and other contributors
16213 * Released under the MIT license.
16214 * https://jquery.org/license
16215 */
16216
16217//>>label: Shake Effect
16218//>>group: Effects
16219//>>description: Shakes an element horizontally or vertically n times.
16220//>>docs: https://api.jqueryui.com/shake-effect/
16221//>>demos: https://jqueryui.com/effect/
16222
16223( function( factory ) {
16224 "use strict";
16225
16226 if ( typeof define === "function" && define.amd ) {
16227
16228 // AMD. Register as an anonymous module.
16229 define( [
16230 "jquery",
16231 "../version",
16232 "../effect"
16233 ], factory );
16234 } else {
16235
16236 // Browser globals
16237 factory( jQuery );
16238 }
16239} )( function( $ ) {
16240"use strict";
16241
16242return $.effects.define( "shake", function( options, done ) {
16243
16244 var i = 1,
16245 element = $( this ),
16246 direction = options.direction || "left",
16247 distance = options.distance || 20,
16248 times = options.times || 3,
16249 anims = times * 2 + 1,
16250 speed = Math.round( options.duration / anims ),
16251 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
16252 positiveMotion = ( direction === "up" || direction === "left" ),
16253 animation = {},
16254 animation1 = {},
16255 animation2 = {},
16256
16257 queuelen = element.queue().length;
16258
16259 $.effects.createPlaceholder( element );
16260
16261 // Animation
16262 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
16263 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
16264 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
16265
16266 // Animate
16267 element.animate( animation, speed, options.easing );
16268
16269 // Shakes
16270 for ( ; i < times; i++ ) {
16271 element
16272 .animate( animation1, speed, options.easing )
16273 .animate( animation2, speed, options.easing );
16274 }
16275
16276 element
16277 .animate( animation1, speed, options.easing )
16278 .animate( animation, speed / 2, options.easing )
16279 .queue( done );
16280
16281 $.effects.unshift( element, queuelen, anims + 1 );
16282} );
16283
16284} );
16285
16286
16287
16288/*!
16289 * jQuery UI Effects Slide 1.14.1
16290 * https://jqueryui.com
16291 *
16292 * Copyright OpenJS Foundation and other contributors
16293 * Released under the MIT license.
16294 * https://jquery.org/license
16295 */
16296
16297//>>label: Slide Effect
16298//>>group: Effects
16299//>>description: Slides an element in and out of the viewport.
16300//>>docs: https://api.jqueryui.com/slide-effect/
16301//>>demos: https://jqueryui.com/effect/
16302
16303( function( factory ) {
16304 "use strict";
16305
16306 if ( typeof define === "function" && define.amd ) {
16307
16308 // AMD. Register as an anonymous module.
16309 define( [
16310 "jquery",
16311 "../version",
16312 "../effect"
16313 ], factory );
16314 } else {
16315
16316 // Browser globals
16317 factory( jQuery );
16318 }
16319} )( function( $ ) {
16320"use strict";
16321
16322return $.effects.define( "slide", "show", function( options, done ) {
16323 var startClip, startRef,
16324 element = $( this ),
16325 map = {
16326 up: [ "bottom", "top" ],
16327 down: [ "top", "bottom" ],
16328 left: [ "right", "left" ],
16329 right: [ "left", "right" ]
16330 },
16331 mode = options.mode,
16332 direction = options.direction || "left",
16333 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
16334 positiveMotion = ( direction === "up" || direction === "left" ),
16335 distance = options.distance ||
16336 element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ),
16337 animation = {};
16338
16339 $.effects.createPlaceholder( element );
16340
16341 startClip = element.cssClip();
16342 startRef = element.position()[ ref ];
16343
16344 // Define hide animation
16345 animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;
16346 animation.clip = element.cssClip();
16347 animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];
16348
16349 // Reverse the animation if we're showing
16350 if ( mode === "show" ) {
16351 element.cssClip( animation.clip );
16352 element.css( ref, animation[ ref ] );
16353 animation.clip = startClip;
16354 animation[ ref ] = startRef;
16355 }
16356
16357 // Actually animate
16358 element.animate( animation, {
16359 queue: false,
16360 duration: options.duration,
16361 easing: options.easing,
16362 complete: done
16363 } );
16364} );
16365
16366} );
16367
16368
16369
16370/*!
16371 * jQuery UI Effects Transfer 1.14.1
16372 * https://jqueryui.com
16373 *
16374 * Copyright OpenJS Foundation and other contributors
16375 * Released under the MIT license.
16376 * https://jquery.org/license
16377 */
16378
16379//>>label: Transfer Effect
16380//>>group: Effects
16381//>>description: Displays a transfer effect from one element to another.
16382//>>docs: https://api.jqueryui.com/transfer-effect/
16383//>>demos: https://jqueryui.com/effect/
16384
16385( function( factory ) {
16386 "use strict";
16387
16388 if ( typeof define === "function" && define.amd ) {
16389
16390 // AMD. Register as an anonymous module.
16391 define( [
16392 "jquery",
16393 "../version",
16394 "../effect"
16395 ], factory );
16396 } else {
16397
16398 // Browser globals
16399 factory( jQuery );
16400 }
16401} )( function( $ ) {
16402"use strict";
16403
16404var effect;
16405if ( $.uiBackCompat === true ) {
16406 effect = $.effects.define( "transfer", function( options, done ) {
16407 $( this ).transfer( options, done );
16408 } );
16409}
16410return effect;
16411
16412} );
16413
16414
16415
16416
16417
16418/*!
16419 * jQuery UI Accordion 1.14.1
16420 * https://jqueryui.com
16421 *
16422 * Copyright OpenJS Foundation and other contributors
16423 * Released under the MIT license.
16424 * https://jquery.org/license
16425 */
16426
16427//>>label: Accordion
16428//>>group: Widgets
16429/* eslint-disable max-len */
16430//>>description: Displays collapsible content panels for presenting information in a limited amount of space.
16431/* eslint-enable max-len */
16432//>>docs: https://api.jqueryui.com/accordion/
16433//>>demos: https://jqueryui.com/accordion/
16434//>>css.structure: ../../themes/base/core.css
16435//>>css.structure: ../../themes/base/accordion.css
16436//>>css.theme: ../../themes/base/theme.css
16437
16438( function( factory ) {
16439 "use strict";
16440
16441 if ( typeof define === "function" && define.amd ) {
16442
16443 // AMD. Register as an anonymous module.
16444 define( [
16445 "jquery",
16446 "../version",
16447 "../keycode",
16448 "../unique-id",
16449 "../widget"
16450 ], factory );
16451 } else {
16452
16453 // Browser globals
16454 factory( jQuery );
16455 }
16456} )( function( $ ) {
16457"use strict";
16458
16459return $.widget( "ui.accordion", {
16460 version: "1.14.1",
16461 options: {
16462 active: 0,
16463 animate: {},
16464 classes: {
16465 "ui-accordion-header": "ui-corner-top",
16466 "ui-accordion-header-collapsed": "ui-corner-all",
16467 "ui-accordion-content": "ui-corner-bottom"
16468 },
16469 collapsible: false,
16470 event: "click",
16471 header: function( elem ) {
16472 return elem
16473 .find( "> li > :first-child" )
16474 .add(
16475 elem.find( "> :not(li)" )
16476
16477 // Support: jQuery <3.5 only
16478 // We could use `.even()` but that's unavailable in older jQuery.
16479 .filter( function( i ) {
16480 return i % 2 === 0;
16481 } )
16482 );
16483 },
16484 heightStyle: "auto",
16485 icons: {
16486 activeHeader: "ui-icon-triangle-1-s",
16487 header: "ui-icon-triangle-1-e"
16488 },
16489
16490 // Callbacks
16491 activate: null,
16492 beforeActivate: null
16493 },
16494
16495 hideProps: {
16496 borderTopWidth: "hide",
16497 borderBottomWidth: "hide",
16498 paddingTop: "hide",
16499 paddingBottom: "hide",
16500 height: "hide"
16501 },
16502
16503 showProps: {
16504 borderTopWidth: "show",
16505 borderBottomWidth: "show",
16506 paddingTop: "show",
16507 paddingBottom: "show",
16508 height: "show"
16509 },
16510
16511 _create: function() {
16512 var options = this.options;
16513
16514 this.prevShow = this.prevHide = $();
16515 this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
16516 this.element.attr( "role", "tablist" );
16517
16518 // Don't allow collapsible: false and active: false / null
16519 if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
16520 options.active = 0;
16521 }
16522
16523 this._processPanels();
16524
16525 // handle negative values
16526 if ( options.active < 0 ) {
16527 options.active += this.headers.length;
16528 }
16529 this._refresh();
16530 },
16531
16532 _getCreateEventData: function() {
16533 return {
16534 header: this.active,
16535 panel: !this.active.length ? $() : this.active.next()
16536 };
16537 },
16538
16539 _createIcons: function() {
16540 var icon, children,
16541 icons = this.options.icons;
16542
16543 if ( icons ) {
16544 icon = $( "<span>" );
16545 this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
16546 icon.prependTo( this.headers );
16547 children = this.active.children( ".ui-accordion-header-icon" );
16548 this._removeClass( children, icons.header )
16549 ._addClass( children, null, icons.activeHeader )
16550 ._addClass( this.headers, "ui-accordion-icons" );
16551 }
16552 },
16553
16554 _destroyIcons: function() {
16555 this._removeClass( this.headers, "ui-accordion-icons" );
16556 this.headers.children( ".ui-accordion-header-icon" ).remove();
16557 },
16558
16559 _destroy: function() {
16560 var contents;
16561
16562 // Clean up main element
16563 this.element.removeAttr( "role" );
16564
16565 // Clean up headers
16566 this.headers
16567 .removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
16568 .removeUniqueId();
16569
16570 this._destroyIcons();
16571
16572 // Clean up content panels
16573 contents = this.headers.next()
16574 .css( "display", "" )
16575 .removeAttr( "role aria-hidden aria-labelledby" )
16576 .removeUniqueId();
16577
16578 if ( this.options.heightStyle !== "content" ) {
16579 contents.css( "height", "" );
16580 }
16581 },
16582
16583 _setOption: function( key, value ) {
16584 if ( key === "active" ) {
16585
16586 // _activate() will handle invalid values and update this.options
16587 this._activate( value );
16588 return;
16589 }
16590
16591 if ( key === "event" ) {
16592 if ( this.options.event ) {
16593 this._off( this.headers, this.options.event );
16594 }
16595 this._setupEvents( value );
16596 }
16597
16598 this._super( key, value );
16599
16600 // Setting collapsible: false while collapsed; open first panel
16601 if ( key === "collapsible" && !value && this.options.active === false ) {
16602 this._activate( 0 );
16603 }
16604
16605 if ( key === "icons" ) {
16606 this._destroyIcons();
16607 if ( value ) {
16608 this._createIcons();
16609 }
16610 }
16611 },
16612
16613 _setOptionDisabled: function( value ) {
16614 this._super( value );
16615
16616 this.element.attr( "aria-disabled", value );
16617 this._toggleClass( null, "ui-state-disabled", !!value );
16618 },
16619
16620 _keydown: function( event ) {
16621 if ( event.altKey || event.ctrlKey ) {
16622 return;
16623 }
16624
16625 var keyCode = $.ui.keyCode,
16626 length = this.headers.length,
16627 currentIndex = this.headers.index( event.target ),
16628 toFocus = false;
16629
16630 switch ( event.keyCode ) {
16631 case keyCode.RIGHT:
16632 case keyCode.DOWN:
16633 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
16634 break;
16635 case keyCode.LEFT:
16636 case keyCode.UP:
16637 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
16638 break;
16639 case keyCode.SPACE:
16640 case keyCode.ENTER:
16641 this._eventHandler( event );
16642 break;
16643 case keyCode.HOME:
16644 toFocus = this.headers[ 0 ];
16645 break;
16646 case keyCode.END:
16647 toFocus = this.headers[ length - 1 ];
16648 break;
16649 }
16650
16651 if ( toFocus ) {
16652 $( event.target ).attr( "tabIndex", -1 );
16653 $( toFocus ).attr( "tabIndex", 0 );
16654 $( toFocus ).trigger( "focus" );
16655 event.preventDefault();
16656 }
16657 },
16658
16659 _panelKeyDown: function( event ) {
16660 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
16661 $( event.currentTarget ).prev().trigger( "focus" );
16662 }
16663 },
16664
16665 refresh: function() {
16666 var options = this.options;
16667 this._processPanels();
16668
16669 // Was collapsed or no panel
16670 if ( ( options.active === false && options.collapsible === true ) ||
16671 !this.headers.length ) {
16672 options.active = false;
16673 this.active = $();
16674
16675 // active false only when collapsible is true
16676 } else if ( options.active === false ) {
16677 this._activate( 0 );
16678
16679 // was active, but active panel is gone
16680 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
16681
16682 // all remaining panel are disabled
16683 if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
16684 options.active = false;
16685 this.active = $();
16686
16687 // activate previous panel
16688 } else {
16689 this._activate( Math.max( 0, options.active - 1 ) );
16690 }
16691
16692 // was active, active panel still exists
16693 } else {
16694
16695 // make sure active index is correct
16696 options.active = this.headers.index( this.active );
16697 }
16698
16699 this._destroyIcons();
16700
16701 this._refresh();
16702 },
16703
16704 _processPanels: function() {
16705 var prevHeaders = this.headers,
16706 prevPanels = this.panels;
16707
16708 if ( typeof this.options.header === "function" ) {
16709 this.headers = this.options.header( this.element );
16710 } else {
16711 this.headers = this.element.find( this.options.header );
16712 }
16713 this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
16714 "ui-state-default" );
16715
16716 this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
16717 this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );
16718
16719 // Avoid memory leaks (#10056)
16720 if ( prevPanels ) {
16721 this._off( prevHeaders.not( this.headers ) );
16722 this._off( prevPanels.not( this.panels ) );
16723 }
16724 },
16725
16726 _refresh: function() {
16727 var maxHeight,
16728 options = this.options,
16729 heightStyle = options.heightStyle,
16730 parent = this.element.parent();
16731
16732 this.active = this._findActive( options.active );
16733 this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
16734 ._removeClass( this.active, "ui-accordion-header-collapsed" );
16735 this._addClass( this.active.next(), "ui-accordion-content-active" );
16736 this.active.next().show();
16737
16738 this.headers
16739 .attr( "role", "tab" )
16740 .each( function() {
16741 var header = $( this ),
16742 headerId = header.uniqueId().attr( "id" ),
16743 panel = header.next(),
16744 panelId = panel.uniqueId().attr( "id" );
16745 header.attr( "aria-controls", panelId );
16746 panel.attr( "aria-labelledby", headerId );
16747 } )
16748 .next()
16749 .attr( "role", "tabpanel" );
16750
16751 this.headers
16752 .not( this.active )
16753 .attr( {
16754 "aria-selected": "false",
16755 "aria-expanded": "false",
16756 tabIndex: -1
16757 } )
16758 .next()
16759 .attr( {
16760 "aria-hidden": "true"
16761 } )
16762 .hide();
16763
16764 // Make sure at least one header is in the tab order
16765 if ( !this.active.length ) {
16766 this.headers.eq( 0 ).attr( "tabIndex", 0 );
16767 } else {
16768 this.active.attr( {
16769 "aria-selected": "true",
16770 "aria-expanded": "true",
16771 tabIndex: 0
16772 } )
16773 .next()
16774 .attr( {
16775 "aria-hidden": "false"
16776 } );
16777 }
16778
16779 this._createIcons();
16780
16781 this._setupEvents( options.event );
16782
16783 if ( heightStyle === "fill" ) {
16784 maxHeight = parent.height();
16785 this.element.siblings( ":visible" ).each( function() {
16786 var elem = $( this ),
16787 position = elem.css( "position" );
16788
16789 if ( position === "absolute" || position === "fixed" ) {
16790 return;
16791 }
16792 maxHeight -= elem.outerHeight( true );
16793 } );
16794
16795 this.headers.each( function() {
16796 maxHeight -= $( this ).outerHeight( true );
16797 } );
16798
16799 this.headers.next()
16800 .each( function() {
16801 $( this ).height( Math.max( 0, maxHeight -
16802 $( this ).innerHeight() + $( this ).height() ) );
16803 } )
16804 .css( "overflow", "auto" );
16805 } else if ( heightStyle === "auto" ) {
16806 maxHeight = 0;
16807 this.headers.next()
16808 .each( function() {
16809 var isVisible = $( this ).is( ":visible" );
16810 if ( !isVisible ) {
16811 $( this ).show();
16812 }
16813 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
16814 if ( !isVisible ) {
16815 $( this ).hide();
16816 }
16817 } )
16818 .height( maxHeight );
16819 }
16820 },
16821
16822 _activate: function( index ) {
16823 var active = this._findActive( index )[ 0 ];
16824
16825 // Trying to activate the already active panel
16826 if ( active === this.active[ 0 ] ) {
16827 return;
16828 }
16829
16830 // Trying to collapse, simulate a click on the currently active header
16831 active = active || this.active[ 0 ];
16832
16833 this._eventHandler( {
16834 target: active,
16835 currentTarget: active,
16836 preventDefault: $.noop
16837 } );
16838 },
16839
16840 _findActive: function( selector ) {
16841 return typeof selector === "number" ? this.headers.eq( selector ) : $();
16842 },
16843
16844 _setupEvents: function( event ) {
16845 var events = {
16846 keydown: "_keydown"
16847 };
16848 if ( event ) {
16849 $.each( event.split( " " ), function( index, eventName ) {
16850 events[ eventName ] = "_eventHandler";
16851 } );
16852 }
16853
16854 this._off( this.headers.add( this.headers.next() ) );
16855 this._on( this.headers, events );
16856 this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
16857 this._hoverable( this.headers );
16858 this._focusable( this.headers );
16859 },
16860
16861 _eventHandler: function( event ) {
16862 var activeChildren, clickedChildren,
16863 options = this.options,
16864 active = this.active,
16865 clicked = $( event.currentTarget ),
16866 clickedIsActive = clicked[ 0 ] === active[ 0 ],
16867 collapsing = clickedIsActive && options.collapsible,
16868 toShow = collapsing ? $() : clicked.next(),
16869 toHide = active.next(),
16870 eventData = {
16871 oldHeader: active,
16872 oldPanel: toHide,
16873 newHeader: collapsing ? $() : clicked,
16874 newPanel: toShow
16875 };
16876
16877 event.preventDefault();
16878
16879 if (
16880
16881 // click on active header, but not collapsible
16882 ( clickedIsActive && !options.collapsible ) ||
16883
16884 // allow canceling activation
16885 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
16886 return;
16887 }
16888
16889 options.active = collapsing ? false : this.headers.index( clicked );
16890
16891 // When the call to ._toggle() comes after the class changes
16892 // it causes a very odd bug in IE 8 (see #6720)
16893 this.active = clickedIsActive ? $() : clicked;
16894 this._toggle( eventData );
16895
16896 // Switch classes
16897 // corner classes on the previously active header stay after the animation
16898 this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
16899 if ( options.icons ) {
16900 activeChildren = active.children( ".ui-accordion-header-icon" );
16901 this._removeClass( activeChildren, null, options.icons.activeHeader )
16902 ._addClass( activeChildren, null, options.icons.header );
16903 }
16904
16905 if ( !clickedIsActive ) {
16906 this._removeClass( clicked, "ui-accordion-header-collapsed" )
16907 ._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
16908 if ( options.icons ) {
16909 clickedChildren = clicked.children( ".ui-accordion-header-icon" );
16910 this._removeClass( clickedChildren, null, options.icons.header )
16911 ._addClass( clickedChildren, null, options.icons.activeHeader );
16912 }
16913
16914 this._addClass( clicked.next(), "ui-accordion-content-active" );
16915 }
16916 },
16917
16918 _toggle: function( data ) {
16919 var toShow = data.newPanel,
16920 toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
16921
16922 // Handle activating a panel during the animation for another activation
16923 this.prevShow.add( this.prevHide ).stop( true, true );
16924 this.prevShow = toShow;
16925 this.prevHide = toHide;
16926
16927 if ( this.options.animate ) {
16928 this._animate( toShow, toHide, data );
16929 } else {
16930 toHide.hide();
16931 toShow.show();
16932 this._toggleComplete( data );
16933 }
16934
16935 toHide.attr( {
16936 "aria-hidden": "true"
16937 } );
16938 toHide.prev().attr( {
16939 "aria-selected": "false",
16940 "aria-expanded": "false"
16941 } );
16942
16943 // if we're switching panels, remove the old header from the tab order
16944 // if we're opening from collapsed state, remove the previous header from the tab order
16945 // if we're collapsing, then keep the collapsing header in the tab order
16946 if ( toShow.length && toHide.length ) {
16947 toHide.prev().attr( {
16948 "tabIndex": -1,
16949 "aria-expanded": "false"
16950 } );
16951 } else if ( toShow.length ) {
16952 this.headers.filter( function() {
16953 return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
16954 } )
16955 .attr( "tabIndex", -1 );
16956 }
16957
16958 toShow
16959 .attr( "aria-hidden", "false" )
16960 .prev()
16961 .attr( {
16962 "aria-selected": "true",
16963 "aria-expanded": "true",
16964 tabIndex: 0
16965 } );
16966 },
16967
16968 _animate: function( toShow, toHide, data ) {
16969 var total, easing, duration,
16970 that = this,
16971 adjust = 0,
16972 boxSizing = toShow.css( "box-sizing" ),
16973 down = toShow.length &&
16974 ( !toHide.length || ( toShow.index() < toHide.index() ) ),
16975 animate = this.options.animate || {},
16976 options = down && animate.down || animate,
16977 complete = function() {
16978 that._toggleComplete( data );
16979 };
16980
16981 if ( typeof options === "number" ) {
16982 duration = options;
16983 }
16984 if ( typeof options === "string" ) {
16985 easing = options;
16986 }
16987
16988 // fall back from options to animation in case of partial down settings
16989 easing = easing || options.easing || animate.easing;
16990 duration = duration || options.duration || animate.duration;
16991
16992 if ( !toHide.length ) {
16993 return toShow.animate( this.showProps, duration, easing, complete );
16994 }
16995 if ( !toShow.length ) {
16996 return toHide.animate( this.hideProps, duration, easing, complete );
16997 }
16998
16999 total = toShow.show().outerHeight();
17000 toHide.animate( this.hideProps, {
17001 duration: duration,
17002 easing: easing,
17003 step: function( now, fx ) {
17004 fx.now = Math.round( now );
17005 }
17006 } );
17007 toShow
17008 .hide()
17009 .animate( this.showProps, {
17010 duration: duration,
17011 easing: easing,
17012 complete: complete,
17013 step: function( now, fx ) {
17014 fx.now = Math.round( now );
17015 if ( fx.prop !== "height" ) {
17016 if ( boxSizing === "content-box" ) {
17017 adjust += fx.now;
17018 }
17019 } else if ( that.options.heightStyle !== "content" ) {
17020 fx.now = Math.round( total - toHide.outerHeight() - adjust );
17021 adjust = 0;
17022 }
17023 }
17024 } );
17025 },
17026
17027 _toggleComplete: function( data ) {
17028 var toHide = data.oldPanel,
17029 prev = toHide.prev();
17030
17031 this._removeClass( toHide, "ui-accordion-content-active" );
17032 this._removeClass( prev, "ui-accordion-header-active" )
17033 ._addClass( prev, "ui-accordion-header-collapsed" );
17034
17035 this._trigger( "activate", null, data );
17036 }
17037} );
17038
17039} );
17040
17041
17042
17043
17044
17045
17046/*!
17047 * jQuery UI Menu 1.14.1
17048 * https://jqueryui.com
17049 *
17050 * Copyright OpenJS Foundation and other contributors
17051 * Released under the MIT license.
17052 * https://jquery.org/license
17053 */
17054
17055//>>label: Menu
17056//>>group: Widgets
17057//>>description: Creates nestable menus.
17058//>>docs: https://api.jqueryui.com/menu/
17059//>>demos: https://jqueryui.com/menu/
17060//>>css.structure: ../../themes/base/core.css
17061//>>css.structure: ../../themes/base/menu.css
17062//>>css.theme: ../../themes/base/theme.css
17063
17064( function( factory ) {
17065 "use strict";
17066
17067 if ( typeof define === "function" && define.amd ) {
17068
17069 // AMD. Register as an anonymous module.
17070 define( [
17071 "jquery",
17072 "../keycode",
17073 "../position",
17074 "../unique-id",
17075 "../version",
17076 "../widget"
17077 ], factory );
17078 } else {
17079
17080 // Browser globals
17081 factory( jQuery );
17082 }
17083} )( function( $ ) {
17084"use strict";
17085
17086return $.widget( "ui.menu", {
17087 version: "1.14.1",
17088 defaultElement: "<ul>",
17089 delay: 300,
17090 options: {
17091 icons: {
17092 submenu: "ui-icon-caret-1-e"
17093 },
17094 items: "> *",
17095 menus: "ul",
17096 position: {
17097 my: "left top",
17098 at: "right top"
17099 },
17100 role: "menu",
17101
17102 // Callbacks
17103 blur: null,
17104 focus: null,
17105 select: null
17106 },
17107
17108 _create: function() {
17109 this.activeMenu = this.element;
17110
17111 // Flag used to prevent firing of the click handler
17112 // as the event bubbles up through nested menus
17113 this.mouseHandled = false;
17114 this.lastMousePosition = { x: null, y: null };
17115 this.element
17116 .uniqueId()
17117 .attr( {
17118 role: this.options.role,
17119 tabIndex: 0
17120 } );
17121
17122 this._addClass( "ui-menu", "ui-widget ui-widget-content" );
17123 this._on( {
17124
17125 // Prevent focus from sticking to links inside menu after clicking
17126 // them (focus should always stay on UL during navigation).
17127 "mousedown .ui-menu-item": function( event ) {
17128 event.preventDefault();
17129
17130 this._activateItem( event );
17131 },
17132 "click .ui-menu-item": function( event ) {
17133 var target = $( event.target );
17134 var active = $( this.document[ 0 ].activeElement );
17135 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
17136 this.select( event );
17137
17138 // Only set the mouseHandled flag if the event will bubble, see #9469.
17139 if ( !event.isPropagationStopped() ) {
17140 this.mouseHandled = true;
17141 }
17142
17143 // Open submenu on click
17144 if ( target.has( ".ui-menu" ).length ) {
17145 this.expand( event );
17146 } else if ( !this.element.is( ":focus" ) &&
17147 active.closest( ".ui-menu" ).length ) {
17148
17149 // Redirect focus to the menu
17150 this.element.trigger( "focus", [ true ] );
17151
17152 // If the active item is on the top level, let it stay active.
17153 // Otherwise, blur the active item since it is no longer visible.
17154 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
17155 clearTimeout( this.timer );
17156 }
17157 }
17158 }
17159 },
17160 "mouseenter .ui-menu-item": "_activateItem",
17161 "mousemove .ui-menu-item": "_activateItem",
17162 mouseleave: "collapseAll",
17163 "mouseleave .ui-menu": "collapseAll",
17164 focus: function( event, keepActiveItem ) {
17165
17166 // If there's already an active item, keep it active
17167 // If not, activate the first item
17168 var item = this.active || this._menuItems().first();
17169
17170 if ( !keepActiveItem ) {
17171 this.focus( event, item );
17172 }
17173 },
17174 blur: function( event ) {
17175 this._delay( function() {
17176 var notContained = !$.contains(
17177 this.element[ 0 ],
17178 this.document[ 0 ].activeElement
17179 );
17180 if ( notContained ) {
17181 this.collapseAll( event );
17182 }
17183 } );
17184 },
17185 keydown: "_keydown"
17186 } );
17187
17188 this.refresh();
17189
17190 // Clicks outside of a menu collapse any open menus
17191 this._on( this.document, {
17192 click: function( event ) {
17193 if ( this._closeOnDocumentClick( event ) ) {
17194 this.collapseAll( event, true );
17195 }
17196
17197 // Reset the mouseHandled flag
17198 this.mouseHandled = false;
17199 }
17200 } );
17201 },
17202
17203 _activateItem: function( event ) {
17204
17205 // Ignore mouse events while typeahead is active, see #10458.
17206 // Prevents focusing the wrong item when typeahead causes a scroll while the mouse
17207 // is over an item in the menu
17208 if ( this.previousFilter ) {
17209 return;
17210 }
17211
17212 // If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356)
17213 if ( event.clientX === this.lastMousePosition.x &&
17214 event.clientY === this.lastMousePosition.y ) {
17215 return;
17216 }
17217
17218 this.lastMousePosition = {
17219 x: event.clientX,
17220 y: event.clientY
17221 };
17222
17223 var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
17224 target = $( event.currentTarget );
17225
17226 // Ignore bubbled events on parent items, see #11641
17227 if ( actualTarget[ 0 ] !== target[ 0 ] ) {
17228 return;
17229 }
17230
17231 // If the item is already active, there's nothing to do
17232 if ( target.is( ".ui-state-active" ) ) {
17233 return;
17234 }
17235
17236 // Remove ui-state-active class from siblings of the newly focused menu item
17237 // to avoid a jump caused by adjacent elements both having a class with a border
17238 this._removeClass( target.siblings().children( ".ui-state-active" ),
17239 null, "ui-state-active" );
17240 this.focus( event, target );
17241 },
17242
17243 _destroy: function() {
17244 var items = this.element.find( ".ui-menu-item" )
17245 .removeAttr( "role aria-disabled" ),
17246 submenus = items.children( ".ui-menu-item-wrapper" )
17247 .removeUniqueId()
17248 .removeAttr( "tabIndex role aria-haspopup" );
17249
17250 // Destroy (sub)menus
17251 this.element
17252 .removeAttr( "aria-activedescendant" )
17253 .find( ".ui-menu" ).addBack()
17254 .removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
17255 "tabIndex" )
17256 .removeUniqueId()
17257 .show();
17258
17259 submenus.children().each( function() {
17260 var elem = $( this );
17261 if ( elem.data( "ui-menu-submenu-caret" ) ) {
17262 elem.remove();
17263 }
17264 } );
17265 },
17266
17267 _keydown: function( event ) {
17268 var match, prev, character, skip,
17269 preventDefault = true;
17270
17271 switch ( event.keyCode ) {
17272 case $.ui.keyCode.PAGE_UP:
17273 this.previousPage( event );
17274 break;
17275 case $.ui.keyCode.PAGE_DOWN:
17276 this.nextPage( event );
17277 break;
17278 case $.ui.keyCode.HOME:
17279 this._move( "first", "first", event );
17280 break;
17281 case $.ui.keyCode.END:
17282 this._move( "last", "last", event );
17283 break;
17284 case $.ui.keyCode.UP:
17285 this.previous( event );
17286 break;
17287 case $.ui.keyCode.DOWN:
17288 this.next( event );
17289 break;
17290 case $.ui.keyCode.LEFT:
17291 this.collapse( event );
17292 break;
17293 case $.ui.keyCode.RIGHT:
17294 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
17295 this.expand( event );
17296 }
17297 break;
17298 case $.ui.keyCode.ENTER:
17299 case $.ui.keyCode.SPACE:
17300 this._activate( event );
17301 break;
17302 case $.ui.keyCode.ESCAPE:
17303 this.collapse( event );
17304 break;
17305 default:
17306 preventDefault = false;
17307 prev = this.previousFilter || "";
17308 skip = false;
17309
17310 // Support number pad values
17311 character = event.keyCode >= 96 && event.keyCode <= 105 ?
17312 ( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
17313
17314 clearTimeout( this.filterTimer );
17315
17316 if ( character === prev ) {
17317 skip = true;
17318 } else {
17319 character = prev + character;
17320 }
17321
17322 match = this._filterMenuItems( character );
17323 match = skip && match.index( this.active.next() ) !== -1 ?
17324 this.active.nextAll( ".ui-menu-item" ) :
17325 match;
17326
17327 // If no matches on the current filter, reset to the last character pressed
17328 // to move down the menu to the first item that starts with that character
17329 if ( !match.length ) {
17330 character = String.fromCharCode( event.keyCode );
17331 match = this._filterMenuItems( character );
17332 }
17333
17334 if ( match.length ) {
17335 this.focus( event, match );
17336 this.previousFilter = character;
17337 this.filterTimer = this._delay( function() {
17338 delete this.previousFilter;
17339 }, 1000 );
17340 } else {
17341 delete this.previousFilter;
17342 }
17343 }
17344
17345 if ( preventDefault ) {
17346 event.preventDefault();
17347 }
17348 },
17349
17350 _activate: function( event ) {
17351 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
17352 if ( this.active.children( "[aria-haspopup='true']" ).length ) {
17353 this.expand( event );
17354 } else {
17355 this.select( event );
17356 }
17357 }
17358 },
17359
17360 refresh: function() {
17361 var menus, items, newSubmenus, newItems, newWrappers,
17362 that = this,
17363 icon = this.options.icons.submenu,
17364 submenus = this.element.find( this.options.menus );
17365
17366 this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
17367
17368 // Initialize nested menus
17369 newSubmenus = submenus.filter( ":not(.ui-menu)" )
17370 .hide()
17371 .attr( {
17372 role: this.options.role,
17373 "aria-hidden": "true",
17374 "aria-expanded": "false"
17375 } )
17376 .each( function() {
17377 var menu = $( this ),
17378 item = menu.prev(),
17379 submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
17380
17381 that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
17382 item
17383 .attr( "aria-haspopup", "true" )
17384 .prepend( submenuCaret );
17385 menu.attr( "aria-labelledby", item.attr( "id" ) );
17386 } );
17387
17388 this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
17389
17390 menus = submenus.add( this.element );
17391 items = menus.find( this.options.items );
17392
17393 // Initialize menu-items containing spaces and/or dashes only as dividers
17394 items.not( ".ui-menu-item" ).each( function() {
17395 var item = $( this );
17396 if ( that._isDivider( item ) ) {
17397 that._addClass( item, "ui-menu-divider", "ui-widget-content" );
17398 }
17399 } );
17400
17401 // Don't refresh list items that are already adapted
17402 newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
17403 newWrappers = newItems.children()
17404 .not( ".ui-menu" )
17405 .uniqueId()
17406 .attr( {
17407 tabIndex: -1,
17408 role: this._itemRole()
17409 } );
17410 this._addClass( newItems, "ui-menu-item" )
17411 ._addClass( newWrappers, "ui-menu-item-wrapper" );
17412
17413 // Add aria-disabled attribute to any disabled menu item
17414 items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
17415
17416 // If the active item has been removed, blur the menu
17417 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
17418 this.blur();
17419 }
17420 },
17421
17422 _itemRole: function() {
17423 return {
17424 menu: "menuitem",
17425 listbox: "option"
17426 }[ this.options.role ];
17427 },
17428
17429 _setOption: function( key, value ) {
17430 if ( key === "icons" ) {
17431 var icons = this.element.find( ".ui-menu-icon" );
17432 this._removeClass( icons, null, this.options.icons.submenu )
17433 ._addClass( icons, null, value.submenu );
17434 }
17435 this._super( key, value );
17436 },
17437
17438 _setOptionDisabled: function( value ) {
17439 this._super( value );
17440
17441 this.element.attr( "aria-disabled", String( value ) );
17442 this._toggleClass( null, "ui-state-disabled", !!value );
17443 },
17444
17445 focus: function( event, item ) {
17446 var nested, focused, activeParent;
17447 this.blur( event, event && event.type === "focus" );
17448
17449 this._scrollIntoView( item );
17450
17451 this.active = item.first();
17452
17453 focused = this.active.children( ".ui-menu-item-wrapper" );
17454 this._addClass( focused, null, "ui-state-active" );
17455
17456 // Only update aria-activedescendant if there's a role
17457 // otherwise we assume focus is managed elsewhere
17458 if ( this.options.role ) {
17459 this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
17460 }
17461
17462 // Highlight active parent menu item, if any
17463 activeParent = this.active
17464 .parent()
17465 .closest( ".ui-menu-item" )
17466 .children( ".ui-menu-item-wrapper" );
17467 this._addClass( activeParent, null, "ui-state-active" );
17468
17469 if ( event && event.type === "keydown" ) {
17470 this._close();
17471 } else {
17472 this.timer = this._delay( function() {
17473 this._close();
17474 }, this.delay );
17475 }
17476
17477 nested = item.children( ".ui-menu" );
17478 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
17479 this._startOpening( nested );
17480 }
17481 this.activeMenu = item.parent();
17482
17483 this._trigger( "focus", event, { item: item } );
17484 },
17485
17486 _scrollIntoView: function( item ) {
17487 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
17488 if ( this._hasScroll() ) {
17489 borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
17490 paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
17491 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
17492 scroll = this.activeMenu.scrollTop();
17493 elementHeight = this.activeMenu.height();
17494 itemHeight = item.outerHeight();
17495
17496 if ( offset < 0 ) {
17497 this.activeMenu.scrollTop( scroll + offset );
17498 } else if ( offset + itemHeight > elementHeight ) {
17499 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
17500 }
17501 }
17502 },
17503
17504 blur: function( event, fromFocus ) {
17505 if ( !fromFocus ) {
17506 clearTimeout( this.timer );
17507 }
17508
17509 if ( !this.active ) {
17510 return;
17511 }
17512
17513 this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
17514 null, "ui-state-active" );
17515
17516 this._trigger( "blur", event, { item: this.active } );
17517 this.active = null;
17518 },
17519
17520 _startOpening: function( submenu ) {
17521 clearTimeout( this.timer );
17522
17523 // Don't open if already open fixes a Firefox bug that caused a .5 pixel
17524 // shift in the submenu position when mousing over the caret icon
17525 if ( submenu.attr( "aria-hidden" ) !== "true" ) {
17526 return;
17527 }
17528
17529 this.timer = this._delay( function() {
17530 this._close();
17531 this._open( submenu );
17532 }, this.delay );
17533 },
17534
17535 _open: function( submenu ) {
17536 var position = $.extend( {
17537 of: this.active
17538 }, this.options.position );
17539
17540 clearTimeout( this.timer );
17541 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
17542 .hide()
17543 .attr( "aria-hidden", "true" );
17544
17545 submenu
17546 .show()
17547 .removeAttr( "aria-hidden" )
17548 .attr( "aria-expanded", "true" )
17549 .position( position );
17550 },
17551
17552 collapseAll: function( event, all ) {
17553 clearTimeout( this.timer );
17554 this.timer = this._delay( function() {
17555
17556 // If we were passed an event, look for the submenu that contains the event
17557 var currentMenu = all ? this.element :
17558 $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
17559
17560 // If we found no valid submenu ancestor, use the main menu to close all
17561 // sub menus anyway
17562 if ( !currentMenu.length ) {
17563 currentMenu = this.element;
17564 }
17565
17566 this._close( currentMenu );
17567
17568 this.blur( event );
17569
17570 // Work around active item staying active after menu is blurred
17571 this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
17572
17573 this.activeMenu = currentMenu;
17574 }, all ? 0 : this.delay );
17575 },
17576
17577 // With no arguments, closes the currently active menu - if nothing is active
17578 // it closes all menus. If passed an argument, it will search for menus BELOW
17579 _close: function( startMenu ) {
17580 if ( !startMenu ) {
17581 startMenu = this.active ? this.active.parent() : this.element;
17582 }
17583
17584 startMenu.find( ".ui-menu" )
17585 .hide()
17586 .attr( "aria-hidden", "true" )
17587 .attr( "aria-expanded", "false" );
17588 },
17589
17590 _closeOnDocumentClick: function( event ) {
17591 return !$( event.target ).closest( ".ui-menu" ).length;
17592 },
17593
17594 _isDivider: function( item ) {
17595
17596 // Match hyphen, em dash, en dash
17597 return !/[^\-\u2014\u2013\s]/.test( item.text() );
17598 },
17599
17600 collapse: function( event ) {
17601 var newItem = this.active &&
17602 this.active.parent().closest( ".ui-menu-item", this.element );
17603 if ( newItem && newItem.length ) {
17604 this._close();
17605 this.focus( event, newItem );
17606 }
17607 },
17608
17609 expand: function( event ) {
17610 var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first();
17611
17612 if ( newItem && newItem.length ) {
17613 this._open( newItem.parent() );
17614
17615 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
17616 this._delay( function() {
17617 this.focus( event, newItem );
17618 } );
17619 }
17620 },
17621
17622 next: function( event ) {
17623 this._move( "next", "first", event );
17624 },
17625
17626 previous: function( event ) {
17627 this._move( "prev", "last", event );
17628 },
17629
17630 isFirstItem: function() {
17631 return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
17632 },
17633
17634 isLastItem: function() {
17635 return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
17636 },
17637
17638 _menuItems: function( menu ) {
17639 return ( menu || this.element )
17640 .find( this.options.items )
17641 .filter( ".ui-menu-item" );
17642 },
17643
17644 _move: function( direction, filter, event ) {
17645 var next;
17646 if ( this.active ) {
17647 if ( direction === "first" || direction === "last" ) {
17648 next = this.active
17649 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
17650 .last();
17651 } else {
17652 next = this.active
17653 [ direction + "All" ]( ".ui-menu-item" )
17654 .first();
17655 }
17656 }
17657 if ( !next || !next.length || !this.active ) {
17658 next = this._menuItems( this.activeMenu )[ filter ]();
17659 }
17660
17661 this.focus( event, next );
17662 },
17663
17664 nextPage: function( event ) {
17665 var item, base, height;
17666
17667 if ( !this.active ) {
17668 this.next( event );
17669 return;
17670 }
17671 if ( this.isLastItem() ) {
17672 return;
17673 }
17674 if ( this._hasScroll() ) {
17675 base = this.active.offset().top;
17676 height = this.element.innerHeight();
17677
17678 // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
17679 if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
17680 height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
17681 }
17682
17683 this.active.nextAll( ".ui-menu-item" ).each( function() {
17684 item = $( this );
17685 return item.offset().top - base - height < 0;
17686 } );
17687
17688 this.focus( event, item );
17689 } else {
17690 this.focus( event, this._menuItems( this.activeMenu )
17691 [ !this.active ? "first" : "last" ]() );
17692 }
17693 },
17694
17695 previousPage: function( event ) {
17696 var item, base, height;
17697 if ( !this.active ) {
17698 this.next( event );
17699 return;
17700 }
17701 if ( this.isFirstItem() ) {
17702 return;
17703 }
17704 if ( this._hasScroll() ) {
17705 base = this.active.offset().top;
17706 height = this.element.innerHeight();
17707
17708 // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
17709 if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
17710 height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
17711 }
17712
17713 this.active.prevAll( ".ui-menu-item" ).each( function() {
17714 item = $( this );
17715 return item.offset().top - base + height > 0;
17716 } );
17717
17718 this.focus( event, item );
17719 } else {
17720 this.focus( event, this._menuItems( this.activeMenu ).first() );
17721 }
17722 },
17723
17724 _hasScroll: function() {
17725 return this.element.outerHeight() < this.element.prop( "scrollHeight" );
17726 },
17727
17728 select: function( event ) {
17729
17730 // TODO: It should never be possible to not have an active item at this
17731 // point, but the tests don't trigger mouseenter before click.
17732 this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
17733 var ui = { item: this.active };
17734 if ( !this.active.has( ".ui-menu" ).length ) {
17735 this.collapseAll( event, true );
17736 }
17737 this._trigger( "select", event, ui );
17738 },
17739
17740 _filterMenuItems: function( character ) {
17741 var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
17742 regex = new RegExp( "^" + escapedCharacter, "i" );
17743
17744 return this.activeMenu
17745 .find( this.options.items )
17746
17747 // Only match on items, not dividers or other content (#10571)
17748 .filter( ".ui-menu-item" )
17749 .filter( function() {
17750 return regex.test(
17751 String.prototype.trim.call(
17752 $( this ).children( ".ui-menu-item-wrapper" ).text() ) );
17753 } );
17754 }
17755} );
17756
17757} );
17758
17759
17760
17761
17762
17763
17764/*!
17765 * jQuery UI Autocomplete 1.14.1
17766 * https://jqueryui.com
17767 *
17768 * Copyright OpenJS Foundation and other contributors
17769 * Released under the MIT license.
17770 * https://jquery.org/license
17771 */
17772
17773//>>label: Autocomplete
17774//>>group: Widgets
17775//>>description: Lists suggested words as the user is typing.
17776//>>docs: https://api.jqueryui.com/autocomplete/
17777//>>demos: https://jqueryui.com/autocomplete/
17778//>>css.structure: ../../themes/base/core.css
17779//>>css.structure: ../../themes/base/autocomplete.css
17780//>>css.theme: ../../themes/base/theme.css
17781
17782( function( factory ) {
17783 "use strict";
17784
17785 if ( typeof define === "function" && define.amd ) {
17786
17787 // AMD. Register as an anonymous module.
17788 define( [
17789 "jquery",
17790 "./menu",
17791 "../keycode",
17792 "../position",
17793 "../version",
17794 "../widget"
17795 ], factory );
17796 } else {
17797
17798 // Browser globals
17799 factory( jQuery );
17800 }
17801} )( function( $ ) {
17802"use strict";
17803
17804$.widget( "ui.autocomplete", {
17805 version: "1.14.1",
17806 defaultElement: "<input>",
17807 options: {
17808 appendTo: null,
17809 autoFocus: false,
17810 delay: 300,
17811 minLength: 1,
17812 position: {
17813 my: "left top",
17814 at: "left bottom",
17815 collision: "none"
17816 },
17817 source: null,
17818
17819 // Callbacks
17820 change: null,
17821 close: null,
17822 focus: null,
17823 open: null,
17824 response: null,
17825 search: null,
17826 select: null
17827 },
17828
17829 requestIndex: 0,
17830 pending: 0,
17831 liveRegionTimer: null,
17832
17833 _create: function() {
17834
17835 // Some browsers only repeat keydown events, not keypress events,
17836 // so we use the suppressKeyPress flag to determine if we've already
17837 // handled the keydown event. #7269
17838 // Unfortunately the code for & in keypress is the same as the up arrow,
17839 // so we use the suppressKeyPressRepeat flag to avoid handling keypress
17840 // events when we know the keydown event was used to modify the
17841 // search term. #7799
17842 var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
17843 nodeName = this.element[ 0 ].nodeName.toLowerCase(),
17844 isTextarea = nodeName === "textarea",
17845 isInput = nodeName === "input";
17846
17847 // Textareas are always multi-line
17848 // Inputs are always single-line, even if inside a contentEditable element
17849 // All other element types are determined by whether they're contentEditable
17850 this.isMultiLine = isTextarea ||
17851 !isInput && this.element.prop( "contentEditable" ) === "true";
17852
17853 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
17854 this.isNewMenu = true;
17855
17856 this._addClass( "ui-autocomplete-input" );
17857 this.element.attr( "autocomplete", "off" );
17858
17859 this._on( this.element, {
17860 keydown: function( event ) {
17861 if ( this.element.prop( "readOnly" ) ) {
17862 suppressKeyPress = true;
17863 suppressInput = true;
17864 suppressKeyPressRepeat = true;
17865 return;
17866 }
17867
17868 suppressKeyPress = false;
17869 suppressInput = false;
17870 suppressKeyPressRepeat = false;
17871 var keyCode = $.ui.keyCode;
17872 switch ( event.keyCode ) {
17873 case keyCode.PAGE_UP:
17874 suppressKeyPress = true;
17875 this._move( "previousPage", event );
17876 break;
17877 case keyCode.PAGE_DOWN:
17878 suppressKeyPress = true;
17879 this._move( "nextPage", event );
17880 break;
17881 case keyCode.UP:
17882 suppressKeyPress = true;
17883 this._keyEvent( "previous", event );
17884 break;
17885 case keyCode.DOWN:
17886 suppressKeyPress = true;
17887 this._keyEvent( "next", event );
17888 break;
17889 case keyCode.ENTER:
17890
17891 // when menu is open and has focus
17892 if ( this.menu.active ) {
17893
17894 // #6055 - Opera still allows the keypress to occur
17895 // which causes forms to submit
17896 suppressKeyPress = true;
17897 event.preventDefault();
17898 this.menu.select( event );
17899 }
17900 break;
17901 case keyCode.TAB:
17902 if ( this.menu.active ) {
17903 this.menu.select( event );
17904 }
17905 break;
17906 case keyCode.ESCAPE:
17907 if ( this.menu.element.is( ":visible" ) ) {
17908 if ( !this.isMultiLine ) {
17909 this._value( this.term );
17910 }
17911 this.close( event );
17912
17913 // Different browsers have different default behavior for escape
17914 // Single press can mean undo or clear
17915 event.preventDefault();
17916 }
17917 break;
17918 default:
17919 suppressKeyPressRepeat = true;
17920
17921 // search timeout should be triggered before the input value is changed
17922 this._searchTimeout( event );
17923 break;
17924 }
17925 },
17926 keypress: function( event ) {
17927 if ( suppressKeyPress ) {
17928 suppressKeyPress = false;
17929 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
17930 event.preventDefault();
17931 }
17932 return;
17933 }
17934 if ( suppressKeyPressRepeat ) {
17935 return;
17936 }
17937
17938 // Replicate some key handlers to allow them to repeat in Firefox and Opera
17939 var keyCode = $.ui.keyCode;
17940 switch ( event.keyCode ) {
17941 case keyCode.PAGE_UP:
17942 this._move( "previousPage", event );
17943 break;
17944 case keyCode.PAGE_DOWN:
17945 this._move( "nextPage", event );
17946 break;
17947 case keyCode.UP:
17948 this._keyEvent( "previous", event );
17949 break;
17950 case keyCode.DOWN:
17951 this._keyEvent( "next", event );
17952 break;
17953 }
17954 },
17955 input: function( event ) {
17956 if ( suppressInput ) {
17957 suppressInput = false;
17958 event.preventDefault();
17959 return;
17960 }
17961 this._searchTimeout( event );
17962 },
17963 focus: function() {
17964 this.selectedItem = null;
17965 this.previous = this._value();
17966 },
17967 blur: function( event ) {
17968 clearTimeout( this.searching );
17969 this.close( event );
17970 this._change( event );
17971 }
17972 } );
17973
17974 this._initSource();
17975 this.menu = $( "<ul>" )
17976 .appendTo( this._appendTo() )
17977 .menu( {
17978
17979 // disable ARIA support, the live region takes care of that
17980 role: null
17981 } )
17982 .hide()
17983 .menu( "instance" );
17984
17985 this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
17986 this._on( this.menu.element, {
17987 mousedown: function( event ) {
17988
17989 // Prevent moving focus out of the text field
17990 event.preventDefault();
17991 },
17992 menufocus: function( event, ui ) {
17993 var label, item;
17994
17995 // Support: Firefox
17996 // Prevent accidental activation of menu items in Firefox (#7024 #9118)
17997 if ( this.isNewMenu ) {
17998 this.isNewMenu = false;
17999 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
18000 this.menu.blur();
18001
18002 this.document.one( "mousemove", function() {
18003 $( event.target ).trigger( event.originalEvent );
18004 } );
18005
18006 return;
18007 }
18008 }
18009
18010 item = ui.item.data( "ui-autocomplete-item" );
18011 if ( false !== this._trigger( "focus", event, { item: item } ) ) {
18012
18013 // use value to match what will end up in the input, if it was a key event
18014 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
18015 this._value( item.value );
18016 }
18017 }
18018
18019 // Announce the value in the liveRegion
18020 label = ui.item.attr( "aria-label" ) || item.value;
18021 if ( label && String.prototype.trim.call( label ).length ) {
18022 clearTimeout( this.liveRegionTimer );
18023 this.liveRegionTimer = this._delay( function() {
18024 this.liveRegion.html( $( "<div>" ).text( label ) );
18025 }, 100 );
18026 }
18027 },
18028 menuselect: function( event, ui ) {
18029 var item = ui.item.data( "ui-autocomplete-item" ),
18030 previous = this.previous;
18031
18032 // Only trigger when focus was lost (click on menu)
18033 if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
18034 this.element.trigger( "focus" );
18035 this.previous = previous;
18036 }
18037
18038 if ( false !== this._trigger( "select", event, { item: item } ) ) {
18039 this._value( item.value );
18040 }
18041
18042 // reset the term after the select event
18043 // this allows custom select handling to work properly
18044 this.term = this._value();
18045
18046 this.close( event );
18047 this.selectedItem = item;
18048 }
18049 } );
18050
18051 this.liveRegion = $( "<div>", {
18052 role: "status",
18053 "aria-live": "assertive",
18054 "aria-relevant": "additions"
18055 } )
18056 .appendTo( this.document[ 0 ].body );
18057
18058 this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
18059
18060 // Turning off autocomplete prevents the browser from remembering the
18061 // value when navigating through history, so we re-enable autocomplete
18062 // if the page is unloaded before the widget is destroyed. #7790
18063 this._on( this.window, {
18064 beforeunload: function() {
18065 this.element.removeAttr( "autocomplete" );
18066 }
18067 } );
18068 },
18069
18070 _destroy: function() {
18071 clearTimeout( this.searching );
18072 this.element.removeAttr( "autocomplete" );
18073 this.menu.element.remove();
18074 this.liveRegion.remove();
18075 },
18076
18077 _setOption: function( key, value ) {
18078 this._super( key, value );
18079 if ( key === "source" ) {
18080 this._initSource();
18081 }
18082 if ( key === "appendTo" ) {
18083 this.menu.element.appendTo( this._appendTo() );
18084 }
18085 if ( key === "disabled" && value && this.xhr ) {
18086 this.xhr.abort();
18087 }
18088 },
18089
18090 _isEventTargetInWidget: function( event ) {
18091 var menuElement = this.menu.element[ 0 ];
18092
18093 return event.target === this.element[ 0 ] ||
18094 event.target === menuElement ||
18095 $.contains( menuElement, event.target );
18096 },
18097
18098 _closeOnClickOutside: function( event ) {
18099 if ( !this._isEventTargetInWidget( event ) ) {
18100 this.close();
18101 }
18102 },
18103
18104 _appendTo: function() {
18105 var element = this.options.appendTo;
18106
18107 if ( element ) {
18108 element = element.jquery || element.nodeType ?
18109 $( element ) :
18110 this.document.find( element ).eq( 0 );
18111 }
18112
18113 if ( !element || !element[ 0 ] ) {
18114 element = this.element.closest( ".ui-front, dialog" );
18115 }
18116
18117 if ( !element.length ) {
18118 element = this.document[ 0 ].body;
18119 }
18120
18121 return element;
18122 },
18123
18124 _initSource: function() {
18125 var array, url,
18126 that = this;
18127 if ( Array.isArray( this.options.source ) ) {
18128 array = this.options.source;
18129 this.source = function( request, response ) {
18130 response( $.ui.autocomplete.filter( array, request.term ) );
18131 };
18132 } else if ( typeof this.options.source === "string" ) {
18133 url = this.options.source;
18134 this.source = function( request, response ) {
18135 if ( that.xhr ) {
18136 that.xhr.abort();
18137 }
18138 that.xhr = $.ajax( {
18139 url: url,
18140 data: request,
18141 dataType: "json",
18142 success: function( data ) {
18143 response( data );
18144 },
18145 error: function() {
18146 response( [] );
18147 }
18148 } );
18149 };
18150 } else {
18151 this.source = this.options.source;
18152 }
18153 },
18154
18155 _searchTimeout: function( event ) {
18156 clearTimeout( this.searching );
18157 this.searching = this._delay( function() {
18158
18159 // Search if the value has changed, or if the user retypes the same value (see #7434)
18160 var equalValues = this.term === this._value(),
18161 menuVisible = this.menu.element.is( ":visible" ),
18162 modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
18163
18164 if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
18165 this.selectedItem = null;
18166 this.search( null, event );
18167 }
18168 }, this.options.delay );
18169 },
18170
18171 search: function( value, event ) {
18172 value = value != null ? value : this._value();
18173
18174 // Always save the actual value, not the one passed as an argument
18175 this.term = this._value();
18176
18177 if ( value.length < this.options.minLength ) {
18178 return this.close( event );
18179 }
18180
18181 if ( this._trigger( "search", event ) === false ) {
18182 return;
18183 }
18184
18185 return this._search( value );
18186 },
18187
18188 _search: function( value ) {
18189 this.pending++;
18190 this._addClass( "ui-autocomplete-loading" );
18191 this.cancelSearch = false;
18192
18193 this.source( { term: value }, this._response() );
18194 },
18195
18196 _response: function() {
18197 var index = ++this.requestIndex;
18198
18199 return function( content ) {
18200 if ( index === this.requestIndex ) {
18201 this.__response( content );
18202 }
18203
18204 this.pending--;
18205 if ( !this.pending ) {
18206 this._removeClass( "ui-autocomplete-loading" );
18207 }
18208 }.bind( this );
18209 },
18210
18211 __response: function( content ) {
18212 if ( content ) {
18213 content = this._normalize( content );
18214 }
18215 this._trigger( "response", null, { content: content } );
18216 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
18217 this._suggest( content );
18218 this._trigger( "open" );
18219 } else {
18220
18221 // use ._close() instead of .close() so we don't cancel future searches
18222 this._close();
18223 }
18224 },
18225
18226 close: function( event ) {
18227 this.cancelSearch = true;
18228 this._close( event );
18229 },
18230
18231 _close: function( event ) {
18232
18233 // Remove the handler that closes the menu on outside clicks
18234 this._off( this.document, "mousedown" );
18235
18236 if ( this.menu.element.is( ":visible" ) ) {
18237 this.menu.element.hide();
18238 this.menu.blur();
18239 this.isNewMenu = true;
18240 this._trigger( "close", event );
18241 }
18242 },
18243
18244 _change: function( event ) {
18245 if ( this.previous !== this._value() ) {
18246 this._trigger( "change", event, { item: this.selectedItem } );
18247 }
18248 },
18249
18250 _normalize: function( items ) {
18251
18252 // assume all items have the right format when the first item is complete
18253 if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
18254 return items;
18255 }
18256 return $.map( items, function( item ) {
18257 if ( typeof item === "string" ) {
18258 return {
18259 label: item,
18260 value: item
18261 };
18262 }
18263 return $.extend( {}, item, {
18264 label: item.label || item.value,
18265 value: item.value || item.label
18266 } );
18267 } );
18268 },
18269
18270 _suggest: function( items ) {
18271 var ul = this.menu.element.empty();
18272 this._renderMenu( ul, items );
18273 this.isNewMenu = true;
18274 this.menu.refresh();
18275
18276 // Size and position menu
18277 ul.show();
18278 this._resizeMenu();
18279 ul.position( $.extend( {
18280 of: this.element
18281 }, this.options.position ) );
18282
18283 if ( this.options.autoFocus ) {
18284 this.menu.next();
18285 }
18286
18287 // Listen for interactions outside of the widget (#6642)
18288 this._on( this.document, {
18289 mousedown: "_closeOnClickOutside"
18290 } );
18291 },
18292
18293 _resizeMenu: function() {
18294 var ul = this.menu.element;
18295 ul.outerWidth( Math.max(
18296
18297 // Firefox wraps long text (possibly a rounding bug)
18298 // so we add 1px to avoid the wrapping (#7513)
18299 ul.width( "" ).outerWidth() + 1,
18300 this.element.outerWidth()
18301 ) );
18302 },
18303
18304 _renderMenu: function( ul, items ) {
18305 var that = this;
18306 $.each( items, function( index, item ) {
18307 that._renderItemData( ul, item );
18308 } );
18309 },
18310
18311 _renderItemData: function( ul, item ) {
18312 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
18313 },
18314
18315 _renderItem: function( ul, item ) {
18316 return $( "<li>" )
18317 .append( $( "<div>" ).text( item.label ) )
18318 .appendTo( ul );
18319 },
18320
18321 _move: function( direction, event ) {
18322 if ( !this.menu.element.is( ":visible" ) ) {
18323 this.search( null, event );
18324 return;
18325 }
18326 if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
18327 this.menu.isLastItem() && /^next/.test( direction ) ) {
18328
18329 if ( !this.isMultiLine ) {
18330 this._value( this.term );
18331 }
18332
18333 this.menu.blur();
18334 return;
18335 }
18336 this.menu[ direction ]( event );
18337 },
18338
18339 widget: function() {
18340 return this.menu.element;
18341 },
18342
18343 _value: function() {
18344 return this.valueMethod.apply( this.element, arguments );
18345 },
18346
18347 _keyEvent: function( keyEvent, event ) {
18348 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
18349 this._move( keyEvent, event );
18350
18351 // Prevents moving cursor to beginning/end of the text field in some browsers
18352 event.preventDefault();
18353 }
18354 }
18355} );
18356
18357$.extend( $.ui.autocomplete, {
18358 escapeRegex: function( value ) {
18359 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
18360 },
18361 filter: function( array, term ) {
18362 var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
18363 return $.grep( array, function( value ) {
18364 return matcher.test( value.label || value.value || value );
18365 } );
18366 }
18367} );
18368
18369// Live region extension, adding a `messages` option
18370// NOTE: This is an experimental API. We are still investigating
18371// a full solution for string manipulation and internationalization.
18372$.widget( "ui.autocomplete", $.ui.autocomplete, {
18373 options: {
18374 messages: {
18375 noResults: "No search results.",
18376 results: function( amount ) {
18377 return amount + ( amount > 1 ? " results are" : " result is" ) +
18378 " available, use up and down arrow keys to navigate.";
18379 }
18380 }
18381 },
18382
18383 __response: function( content ) {
18384 var message;
18385 this._superApply( arguments );
18386 if ( this.options.disabled || this.cancelSearch ) {
18387 return;
18388 }
18389 if ( content && content.length ) {
18390 message = this.options.messages.results( content.length );
18391 } else {
18392 message = this.options.messages.noResults;
18393 }
18394 clearTimeout( this.liveRegionTimer );
18395 this.liveRegionTimer = this._delay( function() {
18396 this.liveRegion.html( $( "<div>" ).text( message ) );
18397 }, 100 );
18398 }
18399} );
18400
18401return $.ui.autocomplete;
18402
18403} );
18404
18405
18406/*!
18407 * jQuery UI Controlgroup 1.14.1
18408 * https://jqueryui.com
18409 *
18410 * Copyright OpenJS Foundation and other contributors
18411 * Released under the MIT license.
18412 * https://jquery.org/license
18413 */
18414
18415//>>label: Controlgroup
18416//>>group: Widgets
18417//>>description: Visually groups form control widgets
18418//>>docs: https://api.jqueryui.com/controlgroup/
18419//>>demos: https://jqueryui.com/controlgroup/
18420//>>css.structure: ../../themes/base/core.css
18421//>>css.structure: ../../themes/base/controlgroup.css
18422//>>css.theme: ../../themes/base/theme.css
18423
18424( function( factory ) {
18425 "use strict";
18426
18427 if ( typeof define === "function" && define.amd ) {
18428
18429 // AMD. Register as an anonymous module.
18430 define( [
18431 "jquery",
18432 "../widget"
18433 ], factory );
18434 } else {
18435
18436 // Browser globals
18437 factory( jQuery );
18438 }
18439} )( function( $ ) {
18440"use strict";
18441
18442var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
18443
18444return $.widget( "ui.controlgroup", {
18445 version: "1.14.1",
18446 defaultElement: "<div>",
18447 options: {
18448 direction: "horizontal",
18449 disabled: null,
18450 onlyVisible: true,
18451 items: {
18452 "button": "input[type=button], input[type=submit], input[type=reset], button, a",
18453 "controlgroupLabel": ".ui-controlgroup-label",
18454 "checkboxradio": "input[type='checkbox'], input[type='radio']",
18455 "selectmenu": "select",
18456 "spinner": ".ui-spinner-input"
18457 }
18458 },
18459
18460 _create: function() {
18461 this._enhance();
18462 },
18463
18464 // To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
18465 _enhance: function() {
18466 this.element.attr( "role", "toolbar" );
18467 this.refresh();
18468 },
18469
18470 _destroy: function() {
18471 this._callChildMethod( "destroy" );
18472 this.childWidgets.removeData( "ui-controlgroup-data" );
18473 this.element.removeAttr( "role" );
18474 if ( this.options.items.controlgroupLabel ) {
18475 this.element
18476 .find( this.options.items.controlgroupLabel )
18477 .find( ".ui-controlgroup-label-contents" )
18478 .contents().unwrap();
18479 }
18480 },
18481
18482 _initWidgets: function() {
18483 var that = this,
18484 childWidgets = [];
18485
18486 // First we iterate over each of the items options
18487 $.each( this.options.items, function( widget, selector ) {
18488 var labels;
18489 var options = {};
18490
18491 // Make sure the widget has a selector set
18492 if ( !selector ) {
18493 return;
18494 }
18495
18496 if ( widget === "controlgroupLabel" ) {
18497 labels = that.element.find( selector );
18498 labels.each( function() {
18499 var element = $( this );
18500
18501 if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
18502 return;
18503 }
18504 element.contents()
18505 .wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
18506 } );
18507 that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
18508 childWidgets = childWidgets.concat( labels.get() );
18509 return;
18510 }
18511
18512 // Make sure the widget actually exists
18513 if ( !$.fn[ widget ] ) {
18514 return;
18515 }
18516
18517 // We assume everything is in the middle to start because we can't determine
18518 // first / last elements until all enhancments are done.
18519 if ( that[ "_" + widget + "Options" ] ) {
18520 options = that[ "_" + widget + "Options" ]( "middle" );
18521 } else {
18522 options = { classes: {} };
18523 }
18524
18525 // Find instances of this widget inside controlgroup and init them
18526 that.element
18527 .find( selector )
18528 .each( function() {
18529 var element = $( this );
18530 var instance = element[ widget ]( "instance" );
18531
18532 // We need to clone the default options for this type of widget to avoid
18533 // polluting the variable options which has a wider scope than a single widget.
18534 var instanceOptions = $.widget.extend( {}, options );
18535
18536 // If the button is the child of a spinner ignore it
18537 // TODO: Find a more generic solution
18538 if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
18539 return;
18540 }
18541
18542 // Create the widget if it doesn't exist
18543 if ( !instance ) {
18544 instance = element[ widget ]()[ widget ]( "instance" );
18545 }
18546 if ( instance ) {
18547 instanceOptions.classes =
18548 that._resolveClassesValues( instanceOptions.classes, instance );
18549 }
18550 element[ widget ]( instanceOptions );
18551
18552 // Store an instance of the controlgroup to be able to reference
18553 // from the outermost element for changing options and refresh
18554 var widgetElement = element[ widget ]( "widget" );
18555 $.data( widgetElement[ 0 ], "ui-controlgroup-data",
18556 instance ? instance : element[ widget ]( "instance" ) );
18557
18558 childWidgets.push( widgetElement[ 0 ] );
18559 } );
18560 } );
18561
18562 this.childWidgets = $( $.uniqueSort( childWidgets ) );
18563 this._addClass( this.childWidgets, "ui-controlgroup-item" );
18564 },
18565
18566 _callChildMethod: function( method ) {
18567 this.childWidgets.each( function() {
18568 var element = $( this ),
18569 data = element.data( "ui-controlgroup-data" );
18570 if ( data && data[ method ] ) {
18571 data[ method ]();
18572 }
18573 } );
18574 },
18575
18576 _updateCornerClass: function( element, position ) {
18577 var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
18578 var add = this._buildSimpleOptions( position, "label" ).classes.label;
18579
18580 this._removeClass( element, null, remove );
18581 this._addClass( element, null, add );
18582 },
18583
18584 _buildSimpleOptions: function( position, key ) {
18585 var direction = this.options.direction === "vertical";
18586 var result = {
18587 classes: {}
18588 };
18589 result.classes[ key ] = {
18590 "middle": "",
18591 "first": "ui-corner-" + ( direction ? "top" : "left" ),
18592 "last": "ui-corner-" + ( direction ? "bottom" : "right" ),
18593 "only": "ui-corner-all"
18594 }[ position ];
18595
18596 return result;
18597 },
18598
18599 _spinnerOptions: function( position ) {
18600 var options = this._buildSimpleOptions( position, "ui-spinner" );
18601
18602 options.classes[ "ui-spinner-up" ] = "";
18603 options.classes[ "ui-spinner-down" ] = "";
18604
18605 return options;
18606 },
18607
18608 _buttonOptions: function( position ) {
18609 return this._buildSimpleOptions( position, "ui-button" );
18610 },
18611
18612 _checkboxradioOptions: function( position ) {
18613 return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
18614 },
18615
18616 _selectmenuOptions: function( position ) {
18617 var direction = this.options.direction === "vertical";
18618 return {
18619 width: direction ? "auto" : false,
18620 classes: {
18621 middle: {
18622 "ui-selectmenu-button-open": "",
18623 "ui-selectmenu-button-closed": ""
18624 },
18625 first: {
18626 "ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
18627 "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
18628 },
18629 last: {
18630 "ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
18631 "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
18632 },
18633 only: {
18634 "ui-selectmenu-button-open": "ui-corner-top",
18635 "ui-selectmenu-button-closed": "ui-corner-all"
18636 }
18637
18638 }[ position ]
18639 };
18640 },
18641
18642 _resolveClassesValues: function( classes, instance ) {
18643 var result = {};
18644 $.each( classes, function( key ) {
18645 var current = instance.options.classes[ key ] || "";
18646 current = String.prototype.trim.call( current.replace( controlgroupCornerRegex, "" ) );
18647 result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
18648 } );
18649 return result;
18650 },
18651
18652 _setOption: function( key, value ) {
18653 if ( key === "direction" ) {
18654 this._removeClass( "ui-controlgroup-" + this.options.direction );
18655 }
18656
18657 this._super( key, value );
18658 if ( key === "disabled" ) {
18659 this._callChildMethod( value ? "disable" : "enable" );
18660 return;
18661 }
18662
18663 this.refresh();
18664 },
18665
18666 refresh: function() {
18667 var children,
18668 that = this;
18669
18670 this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
18671
18672 if ( this.options.direction === "horizontal" ) {
18673 this._addClass( null, "ui-helper-clearfix" );
18674 }
18675 this._initWidgets();
18676
18677 children = this.childWidgets;
18678
18679 // We filter here because we need to track all childWidgets not just the visible ones
18680 if ( this.options.onlyVisible ) {
18681 children = children.filter( ":visible" );
18682 }
18683
18684 if ( children.length ) {
18685
18686 // We do this last because we need to make sure all enhancment is done
18687 // before determining first and last
18688 $.each( [ "first", "last" ], function( index, value ) {
18689 var instance = children[ value ]().data( "ui-controlgroup-data" );
18690
18691 if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
18692 var options = that[ "_" + instance.widgetName + "Options" ](
18693 children.length === 1 ? "only" : value
18694 );
18695 options.classes = that._resolveClassesValues( options.classes, instance );
18696 instance.element[ instance.widgetName ]( options );
18697 } else {
18698 that._updateCornerClass( children[ value ](), value );
18699 }
18700 } );
18701
18702 // Finally call the refresh method on each of the child widgets.
18703 this._callChildMethod( "refresh" );
18704 }
18705 }
18706} );
18707} );
18708
18709
18710
18711
18712/*!
18713 * jQuery UI Checkboxradio 1.14.1
18714 * https://jqueryui.com
18715 *
18716 * Copyright OpenJS Foundation and other contributors
18717 * Released under the MIT license.
18718 * https://jquery.org/license
18719 */
18720
18721//>>label: Checkboxradio
18722//>>group: Widgets
18723//>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
18724//>>docs: https://api.jqueryui.com/checkboxradio/
18725//>>demos: https://jqueryui.com/checkboxradio/
18726//>>css.structure: ../../themes/base/core.css
18727//>>css.structure: ../../themes/base/button.css
18728//>>css.structure: ../../themes/base/checkboxradio.css
18729//>>css.theme: ../../themes/base/theme.css
18730
18731( function( factory ) {
18732 "use strict";
18733
18734 if ( typeof define === "function" && define.amd ) {
18735
18736 // AMD. Register as an anonymous module.
18737 define( [
18738 "jquery",
18739 "../form-reset-mixin",
18740 "../labels",
18741 "../widget"
18742 ], factory );
18743 } else {
18744
18745 // Browser globals
18746 factory( jQuery );
18747 }
18748} )( function( $ ) {
18749"use strict";
18750
18751$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
18752 version: "1.14.1",
18753 options: {
18754 disabled: null,
18755 label: null,
18756 icon: true,
18757 classes: {
18758 "ui-checkboxradio-label": "ui-corner-all",
18759 "ui-checkboxradio-icon": "ui-corner-all"
18760 }
18761 },
18762
18763 _getCreateOptions: function() {
18764 var disabled, labels, labelContents;
18765 var options = this._super() || {};
18766
18767 // We read the type here, because it makes more sense to throw a element type error first,
18768 // rather then the error for lack of a label. Often if its the wrong type, it
18769 // won't have a label (e.g. calling on a div, btn, etc)
18770 this._readType();
18771
18772 labels = this.element.labels();
18773
18774 // If there are multiple labels, use the last one
18775 this.label = $( labels[ labels.length - 1 ] );
18776 if ( !this.label.length ) {
18777 $.error( "No label found for checkboxradio widget" );
18778 }
18779
18780 this.originalLabel = "";
18781
18782 // We need to get the label text but this may also need to make sure it does not contain the
18783 // input itself.
18784 // The label contents could be text, html, or a mix. We wrap all elements
18785 // and read the wrapper's `innerHTML` to get a string representation of
18786 // the label, without the input as part of it.
18787 labelContents = this.label.contents().not( this.element[ 0 ] );
18788
18789 if ( labelContents.length ) {
18790 this.originalLabel += labelContents
18791 .clone()
18792 .wrapAll( "<div></div>" )
18793 .parent()
18794 .html();
18795 }
18796
18797 // Set the label option if we found label text
18798 if ( this.originalLabel ) {
18799 options.label = this.originalLabel;
18800 }
18801
18802 disabled = this.element[ 0 ].disabled;
18803 if ( disabled != null ) {
18804 options.disabled = disabled;
18805 }
18806 return options;
18807 },
18808
18809 _create: function() {
18810 var checked = this.element[ 0 ].checked;
18811
18812 this._bindFormResetHandler();
18813
18814 if ( this.options.disabled == null ) {
18815 this.options.disabled = this.element[ 0 ].disabled;
18816 }
18817
18818 this._setOption( "disabled", this.options.disabled );
18819 this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
18820 this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
18821
18822 if ( this.type === "radio" ) {
18823 this._addClass( this.label, "ui-checkboxradio-radio-label" );
18824 }
18825
18826 if ( this.options.label && this.options.label !== this.originalLabel ) {
18827 this._updateLabel();
18828 } else if ( this.originalLabel ) {
18829 this.options.label = this.originalLabel;
18830 }
18831
18832 this._enhance();
18833
18834 if ( checked ) {
18835 this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
18836 }
18837
18838 this._on( {
18839 change: "_toggleClasses",
18840 focus: function() {
18841 this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
18842 },
18843 blur: function() {
18844 this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
18845 }
18846 } );
18847 },
18848
18849 _readType: function() {
18850 var nodeName = this.element[ 0 ].nodeName.toLowerCase();
18851 this.type = this.element[ 0 ].type;
18852 if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
18853 $.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
18854 " and element.type=" + this.type );
18855 }
18856 },
18857
18858 // Support jQuery Mobile enhanced option
18859 _enhance: function() {
18860 this._updateIcon( this.element[ 0 ].checked );
18861 },
18862
18863 widget: function() {
18864 return this.label;
18865 },
18866
18867 _getRadioGroup: function() {
18868 var group;
18869 var name = this.element[ 0 ].name;
18870 var nameSelector = "input[name='" + CSS.escape( name ) + "']";
18871
18872 if ( !name ) {
18873 return $( [] );
18874 }
18875
18876 if ( this.form.length ) {
18877 group = $( this.form[ 0 ].elements ).filter( nameSelector );
18878 } else {
18879
18880 // Not inside a form, check all inputs that also are not inside a form
18881 group = $( nameSelector ).filter( function() {
18882 return $( $( this ).prop( "form" ) ).length === 0;
18883 } );
18884 }
18885
18886 return group.not( this.element );
18887 },
18888
18889 _toggleClasses: function() {
18890 var checked = this.element[ 0 ].checked;
18891 this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
18892
18893 if ( this.options.icon && this.type === "checkbox" ) {
18894 this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
18895 ._toggleClass( this.icon, null, "ui-icon-blank", !checked );
18896 }
18897
18898 if ( this.type === "radio" ) {
18899 this._getRadioGroup()
18900 .each( function() {
18901 var instance = $( this ).checkboxradio( "instance" );
18902
18903 if ( instance ) {
18904 instance._removeClass( instance.label,
18905 "ui-checkboxradio-checked", "ui-state-active" );
18906 }
18907 } );
18908 }
18909 },
18910
18911 _destroy: function() {
18912 this._unbindFormResetHandler();
18913
18914 if ( this.icon ) {
18915 this.icon.remove();
18916 this.iconSpace.remove();
18917 }
18918 },
18919
18920 _setOption: function( key, value ) {
18921
18922 // We don't allow the value to be set to nothing
18923 if ( key === "label" && !value ) {
18924 return;
18925 }
18926
18927 this._super( key, value );
18928
18929 if ( key === "disabled" ) {
18930 this._toggleClass( this.label, null, "ui-state-disabled", value );
18931 this.element[ 0 ].disabled = value;
18932
18933 // Don't refresh when setting disabled
18934 return;
18935 }
18936 this.refresh();
18937 },
18938
18939 _updateIcon: function( checked ) {
18940 var toAdd = "ui-icon ui-icon-background ";
18941
18942 if ( this.options.icon ) {
18943 if ( !this.icon ) {
18944 this.icon = $( "<span>" );
18945 this.iconSpace = $( "<span> </span>" );
18946 this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
18947 }
18948
18949 if ( this.type === "checkbox" ) {
18950 toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
18951 this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
18952 } else {
18953 toAdd += "ui-icon-blank";
18954 }
18955 this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
18956 if ( !checked ) {
18957 this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
18958 }
18959 this.icon.prependTo( this.label ).after( this.iconSpace );
18960 } else if ( this.icon !== undefined ) {
18961 this.icon.remove();
18962 this.iconSpace.remove();
18963 delete this.icon;
18964 }
18965 },
18966
18967 _updateLabel: function() {
18968
18969 // Remove the contents of the label ( minus the icon, icon space, and input )
18970 var contents = this.label.contents().not( this.element[ 0 ] );
18971 if ( this.icon ) {
18972 contents = contents.not( this.icon[ 0 ] );
18973 }
18974 if ( this.iconSpace ) {
18975 contents = contents.not( this.iconSpace[ 0 ] );
18976 }
18977 contents.remove();
18978
18979 this.label.append( this.options.label );
18980 },
18981
18982 refresh: function() {
18983 var checked = this.element[ 0 ].checked,
18984 isDisabled = this.element[ 0 ].disabled;
18985
18986 this._updateIcon( checked );
18987 this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
18988 if ( this.options.label !== null ) {
18989 this._updateLabel();
18990 }
18991
18992 if ( isDisabled !== this.options.disabled ) {
18993 this._setOptions( { "disabled": isDisabled } );
18994 }
18995 }
18996
18997} ] );
18998
18999return $.ui.checkboxradio;
19000
19001} );
19002
19003
19004
19005
19006
19007/*!
19008 * jQuery UI Button 1.14.1
19009 * https://jqueryui.com
19010 *
19011 * Copyright OpenJS Foundation and other contributors
19012 * Released under the MIT license.
19013 * https://jquery.org/license
19014 */
19015
19016//>>label: Button
19017//>>group: Widgets
19018//>>description: Enhances a form with themeable buttons.
19019//>>docs: https://api.jqueryui.com/button/
19020//>>demos: https://jqueryui.com/button/
19021//>>css.structure: ../../themes/base/core.css
19022//>>css.structure: ../../themes/base/button.css
19023//>>css.theme: ../../themes/base/theme.css
19024
19025( function( factory ) {
19026 "use strict";
19027
19028 if ( typeof define === "function" && define.amd ) {
19029
19030 // AMD. Register as an anonymous module.
19031 define( [
19032 "jquery",
19033
19034 // These are only for backcompat
19035 // TODO: Remove after 1.12
19036 "./controlgroup",
19037 "./checkboxradio",
19038
19039 "../keycode",
19040 "../widget"
19041 ], factory );
19042 } else {
19043
19044 // Browser globals
19045 factory( jQuery );
19046 }
19047} )( function( $ ) {
19048"use strict";
19049
19050$.widget( "ui.button", {
19051 version: "1.14.1",
19052 defaultElement: "<button>",
19053 options: {
19054 classes: {
19055 "ui-button": "ui-corner-all"
19056 },
19057 disabled: null,
19058 icon: null,
19059 iconPosition: "beginning",
19060 label: null,
19061 showLabel: true
19062 },
19063
19064 _getCreateOptions: function() {
19065 var disabled,
19066
19067 // This is to support cases like in jQuery Mobile where the base widget does have
19068 // an implementation of _getCreateOptions
19069 options = this._super() || {};
19070
19071 this.isInput = this.element.is( "input" );
19072
19073 disabled = this.element[ 0 ].disabled;
19074 if ( disabled != null ) {
19075 options.disabled = disabled;
19076 }
19077
19078 this.originalLabel = this.isInput ? this.element.val() : this.element.html();
19079 if ( this.originalLabel ) {
19080 options.label = this.originalLabel;
19081 }
19082
19083 return options;
19084 },
19085
19086 _create: function() {
19087 if ( !this.option.showLabel & !this.options.icon ) {
19088 this.options.showLabel = true;
19089 }
19090
19091 // We have to check the option again here even though we did in _getCreateOptions,
19092 // because null may have been passed on init which would override what was set in
19093 // _getCreateOptions
19094 if ( this.options.disabled == null ) {
19095 this.options.disabled = this.element[ 0 ].disabled || false;
19096 }
19097
19098 this.hasTitle = !!this.element.attr( "title" );
19099
19100 // Check to see if the label needs to be set or if its already correct
19101 if ( this.options.label && this.options.label !== this.originalLabel ) {
19102 if ( this.isInput ) {
19103 this.element.val( this.options.label );
19104 } else {
19105 this.element.html( this.options.label );
19106 }
19107 }
19108 this._addClass( "ui-button", "ui-widget" );
19109 this._setOption( "disabled", this.options.disabled );
19110 this._enhance();
19111
19112 if ( this.element.is( "a" ) ) {
19113 this._on( {
19114 "keyup": function( event ) {
19115 if ( event.keyCode === $.ui.keyCode.SPACE ) {
19116 event.preventDefault();
19117
19118 // If a native click is available use it, so we
19119 // actually cause navigation. Otherwise, just trigger
19120 // a click event.
19121 if ( this.element[ 0 ].click ) {
19122 this.element[ 0 ].click();
19123 } else {
19124 this.element.trigger( "click" );
19125 }
19126 }
19127 }
19128 } );
19129 }
19130 },
19131
19132 _enhance: function() {
19133 if ( !this.element.is( "button" ) ) {
19134 this.element.attr( "role", "button" );
19135 }
19136
19137 if ( this.options.icon ) {
19138 this._updateIcon( "icon", this.options.icon );
19139 this._updateTooltip();
19140 }
19141 },
19142
19143 _updateTooltip: function() {
19144 this.title = this.element.attr( "title" );
19145
19146 if ( !this.options.showLabel && !this.title ) {
19147 this.element.attr( "title", this.options.label );
19148 }
19149 },
19150
19151 _updateIcon: function( option, value ) {
19152 var icon = option !== "iconPosition",
19153 position = icon ? this.options.iconPosition : value,
19154 displayBlock = position === "top" || position === "bottom";
19155
19156 // Create icon
19157 if ( !this.icon ) {
19158 this.icon = $( "<span>" );
19159
19160 this._addClass( this.icon, "ui-button-icon", "ui-icon" );
19161
19162 if ( !this.options.showLabel ) {
19163 this._addClass( "ui-button-icon-only" );
19164 }
19165 } else if ( icon ) {
19166
19167 // If we are updating the icon remove the old icon class
19168 this._removeClass( this.icon, null, this.options.icon );
19169 }
19170
19171 // If we are updating the icon add the new icon class
19172 if ( icon ) {
19173 this._addClass( this.icon, null, value );
19174 }
19175
19176 this._attachIcon( position );
19177
19178 // If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
19179 // the iconSpace if there is one.
19180 if ( displayBlock ) {
19181 this._addClass( this.icon, null, "ui-widget-icon-block" );
19182 if ( this.iconSpace ) {
19183 this.iconSpace.remove();
19184 }
19185 } else {
19186
19187 // Position is beginning or end so remove the ui-widget-icon-block class and add the
19188 // space if it does not exist
19189 if ( !this.iconSpace ) {
19190 this.iconSpace = $( "<span> </span>" );
19191 this._addClass( this.iconSpace, "ui-button-icon-space" );
19192 }
19193 this._removeClass( this.icon, null, "ui-wiget-icon-block" );
19194 this._attachIconSpace( position );
19195 }
19196 },
19197
19198 _destroy: function() {
19199 this.element.removeAttr( "role" );
19200
19201 if ( this.icon ) {
19202 this.icon.remove();
19203 }
19204 if ( this.iconSpace ) {
19205 this.iconSpace.remove();
19206 }
19207 if ( !this.hasTitle ) {
19208 this.element.removeAttr( "title" );
19209 }
19210 },
19211
19212 _attachIconSpace: function( iconPosition ) {
19213 this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
19214 },
19215
19216 _attachIcon: function( iconPosition ) {
19217 this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
19218 },
19219
19220 _setOptions: function( options ) {
19221 var newShowLabel = options.showLabel === undefined ?
19222 this.options.showLabel :
19223 options.showLabel,
19224 newIcon = options.icon === undefined ? this.options.icon : options.icon;
19225
19226 if ( !newShowLabel && !newIcon ) {
19227 options.showLabel = true;
19228 }
19229 this._super( options );
19230 },
19231
19232 _setOption: function( key, value ) {
19233 if ( key === "icon" ) {
19234 if ( value ) {
19235 this._updateIcon( key, value );
19236 } else if ( this.icon ) {
19237 this.icon.remove();
19238 if ( this.iconSpace ) {
19239 this.iconSpace.remove();
19240 }
19241 }
19242 }
19243
19244 if ( key === "iconPosition" ) {
19245 this._updateIcon( key, value );
19246 }
19247
19248 // Make sure we can't end up with a button that has neither text nor icon
19249 if ( key === "showLabel" ) {
19250 this._toggleClass( "ui-button-icon-only", null, !value );
19251 this._updateTooltip();
19252 }
19253
19254 if ( key === "label" ) {
19255 if ( this.isInput ) {
19256 this.element.val( value );
19257 } else {
19258
19259 // If there is an icon, append it, else nothing then append the value
19260 // this avoids removal of the icon when setting label text
19261 this.element.html( value );
19262 if ( this.icon ) {
19263 this._attachIcon( this.options.iconPosition );
19264 this._attachIconSpace( this.options.iconPosition );
19265 }
19266 }
19267 }
19268
19269 this._super( key, value );
19270
19271 if ( key === "disabled" ) {
19272 this._toggleClass( null, "ui-state-disabled", value );
19273 this.element[ 0 ].disabled = value;
19274 if ( value ) {
19275 this.element.trigger( "blur" );
19276 }
19277 }
19278 },
19279
19280 refresh: function() {
19281
19282 // Make sure to only check disabled if its an element that supports this otherwise
19283 // check for the disabled class to determine state
19284 var isDisabled = this.element.is( "input, button" ) ?
19285 this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
19286
19287 if ( isDisabled !== this.options.disabled ) {
19288 this._setOptions( { disabled: isDisabled } );
19289 }
19290
19291 this._updateTooltip();
19292 }
19293} );
19294
19295// DEPRECATED
19296if ( $.uiBackCompat === true ) {
19297
19298 // Text and Icons options
19299 $.widget( "ui.button", $.ui.button, {
19300 options: {
19301 text: true,
19302 icons: {
19303 primary: null,
19304 secondary: null
19305 }
19306 },
19307
19308 _create: function() {
19309 if ( this.options.showLabel && !this.options.text ) {
19310 this.options.showLabel = this.options.text;
19311 }
19312 if ( !this.options.showLabel && this.options.text ) {
19313 this.options.text = this.options.showLabel;
19314 }
19315 if ( !this.options.icon && ( this.options.icons.primary ||
19316 this.options.icons.secondary ) ) {
19317 if ( this.options.icons.primary ) {
19318 this.options.icon = this.options.icons.primary;
19319 } else {
19320 this.options.icon = this.options.icons.secondary;
19321 this.options.iconPosition = "end";
19322 }
19323 } else if ( this.options.icon ) {
19324 this.options.icons.primary = this.options.icon;
19325 }
19326 this._super();
19327 },
19328
19329 _setOption: function( key, value ) {
19330 if ( key === "text" ) {
19331 this._super( "showLabel", value );
19332 return;
19333 }
19334 if ( key === "showLabel" ) {
19335 this.options.text = value;
19336 }
19337 if ( key === "icon" ) {
19338 this.options.icons.primary = value;
19339 }
19340 if ( key === "icons" ) {
19341 if ( value.primary ) {
19342 this._super( "icon", value.primary );
19343 this._super( "iconPosition", "beginning" );
19344 } else if ( value.secondary ) {
19345 this._super( "icon", value.secondary );
19346 this._super( "iconPosition", "end" );
19347 }
19348 }
19349 this._superApply( arguments );
19350 }
19351 } );
19352
19353 $.fn.button = ( function( orig ) {
19354 return function( options ) {
19355 var isMethodCall = typeof options === "string";
19356 var args = Array.prototype.slice.call( arguments, 1 );
19357 var returnValue = this;
19358
19359 if ( isMethodCall ) {
19360
19361 // If this is an empty collection, we need to have the instance method
19362 // return undefined instead of the jQuery instance
19363 if ( !this.length && options === "instance" ) {
19364 returnValue = undefined;
19365 } else {
19366 this.each( function() {
19367 var methodValue;
19368 var type = $( this ).attr( "type" );
19369 var name = type !== "checkbox" && type !== "radio" ?
19370 "button" :
19371 "checkboxradio";
19372 var instance = $.data( this, "ui-" + name );
19373
19374 if ( options === "instance" ) {
19375 returnValue = instance;
19376 return false;
19377 }
19378
19379 if ( !instance ) {
19380 return $.error( "cannot call methods on button" +
19381 " prior to initialization; " +
19382 "attempted to call method '" + options + "'" );
19383 }
19384
19385 if ( typeof instance[ options ] !== "function" ||
19386 options.charAt( 0 ) === "_" ) {
19387 return $.error( "no such method '" + options + "' for button" +
19388 " widget instance" );
19389 }
19390
19391 methodValue = instance[ options ].apply( instance, args );
19392
19393 if ( methodValue !== instance && methodValue !== undefined ) {
19394 returnValue = methodValue && methodValue.jquery ?
19395 returnValue.pushStack( methodValue.get() ) :
19396 methodValue;
19397 return false;
19398 }
19399 } );
19400 }
19401 } else {
19402
19403 // Allow multiple hashes to be passed on init
19404 if ( args.length ) {
19405 options = $.widget.extend.apply( null, [ options ].concat( args ) );
19406 }
19407
19408 this.each( function() {
19409 var type = $( this ).attr( "type" );
19410 var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio";
19411 var instance = $.data( this, "ui-" + name );
19412
19413 if ( instance ) {
19414 instance.option( options || {} );
19415 if ( instance._init ) {
19416 instance._init();
19417 }
19418 } else {
19419 if ( name === "button" ) {
19420 orig.call( $( this ), options );
19421 return;
19422 }
19423
19424 $( this ).checkboxradio( $.extend( { icon: false }, options ) );
19425 }
19426 } );
19427 }
19428
19429 return returnValue;
19430 };
19431 } )( $.fn.button );
19432
19433 $.fn.buttonset = function() {
19434 if ( !$.ui.controlgroup ) {
19435 $.error( "Controlgroup widget missing" );
19436 }
19437 if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
19438 return this.controlgroup.apply( this,
19439 [ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
19440 }
19441 if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
19442 return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
19443 }
19444 if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
19445 arguments[ 0 ].items = {
19446 button: arguments[ 0 ].items
19447 };
19448 }
19449 return this.controlgroup.apply( this, arguments );
19450 };
19451}
19452
19453return $.ui.button;
19454
19455} );
19456
19457
19458
19459/* eslint-disable max-len, camelcase */
19460/*!
19461 * jQuery UI Datepicker 1.14.1
19462 * https://jqueryui.com
19463 *
19464 * Copyright OpenJS Foundation and other contributors
19465 * Released under the MIT license.
19466 * https://jquery.org/license
19467 */
19468
19469//>>label: Datepicker
19470//>>group: Widgets
19471//>>description: Displays a calendar from an input or inline for selecting dates.
19472//>>docs: https://api.jqueryui.com/datepicker/
19473//>>demos: https://jqueryui.com/datepicker/
19474//>>css.structure: ../../themes/base/core.css
19475//>>css.structure: ../../themes/base/datepicker.css
19476//>>css.theme: ../../themes/base/theme.css
19477
19478( function( factory ) {
19479 "use strict";
19480
19481 if ( typeof define === "function" && define.amd ) {
19482
19483 // AMD. Register as an anonymous module.
19484 define( [
19485 "jquery",
19486 "../version",
19487 "../keycode"
19488 ], factory );
19489 } else {
19490
19491 // Browser globals
19492 factory( jQuery );
19493 }
19494} )( function( $ ) {
19495"use strict";
19496
19497$.extend( $.ui, { datepicker: { version: "1.14.1" } } );
19498
19499var datepicker_instActive;
19500
19501function datepicker_getZindex( elem ) {
19502 var position, value;
19503 while ( elem.length && elem[ 0 ] !== document ) {
19504
19505 // Ignore z-index if position is set to a value where z-index is ignored by the browser
19506 // This makes behavior of this function consistent across browsers
19507 // WebKit always returns auto if the element is positioned
19508 position = elem.css( "position" );
19509 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
19510
19511 // IE returns 0 when zIndex is not specified
19512 // other browsers return a string
19513 // we ignore the case of nested elements with an explicit value of 0
19514 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
19515 value = parseInt( elem.css( "zIndex" ), 10 );
19516 if ( !isNaN( value ) && value !== 0 ) {
19517 return value;
19518 }
19519 }
19520 elem = elem.parent();
19521 }
19522
19523 return 0;
19524}
19525
19526/* Date picker manager.
19527 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
19528 Settings for (groups of) date pickers are maintained in an instance object,
19529 allowing multiple different settings on the same page. */
19530
19531function Datepicker() {
19532 this._curInst = null; // The current instance in use
19533 this._keyEvent = false; // If the last event was a key event
19534 this._disabledInputs = []; // List of date picker inputs that have been disabled
19535 this._datepickerShowing = false; // True if the popup picker is showing , false if not
19536 this._inDialog = false; // True if showing within a "dialog", false if not
19537 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
19538 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
19539 this._appendClass = "ui-datepicker-append"; // The name of the append marker class
19540 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
19541 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
19542 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
19543 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
19544 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
19545 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
19546 this.regional = []; // Available regional settings, indexed by language code
19547 this.regional[ "" ] = { // Default regional settings
19548 closeText: "Done", // Display text for close link
19549 prevText: "Prev", // Display text for previous month link
19550 nextText: "Next", // Display text for next month link
19551 currentText: "Today", // Display text for current month link
19552 monthNames: [ "January", "February", "March", "April", "May", "June",
19553 "July", "August", "September", "October", "November", "December" ], // Names of months for drop-down and formatting
19554 monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting
19555 dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting
19556 dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting
19557 dayNamesMin: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], // Column headings for days starting at Sunday
19558 weekHeader: "Wk", // Column header for week of the year
19559 dateFormat: "mm/dd/yy", // See format options on parseDate
19560 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
19561 isRTL: false, // True if right-to-left language, false if left-to-right
19562 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
19563 yearSuffix: "", // Additional text to append to the year in the month headers,
19564 selectMonthLabel: "Select month", // Invisible label for month selector
19565 selectYearLabel: "Select year" // Invisible label for year selector
19566 };
19567 this._defaults = { // Global defaults for all the date picker instances
19568 showOn: "focus", // "focus" for popup on focus,
19569 // "button" for trigger button, or "both" for either
19570 showAnim: "fadeIn", // Name of jQuery animation for popup
19571 showOptions: {}, // Options for enhanced animations
19572 defaultDate: null, // Used when field is blank: actual date,
19573 // +/-number for offset from today, null for today
19574 appendText: "", // Display text following the input box, e.g. showing the format
19575 buttonText: "...", // Text for trigger button
19576 buttonImage: "", // URL for trigger button image
19577 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
19578 hideIfNoPrevNext: false, // True to hide next/previous month links
19579 // if not applicable, false to just disable them
19580 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
19581 gotoCurrent: false, // True if today link goes back to current selection instead
19582 changeMonth: false, // True if month can be selected directly, false if only prev/next
19583 changeYear: false, // True if year can be selected directly, false if only prev/next
19584 yearRange: "c-10:c+10", // Range of years to display in drop-down,
19585 // either relative to today's year (-nn:+nn), relative to currently displayed year
19586 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
19587 showOtherMonths: false, // True to show dates in other months, false to leave blank
19588 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
19589 showWeek: false, // True to show week of the year, false to not show it
19590 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
19591 // takes a Date and returns the number of the week for it
19592 shortYearCutoff: "+10", // Short year values < this are in the current century,
19593 // > this are in the previous century,
19594 // string value starting with "+" for current year + value
19595 minDate: null, // The earliest selectable date, or null for no limit
19596 maxDate: null, // The latest selectable date, or null for no limit
19597 duration: "fast", // Duration of display/closure
19598 beforeShowDay: null, // Function that takes a date and returns an array with
19599 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
19600 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
19601 beforeShow: null, // Function that takes an input field and
19602 // returns a set of custom settings for the date picker
19603 onSelect: null, // Define a callback function when a date is selected
19604 onChangeMonthYear: null, // Define a callback function when the month or year is changed
19605 onClose: null, // Define a callback function when the datepicker is closed
19606 onUpdateDatepicker: null, // Define a callback function when the datepicker is updated
19607 numberOfMonths: 1, // Number of months to show at a time
19608 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
19609 stepMonths: 1, // Number of months to step back/forward
19610 stepBigMonths: 12, // Number of months to step back/forward for the big links
19611 altField: "", // Selector for an alternate field to store selected dates into
19612 altFormat: "", // The date format to use for the alternate field
19613 constrainInput: true, // The input is constrained by the current date format
19614 showButtonPanel: false, // True to show button panel, false to not show it
19615 autoSize: false, // True to size the input for the date format, false to leave as is
19616 disabled: false // The initial disabled state
19617 };
19618 $.extend( this._defaults, this.regional[ "" ] );
19619 this.regional.en = $.extend( true, {}, this.regional[ "" ] );
19620 this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
19621 this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
19622}
19623
19624$.extend( Datepicker.prototype, {
19625
19626 /* Class name added to elements to indicate already configured with a date picker. */
19627 markerClassName: "hasDatepicker",
19628
19629 //Keep track of the maximum number of rows displayed (see #7043)
19630 maxRows: 4,
19631
19632 // TODO rename to "widget" when switching to widget factory
19633 _widgetDatepicker: function() {
19634 return this.dpDiv;
19635 },
19636
19637 /* Override the default settings for all instances of the date picker.
19638 * @param settings object - the new settings to use as defaults (anonymous object)
19639 * @return the manager object
19640 */
19641 setDefaults: function( settings ) {
19642 datepicker_extendRemove( this._defaults, settings || {} );
19643 return this;
19644 },
19645
19646 /* Attach the date picker to a jQuery selection.
19647 * @param target element - the target input field or division or span
19648 * @param settings object - the new settings to use for this date picker instance (anonymous)
19649 */
19650 _attachDatepicker: function( target, settings ) {
19651 var nodeName, inline, inst;
19652 nodeName = target.nodeName.toLowerCase();
19653 inline = ( nodeName === "div" || nodeName === "span" );
19654 if ( !target.id ) {
19655 this.uuid += 1;
19656 target.id = "dp" + this.uuid;
19657 }
19658 inst = this._newInst( $( target ), inline );
19659 inst.settings = $.extend( {}, settings || {} );
19660 if ( nodeName === "input" ) {
19661 this._connectDatepicker( target, inst );
19662 } else if ( inline ) {
19663 this._inlineDatepicker( target, inst );
19664 }
19665 },
19666
19667 /* Create a new instance object. */
19668 _newInst: function( target, inline ) {
19669 var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars
19670 return { id: id, input: target, // associated target
19671 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
19672 drawMonth: 0, drawYear: 0, // month being drawn
19673 inline: inline, // is datepicker inline or not
19674 dpDiv: ( !inline ? this.dpDiv : // presentation div
19675 datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) };
19676 },
19677
19678 /* Attach the date picker to an input field. */
19679 _connectDatepicker: function( target, inst ) {
19680 var input = $( target );
19681 inst.append = $( [] );
19682 inst.trigger = $( [] );
19683 if ( input.hasClass( this.markerClassName ) ) {
19684 return;
19685 }
19686 this._attachments( input, inst );
19687 input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ).
19688 on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp );
19689 this._autoSize( inst );
19690 $.data( target, "datepicker", inst );
19691
19692 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
19693 if ( inst.settings.disabled ) {
19694 this._disableDatepicker( target );
19695 }
19696 },
19697
19698 /* Make attachments based on settings. */
19699 _attachments: function( input, inst ) {
19700 var showOn, buttonText, buttonImage,
19701 appendText = this._get( inst, "appendText" ),
19702 isRTL = this._get( inst, "isRTL" );
19703
19704 if ( inst.append ) {
19705 inst.append.remove();
19706 }
19707 if ( appendText ) {
19708 inst.append = $( "<span>" )
19709 .addClass( this._appendClass )
19710 .text( appendText );
19711 input[ isRTL ? "before" : "after" ]( inst.append );
19712 }
19713
19714 input.off( "focus", this._showDatepicker );
19715
19716 if ( inst.trigger ) {
19717 inst.trigger.remove();
19718 }
19719
19720 showOn = this._get( inst, "showOn" );
19721 if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field
19722 input.on( "focus", this._showDatepicker );
19723 }
19724 if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked
19725 buttonText = this._get( inst, "buttonText" );
19726 buttonImage = this._get( inst, "buttonImage" );
19727
19728 if ( this._get( inst, "buttonImageOnly" ) ) {
19729 inst.trigger = $( "<img>" )
19730 .addClass( this._triggerClass )
19731 .attr( {
19732 src: buttonImage,
19733 alt: buttonText,
19734 title: buttonText
19735 } );
19736 } else {
19737 inst.trigger = $( "<button type='button'>" )
19738 .addClass( this._triggerClass );
19739 if ( buttonImage ) {
19740 inst.trigger.html(
19741 $( "<img>" )
19742 .attr( {
19743 src: buttonImage,
19744 alt: buttonText,
19745 title: buttonText
19746 } )
19747 );
19748 } else {
19749 inst.trigger.text( buttonText );
19750 }
19751 }
19752
19753 input[ isRTL ? "before" : "after" ]( inst.trigger );
19754 inst.trigger.on( "click", function() {
19755 if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {
19756 $.datepicker._hideDatepicker();
19757 } else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {
19758 $.datepicker._hideDatepicker();
19759 $.datepicker._showDatepicker( input[ 0 ] );
19760 } else {
19761 $.datepicker._showDatepicker( input[ 0 ] );
19762 }
19763 return false;
19764 } );
19765 }
19766 },
19767
19768 /* Apply the maximum length for the date format. */
19769 _autoSize: function( inst ) {
19770 if ( this._get( inst, "autoSize" ) && !inst.inline ) {
19771 var findMax, max, maxI, i,
19772 date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits
19773 dateFormat = this._get( inst, "dateFormat" );
19774
19775 if ( dateFormat.match( /[DM]/ ) ) {
19776 findMax = function( names ) {
19777 max = 0;
19778 maxI = 0;
19779 for ( i = 0; i < names.length; i++ ) {
19780 if ( names[ i ].length > max ) {
19781 max = names[ i ].length;
19782 maxI = i;
19783 }
19784 }
19785 return maxI;
19786 };
19787 date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?
19788 "monthNames" : "monthNamesShort" ) ) ) );
19789 date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?
19790 "dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() );
19791 }
19792 inst.input.attr( "size", this._formatDate( inst, date ).length );
19793 }
19794 },
19795
19796 /* Attach an inline date picker to a div. */
19797 _inlineDatepicker: function( target, inst ) {
19798 var divSpan = $( target );
19799 if ( divSpan.hasClass( this.markerClassName ) ) {
19800 return;
19801 }
19802 divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
19803 $.data( target, "datepicker", inst );
19804 this._setDate( inst, this._getDefaultDate( inst ), true );
19805 this._updateDatepicker( inst );
19806 this._updateAlternate( inst );
19807
19808 //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
19809 if ( inst.settings.disabled ) {
19810 this._disableDatepicker( target );
19811 }
19812
19813 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
19814 // https://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
19815 inst.dpDiv.css( "display", "block" );
19816 },
19817
19818 /* Pop-up the date picker in a "dialog" box.
19819 * @param input element - ignored
19820 * @param date string or Date - the initial date to display
19821 * @param onSelect function - the function to call when a date is selected
19822 * @param settings object - update the dialog date picker instance's settings (anonymous object)
19823 * @param pos int[2] - coordinates for the dialog's position within the screen or
19824 * event - with x/y coordinates or
19825 * leave empty for default (screen centre)
19826 * @return the manager object
19827 */
19828 _dialogDatepicker: function( input, date, onSelect, settings, pos ) {
19829 var id, browserWidth, browserHeight, scrollX, scrollY,
19830 inst = this._dialogInst; // internal instance
19831
19832 if ( !inst ) {
19833 this.uuid += 1;
19834 id = "dp" + this.uuid;
19835 this._dialogInput = $( "<input type='text' id='" + id +
19836 "' style='position: absolute; top: -100px; width: 0px;'/>" );
19837 this._dialogInput.on( "keydown", this._doKeyDown );
19838 $( "body" ).append( this._dialogInput );
19839 inst = this._dialogInst = this._newInst( this._dialogInput, false );
19840 inst.settings = {};
19841 $.data( this._dialogInput[ 0 ], "datepicker", inst );
19842 }
19843 datepicker_extendRemove( inst.settings, settings || {} );
19844 date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );
19845 this._dialogInput.val( date );
19846
19847 this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );
19848 if ( !this._pos ) {
19849 browserWidth = document.documentElement.clientWidth;
19850 browserHeight = document.documentElement.clientHeight;
19851 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
19852 scrollY = document.documentElement.scrollTop || document.body.scrollTop;
19853 this._pos = // should use actual width/height below
19854 [ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
19855 }
19856
19857 // Move input on screen for focus, but hidden behind dialog
19858 this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" );
19859 inst.settings.onSelect = onSelect;
19860 this._inDialog = true;
19861 this.dpDiv.addClass( this._dialogClass );
19862 this._showDatepicker( this._dialogInput[ 0 ] );
19863 if ( $.blockUI ) {
19864 $.blockUI( this.dpDiv );
19865 }
19866 $.data( this._dialogInput[ 0 ], "datepicker", inst );
19867 return this;
19868 },
19869
19870 /* Detach a datepicker from its control.
19871 * @param target element - the target input field or division or span
19872 */
19873 _destroyDatepicker: function( target ) {
19874 var nodeName,
19875 $target = $( target ),
19876 inst = $.data( target, "datepicker" );
19877
19878 if ( !$target.hasClass( this.markerClassName ) ) {
19879 return;
19880 }
19881
19882 nodeName = target.nodeName.toLowerCase();
19883 $.removeData( target, "datepicker" );
19884 if ( nodeName === "input" ) {
19885 inst.append.remove();
19886 inst.trigger.remove();
19887 $target.removeClass( this.markerClassName ).
19888 off( "focus", this._showDatepicker ).
19889 off( "keydown", this._doKeyDown ).
19890 off( "keypress", this._doKeyPress ).
19891 off( "keyup", this._doKeyUp );
19892 } else if ( nodeName === "div" || nodeName === "span" ) {
19893 $target.removeClass( this.markerClassName ).empty();
19894 }
19895
19896 $.datepicker._hideDatepicker();
19897 if ( datepicker_instActive === inst ) {
19898 datepicker_instActive = null;
19899 this._curInst = null;
19900 }
19901 },
19902
19903 /* Enable the date picker to a jQuery selection.
19904 * @param target element - the target input field or division or span
19905 */
19906 _enableDatepicker: function( target ) {
19907 var nodeName, inline,
19908 $target = $( target ),
19909 inst = $.data( target, "datepicker" );
19910
19911 if ( !$target.hasClass( this.markerClassName ) ) {
19912 return;
19913 }
19914
19915 nodeName = target.nodeName.toLowerCase();
19916 if ( nodeName === "input" ) {
19917 target.disabled = false;
19918 inst.trigger.filter( "button" ).
19919 each( function() {
19920 this.disabled = false;
19921 } ).end().
19922 filter( "img" ).css( { opacity: "1.0", cursor: "" } );
19923 } else if ( nodeName === "div" || nodeName === "span" ) {
19924 inline = $target.children( "." + this._inlineClass );
19925 inline.children().removeClass( "ui-state-disabled" );
19926 inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
19927 prop( "disabled", false );
19928 }
19929 this._disabledInputs = $.map( this._disabledInputs,
19930
19931 // Delete entry
19932 function( value ) {
19933 return ( value === target ? null : value );
19934 } );
19935 },
19936
19937 /* Disable the date picker to a jQuery selection.
19938 * @param target element - the target input field or division or span
19939 */
19940 _disableDatepicker: function( target ) {
19941 var nodeName, inline,
19942 $target = $( target ),
19943 inst = $.data( target, "datepicker" );
19944
19945 if ( !$target.hasClass( this.markerClassName ) ) {
19946 return;
19947 }
19948
19949 nodeName = target.nodeName.toLowerCase();
19950 if ( nodeName === "input" ) {
19951 target.disabled = true;
19952 inst.trigger.filter( "button" ).
19953 each( function() {
19954 this.disabled = true;
19955 } ).end().
19956 filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
19957 } else if ( nodeName === "div" || nodeName === "span" ) {
19958 inline = $target.children( "." + this._inlineClass );
19959 inline.children().addClass( "ui-state-disabled" );
19960 inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
19961 prop( "disabled", true );
19962 }
19963 this._disabledInputs = $.map( this._disabledInputs,
19964
19965 // Delete entry
19966 function( value ) {
19967 return ( value === target ? null : value );
19968 } );
19969 this._disabledInputs[ this._disabledInputs.length ] = target;
19970 },
19971
19972 /* Is the first field in a jQuery collection disabled as a datepicker?
19973 * @param target element - the target input field or division or span
19974 * @return boolean - true if disabled, false if enabled
19975 */
19976 _isDisabledDatepicker: function( target ) {
19977 if ( !target ) {
19978 return false;
19979 }
19980 for ( var i = 0; i < this._disabledInputs.length; i++ ) {
19981 if ( this._disabledInputs[ i ] === target ) {
19982 return true;
19983 }
19984 }
19985 return false;
19986 },
19987
19988 /* Retrieve the instance data for the target control.
19989 * @param target element - the target input field or division or span
19990 * @return object - the associated instance data
19991 * @throws error if a jQuery problem getting data
19992 */
19993 _getInst: function( target ) {
19994 try {
19995 return $.data( target, "datepicker" );
19996 } catch ( err ) {
19997 throw "Missing instance data for this datepicker";
19998 }
19999 },
20000
20001 /* Update or retrieve the settings for a date picker attached to an input field or division.
20002 * @param target element - the target input field or division or span
20003 * @param name object - the new settings to update or
20004 * string - the name of the setting to change or retrieve,
20005 * when retrieving also "all" for all instance settings or
20006 * "defaults" for all global defaults
20007 * @param value any - the new value for the setting
20008 * (omit if above is an object or to retrieve a value)
20009 */
20010 _optionDatepicker: function( target, name, value ) {
20011 var settings, date, minDate, maxDate,
20012 inst = this._getInst( target );
20013
20014 if ( arguments.length === 2 && typeof name === "string" ) {
20015 return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
20016 ( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
20017 this._get( inst, name ) ) : null ) );
20018 }
20019
20020 settings = name || {};
20021 if ( typeof name === "string" ) {
20022 settings = {};
20023 settings[ name ] = value;
20024 }
20025
20026 if ( inst ) {
20027 if ( this._curInst === inst ) {
20028 this._hideDatepicker();
20029 }
20030
20031 date = this._getDateDatepicker( target, true );
20032 minDate = this._getMinMaxDate( inst, "min" );
20033 maxDate = this._getMinMaxDate( inst, "max" );
20034 datepicker_extendRemove( inst.settings, settings );
20035
20036 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
20037 if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
20038 inst.settings.minDate = this._formatDate( inst, minDate );
20039 }
20040 if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
20041 inst.settings.maxDate = this._formatDate( inst, maxDate );
20042 }
20043 if ( "disabled" in settings ) {
20044 if ( settings.disabled ) {
20045 this._disableDatepicker( target );
20046 } else {
20047 this._enableDatepicker( target );
20048 }
20049 }
20050 this._attachments( $( target ), inst );
20051 this._autoSize( inst );
20052 this._setDate( inst, date );
20053 this._updateAlternate( inst );
20054 this._updateDatepicker( inst );
20055 }
20056 },
20057
20058 // Change method deprecated
20059 _changeDatepicker: function( target, name, value ) {
20060 this._optionDatepicker( target, name, value );
20061 },
20062
20063 /* Redraw the date picker attached to an input field or division.
20064 * @param target element - the target input field or division or span
20065 */
20066 _refreshDatepicker: function( target ) {
20067 var inst = this._getInst( target );
20068 if ( inst ) {
20069 this._updateDatepicker( inst );
20070 }
20071 },
20072
20073 /* Set the dates for a jQuery selection.
20074 * @param target element - the target input field or division or span
20075 * @param date Date - the new date
20076 */
20077 _setDateDatepicker: function( target, date ) {
20078 var inst = this._getInst( target );
20079 if ( inst ) {
20080 this._setDate( inst, date );
20081 this._updateDatepicker( inst );
20082 this._updateAlternate( inst );
20083 }
20084 },
20085
20086 /* Get the date(s) for the first entry in a jQuery selection.
20087 * @param target element - the target input field or division or span
20088 * @param noDefault boolean - true if no default date is to be used
20089 * @return Date - the current date
20090 */
20091 _getDateDatepicker: function( target, noDefault ) {
20092 var inst = this._getInst( target );
20093 if ( inst && !inst.inline ) {
20094 this._setDateFromField( inst, noDefault );
20095 }
20096 return ( inst ? this._getDate( inst ) : null );
20097 },
20098
20099 /* Handle keystrokes. */
20100 _doKeyDown: function( event ) {
20101 var onSelect, dateStr, sel,
20102 inst = $.datepicker._getInst( event.target ),
20103 handled = true,
20104 isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
20105
20106 inst._keyEvent = true;
20107 if ( $.datepicker._datepickerShowing ) {
20108 switch ( event.keyCode ) {
20109 case 9: $.datepicker._hideDatepicker();
20110 handled = false;
20111 break; // hide on tab out
20112 case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
20113 $.datepicker._currentClass + ")", inst.dpDiv );
20114 if ( sel[ 0 ] ) {
20115 $.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
20116 }
20117
20118 onSelect = $.datepicker._get( inst, "onSelect" );
20119 if ( onSelect ) {
20120 dateStr = $.datepicker._formatDate( inst );
20121
20122 // Trigger custom callback
20123 onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
20124 } else {
20125 $.datepicker._hideDatepicker();
20126 }
20127
20128 return false; // don't submit the form
20129 case 27: $.datepicker._hideDatepicker();
20130 break; // hide on escape
20131 case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
20132 -$.datepicker._get( inst, "stepBigMonths" ) :
20133 -$.datepicker._get( inst, "stepMonths" ) ), "M" );
20134 break; // previous month/year on page up/+ ctrl
20135 case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
20136 +$.datepicker._get( inst, "stepBigMonths" ) :
20137 +$.datepicker._get( inst, "stepMonths" ) ), "M" );
20138 break; // next month/year on page down/+ ctrl
20139 case 35: if ( event.ctrlKey || event.metaKey ) {
20140 $.datepicker._clearDate( event.target );
20141 }
20142 handled = event.ctrlKey || event.metaKey;
20143 break; // clear on ctrl or command +end
20144 case 36: if ( event.ctrlKey || event.metaKey ) {
20145 $.datepicker._gotoToday( event.target );
20146 }
20147 handled = event.ctrlKey || event.metaKey;
20148 break; // current on ctrl or command +home
20149 case 37: if ( event.ctrlKey || event.metaKey ) {
20150 $.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
20151 }
20152 handled = event.ctrlKey || event.metaKey;
20153
20154 // -1 day on ctrl or command +left
20155 if ( event.originalEvent.altKey ) {
20156 $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
20157 -$.datepicker._get( inst, "stepBigMonths" ) :
20158 -$.datepicker._get( inst, "stepMonths" ) ), "M" );
20159 }
20160
20161 // next month/year on alt +left on Mac
20162 break;
20163 case 38: if ( event.ctrlKey || event.metaKey ) {
20164 $.datepicker._adjustDate( event.target, -7, "D" );
20165 }
20166 handled = event.ctrlKey || event.metaKey;
20167 break; // -1 week on ctrl or command +up
20168 case 39: if ( event.ctrlKey || event.metaKey ) {
20169 $.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
20170 }
20171 handled = event.ctrlKey || event.metaKey;
20172
20173 // +1 day on ctrl or command +right
20174 if ( event.originalEvent.altKey ) {
20175 $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
20176 +$.datepicker._get( inst, "stepBigMonths" ) :
20177 +$.datepicker._get( inst, "stepMonths" ) ), "M" );
20178 }
20179
20180 // next month/year on alt +right
20181 break;
20182 case 40: if ( event.ctrlKey || event.metaKey ) {
20183 $.datepicker._adjustDate( event.target, +7, "D" );
20184 }
20185 handled = event.ctrlKey || event.metaKey;
20186 break; // +1 week on ctrl or command +down
20187 default: handled = false;
20188 }
20189 } else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
20190 $.datepicker._showDatepicker( this );
20191 } else {
20192 handled = false;
20193 }
20194
20195 if ( handled ) {
20196 event.preventDefault();
20197 event.stopPropagation();
20198 }
20199 },
20200
20201 /* Filter entered characters - based on date format. */
20202 _doKeyPress: function( event ) {
20203 var chars, chr,
20204 inst = $.datepicker._getInst( event.target );
20205
20206 if ( $.datepicker._get( inst, "constrainInput" ) ) {
20207 chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
20208 chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
20209 return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
20210 }
20211 },
20212
20213 /* Synchronise manual entry and field/alternate field. */
20214 _doKeyUp: function( event ) {
20215 var date,
20216 inst = $.datepicker._getInst( event.target );
20217
20218 if ( inst.input.val() !== inst.lastVal ) {
20219 try {
20220 date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
20221 ( inst.input ? inst.input.val() : null ),
20222 $.datepicker._getFormatConfig( inst ) );
20223
20224 if ( date ) { // only if valid
20225 $.datepicker._setDateFromField( inst );
20226 $.datepicker._updateAlternate( inst );
20227 $.datepicker._updateDatepicker( inst );
20228 }
20229 } catch ( err ) {
20230 }
20231 }
20232 return true;
20233 },
20234
20235 /* Pop-up the date picker for a given input field.
20236 * If false returned from beforeShow event handler do not show.
20237 * @param input element - the input field attached to the date picker or
20238 * event - if triggered by focus
20239 */
20240 _showDatepicker: function( input ) {
20241 input = input.target || input;
20242 if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
20243 input = $( "input", input.parentNode )[ 0 ];
20244 }
20245
20246 if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
20247 return;
20248 }
20249
20250 var inst, beforeShow, beforeShowSettings, isFixed,
20251 offset, showAnim, duration;
20252
20253 inst = $.datepicker._getInst( input );
20254 if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
20255 $.datepicker._curInst.dpDiv.stop( true, true );
20256 if ( inst && $.datepicker._datepickerShowing ) {
20257 $.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
20258 }
20259 }
20260
20261 beforeShow = $.datepicker._get( inst, "beforeShow" );
20262 beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
20263 if ( beforeShowSettings === false ) {
20264 return;
20265 }
20266 datepicker_extendRemove( inst.settings, beforeShowSettings );
20267
20268 inst.lastVal = null;
20269 $.datepicker._lastInput = input;
20270 $.datepicker._setDateFromField( inst );
20271
20272 if ( $.datepicker._inDialog ) { // hide cursor
20273 input.value = "";
20274 }
20275 if ( !$.datepicker._pos ) { // position below input
20276 $.datepicker._pos = $.datepicker._findPos( input );
20277 $.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
20278 }
20279
20280 isFixed = false;
20281 $( input ).parents().each( function() {
20282 isFixed |= $( this ).css( "position" ) === "fixed";
20283 return !isFixed;
20284 } );
20285
20286 offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
20287 $.datepicker._pos = null;
20288
20289 //to avoid flashes on Firefox
20290 inst.dpDiv.empty();
20291
20292 // determine sizing offscreen
20293 inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
20294 $.datepicker._updateDatepicker( inst );
20295
20296 // fix width for dynamic number of date pickers
20297 // and adjust position before showing
20298 offset = $.datepicker._checkOffset( inst, offset, isFixed );
20299 inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
20300 "static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
20301 left: offset.left + "px", top: offset.top + "px" } );
20302
20303 if ( !inst.inline ) {
20304 showAnim = $.datepicker._get( inst, "showAnim" );
20305 duration = $.datepicker._get( inst, "duration" );
20306 inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
20307 $.datepicker._datepickerShowing = true;
20308
20309 if ( $.effects && $.effects.effect[ showAnim ] ) {
20310 inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
20311 } else {
20312 inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
20313 }
20314
20315 if ( $.datepicker._shouldFocusInput( inst ) ) {
20316 inst.input.trigger( "focus" );
20317 }
20318
20319 $.datepicker._curInst = inst;
20320 }
20321 },
20322
20323 /* Generate the date picker content. */
20324 _updateDatepicker: function( inst ) {
20325 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
20326 datepicker_instActive = inst; // for delegate hover events
20327 inst.dpDiv.empty().append( this._generateHTML( inst ) );
20328 this._attachHandlers( inst );
20329
20330 var origyearshtml,
20331 numMonths = this._getNumberOfMonths( inst ),
20332 cols = numMonths[ 1 ],
20333 width = 17,
20334 activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ),
20335 onUpdateDatepicker = $.datepicker._get( inst, "onUpdateDatepicker" );
20336
20337 if ( activeCell.length > 0 ) {
20338 datepicker_handleMouseover.apply( activeCell.get( 0 ) );
20339 }
20340
20341 inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
20342 if ( cols > 1 ) {
20343 inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
20344 }
20345 inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
20346 "Class" ]( "ui-datepicker-multi" );
20347 inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
20348 "Class" ]( "ui-datepicker-rtl" );
20349
20350 if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
20351 inst.input.trigger( "focus" );
20352 }
20353
20354 // Deffered render of the years select (to avoid flashes on Firefox)
20355 if ( inst.yearshtml ) {
20356 origyearshtml = inst.yearshtml;
20357 setTimeout( function() {
20358
20359 //assure that inst.yearshtml didn't change.
20360 if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
20361 inst.dpDiv.find( "select.ui-datepicker-year" ).first().replaceWith( inst.yearshtml );
20362 }
20363 origyearshtml = inst.yearshtml = null;
20364 }, 0 );
20365 }
20366
20367 if ( onUpdateDatepicker ) {
20368 onUpdateDatepicker.apply( ( inst.input ? inst.input[ 0 ] : null ), [ inst ] );
20369 }
20370 },
20371
20372 _shouldFocusInput: function( inst ) {
20373 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" );
20374 },
20375
20376 /* Check positioning to remain on screen. */
20377 _checkOffset: function( inst, offset, isFixed ) {
20378 var dpWidth = inst.dpDiv.outerWidth(),
20379 dpHeight = inst.dpDiv.outerHeight(),
20380 inputWidth = inst.input ? inst.input.outerWidth() : 0,
20381 inputHeight = inst.input ? inst.input.outerHeight() : 0,
20382 viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
20383 viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
20384
20385 offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
20386 offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
20387 offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
20388
20389 // Now check if datepicker is showing outside window viewport - move to a better place if so.
20390 offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
20391 Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
20392 offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
20393 Math.abs( dpHeight + inputHeight ) : 0 );
20394
20395 return offset;
20396 },
20397
20398 /* Find an object's position on the screen. */
20399 _findPos: function( obj ) {
20400 var position,
20401 inst = this._getInst( obj ),
20402 isRTL = this._get( inst, "isRTL" );
20403
20404 while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) {
20405 obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
20406 }
20407
20408 position = $( obj ).offset();
20409 return [ position.left, position.top ];
20410 },
20411
20412 /* Hide the date picker from view.
20413 * @param input element - the input field attached to the date picker
20414 */
20415 _hideDatepicker: function( input ) {
20416 var showAnim, duration, postProcess, onClose,
20417 inst = this._curInst;
20418
20419 if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
20420 return;
20421 }
20422
20423 if ( this._datepickerShowing ) {
20424 showAnim = this._get( inst, "showAnim" );
20425 duration = this._get( inst, "duration" );
20426 postProcess = function() {
20427 $.datepicker._tidyDialog( inst );
20428 };
20429
20430 if ( $.effects && ( $.effects.effect[ showAnim ] ) ) {
20431 inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
20432 } else {
20433 inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
20434 ( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
20435 }
20436
20437 if ( !showAnim ) {
20438 postProcess();
20439 }
20440 this._datepickerShowing = false;
20441
20442 onClose = this._get( inst, "onClose" );
20443 if ( onClose ) {
20444 onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
20445 }
20446
20447 this._lastInput = null;
20448 if ( this._inDialog ) {
20449 this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
20450 if ( $.blockUI ) {
20451 $.unblockUI();
20452 $( "body" ).append( this.dpDiv );
20453 }
20454 }
20455 this._inDialog = false;
20456 }
20457 },
20458
20459 /* Tidy up after a dialog display. */
20460 _tidyDialog: function( inst ) {
20461 inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
20462 },
20463
20464 /* Close date picker if clicked elsewhere. */
20465 _checkExternalClick: function( event ) {
20466 if ( !$.datepicker._curInst ) {
20467 return;
20468 }
20469
20470 var $target = $( event.target ),
20471 inst = $.datepicker._getInst( $target[ 0 ] );
20472
20473 if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
20474 $target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
20475 !$target.hasClass( $.datepicker.markerClassName ) &&
20476 !$target.closest( "." + $.datepicker._triggerClass ).length &&
20477 $.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
20478 ( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
20479 $.datepicker._hideDatepicker();
20480 }
20481 },
20482
20483 /* Adjust one of the date sub-fields. */
20484 _adjustDate: function( id, offset, period ) {
20485 var target = $( id ),
20486 inst = this._getInst( target[ 0 ] );
20487
20488 if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
20489 return;
20490 }
20491 this._adjustInstDate( inst, offset, period );
20492 this._updateDatepicker( inst );
20493 },
20494
20495 /* Action for current link. */
20496 _gotoToday: function( id ) {
20497 var date,
20498 target = $( id ),
20499 inst = this._getInst( target[ 0 ] );
20500
20501 if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
20502 inst.selectedDay = inst.currentDay;
20503 inst.drawMonth = inst.selectedMonth = inst.currentMonth;
20504 inst.drawYear = inst.selectedYear = inst.currentYear;
20505 } else {
20506 date = new Date();
20507 inst.selectedDay = date.getDate();
20508 inst.drawMonth = inst.selectedMonth = date.getMonth();
20509 inst.drawYear = inst.selectedYear = date.getFullYear();
20510 }
20511 this._notifyChange( inst );
20512 this._adjustDate( target );
20513 },
20514
20515 /* Action for selecting a new month/year. */
20516 _selectMonthYear: function( id, select, period ) {
20517 var target = $( id ),
20518 inst = this._getInst( target[ 0 ] );
20519
20520 inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
20521 inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
20522 parseInt( select.options[ select.selectedIndex ].value, 10 );
20523
20524 this._notifyChange( inst );
20525 this._adjustDate( target );
20526 },
20527
20528 /* Action for selecting a day. */
20529 _selectDay: function( id, month, year, td ) {
20530 var inst,
20531 target = $( id );
20532
20533 if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
20534 return;
20535 }
20536
20537 inst = this._getInst( target[ 0 ] );
20538 inst.selectedDay = inst.currentDay = parseInt( $( "a", td ).attr( "data-date" ) );
20539 inst.selectedMonth = inst.currentMonth = month;
20540 inst.selectedYear = inst.currentYear = year;
20541 this._selectDate( id, this._formatDate( inst,
20542 inst.currentDay, inst.currentMonth, inst.currentYear ) );
20543 },
20544
20545 /* Erase the input field and hide the date picker. */
20546 _clearDate: function( id ) {
20547 var target = $( id );
20548 this._selectDate( target, "" );
20549 },
20550
20551 /* Update the input field with the selected date. */
20552 _selectDate: function( id, dateStr ) {
20553 var onSelect,
20554 target = $( id ),
20555 inst = this._getInst( target[ 0 ] );
20556
20557 dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
20558 if ( inst.input ) {
20559 inst.input.val( dateStr );
20560 }
20561 this._updateAlternate( inst );
20562
20563 onSelect = this._get( inst, "onSelect" );
20564 if ( onSelect ) {
20565 onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] ); // trigger custom callback
20566 } else if ( inst.input ) {
20567 inst.input.trigger( "change" ); // fire the change event
20568 }
20569
20570 if ( inst.inline ) {
20571 this._updateDatepicker( inst );
20572 } else {
20573 this._hideDatepicker();
20574 this._lastInput = inst.input[ 0 ];
20575 if ( typeof( inst.input[ 0 ] ) !== "object" ) {
20576 inst.input.trigger( "focus" ); // restore focus
20577 }
20578 this._lastInput = null;
20579 }
20580 },
20581
20582 /* Update any alternate field to synchronise with the main field. */
20583 _updateAlternate: function( inst ) {
20584 var altFormat, date, dateStr,
20585 altField = this._get( inst, "altField" );
20586
20587 if ( altField ) { // update alternate field too
20588 altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
20589 date = this._getDate( inst );
20590 dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
20591 $( document ).find( altField ).val( dateStr );
20592 }
20593 },
20594
20595 /* Set as beforeShowDay function to prevent selection of weekends.
20596 * @param date Date - the date to customise
20597 * @return [boolean, string] - is this date selectable?, what is its CSS class?
20598 */
20599 noWeekends: function( date ) {
20600 var day = date.getDay();
20601 return [ ( day > 0 && day < 6 ), "" ];
20602 },
20603
20604 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
20605 * @param date Date - the date to get the week for
20606 * @return number - the number of the week within the year that contains this date
20607 */
20608 iso8601Week: function( date ) {
20609 var time,
20610 checkDate = new Date( date.getTime() );
20611
20612 // Find Thursday of this week starting on Monday
20613 checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
20614
20615 time = checkDate.getTime();
20616 checkDate.setMonth( 0 ); // Compare with Jan 1
20617 checkDate.setDate( 1 );
20618 return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
20619 },
20620
20621 /* Parse a string value into a date object.
20622 * See formatDate below for the possible formats.
20623 *
20624 * @param format string - the expected format of the date
20625 * @param value string - the date in the above format
20626 * @param settings Object - attributes include:
20627 * shortYearCutoff number - the cutoff year for determining the century (optional)
20628 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
20629 * dayNames string[7] - names of the days from Sunday (optional)
20630 * monthNamesShort string[12] - abbreviated names of the months (optional)
20631 * monthNames string[12] - names of the months (optional)
20632 * @return Date - the extracted date value or null if value is blank
20633 */
20634 parseDate: function( format, value, settings ) {
20635 if ( format == null || value == null ) {
20636 throw "Invalid arguments";
20637 }
20638
20639 value = ( typeof value === "object" ? value.toString() : value + "" );
20640 if ( value === "" ) {
20641 return null;
20642 }
20643
20644 var iFormat, dim, extra,
20645 iValue = 0,
20646 shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
20647 shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
20648 new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
20649 dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
20650 dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
20651 monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
20652 monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
20653 year = -1,
20654 month = -1,
20655 day = -1,
20656 doy = -1,
20657 literal = false,
20658 date,
20659
20660 // Check whether a format character is doubled
20661 lookAhead = function( match ) {
20662 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
20663 if ( matches ) {
20664 iFormat++;
20665 }
20666 return matches;
20667 },
20668
20669 // Extract a number from the string value
20670 getNumber = function( match ) {
20671 var isDoubled = lookAhead( match ),
20672 size = ( match === "@" ? 14 : ( match === "!" ? 20 :
20673 ( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
20674 minSize = ( match === "y" ? size : 1 ),
20675 digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
20676 num = value.substring( iValue ).match( digits );
20677 if ( !num ) {
20678 throw "Missing number at position " + iValue;
20679 }
20680 iValue += num[ 0 ].length;
20681 return parseInt( num[ 0 ], 10 );
20682 },
20683
20684 // Extract a name from the string value and convert to an index
20685 getName = function( match, shortNames, longNames ) {
20686 var index = -1,
20687 names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
20688 return [ [ k, v ] ];
20689 } ).sort( function( a, b ) {
20690 return -( a[ 1 ].length - b[ 1 ].length );
20691 } );
20692
20693 $.each( names, function( i, pair ) {
20694 var name = pair[ 1 ];
20695 if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
20696 index = pair[ 0 ];
20697 iValue += name.length;
20698 return false;
20699 }
20700 } );
20701 if ( index !== -1 ) {
20702 return index + 1;
20703 } else {
20704 throw "Unknown name at position " + iValue;
20705 }
20706 },
20707
20708 // Confirm that a literal character matches the string value
20709 checkLiteral = function() {
20710 if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
20711 throw "Unexpected literal at position " + iValue;
20712 }
20713 iValue++;
20714 };
20715
20716 for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
20717 if ( literal ) {
20718 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
20719 literal = false;
20720 } else {
20721 checkLiteral();
20722 }
20723 } else {
20724 switch ( format.charAt( iFormat ) ) {
20725 case "d":
20726 day = getNumber( "d" );
20727 break;
20728 case "D":
20729 getName( "D", dayNamesShort, dayNames );
20730 break;
20731 case "o":
20732 doy = getNumber( "o" );
20733 break;
20734 case "m":
20735 month = getNumber( "m" );
20736 break;
20737 case "M":
20738 month = getName( "M", monthNamesShort, monthNames );
20739 break;
20740 case "y":
20741 year = getNumber( "y" );
20742 break;
20743 case "@":
20744 date = new Date( getNumber( "@" ) );
20745 year = date.getFullYear();
20746 month = date.getMonth() + 1;
20747 day = date.getDate();
20748 break;
20749 case "!":
20750 date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
20751 year = date.getFullYear();
20752 month = date.getMonth() + 1;
20753 day = date.getDate();
20754 break;
20755 case "'":
20756 if ( lookAhead( "'" ) ) {
20757 checkLiteral();
20758 } else {
20759 literal = true;
20760 }
20761 break;
20762 default:
20763 checkLiteral();
20764 }
20765 }
20766 }
20767
20768 if ( iValue < value.length ) {
20769 extra = value.substr( iValue );
20770 if ( !/^\s+/.test( extra ) ) {
20771 throw "Extra/unparsed characters found in date: " + extra;
20772 }
20773 }
20774
20775 if ( year === -1 ) {
20776 year = new Date().getFullYear();
20777 } else if ( year < 100 ) {
20778 year += new Date().getFullYear() - new Date().getFullYear() % 100 +
20779 ( year <= shortYearCutoff ? 0 : -100 );
20780 }
20781
20782 if ( doy > -1 ) {
20783 month = 1;
20784 day = doy;
20785 do {
20786 dim = this._getDaysInMonth( year, month - 1 );
20787 if ( day <= dim ) {
20788 break;
20789 }
20790 month++;
20791 day -= dim;
20792 } while ( true );
20793 }
20794
20795 date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
20796 if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
20797 throw "Invalid date"; // E.g. 31/02/00
20798 }
20799 return date;
20800 },
20801
20802 /* Standard date formats. */
20803 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
20804 COOKIE: "D, dd M yy",
20805 ISO_8601: "yy-mm-dd",
20806 RFC_822: "D, d M y",
20807 RFC_850: "DD, dd-M-y",
20808 RFC_1036: "D, d M y",
20809 RFC_1123: "D, d M yy",
20810 RFC_2822: "D, d M yy",
20811 RSS: "D, d M y", // RFC 822
20812 TICKS: "!",
20813 TIMESTAMP: "@",
20814 W3C: "yy-mm-dd", // ISO 8601
20815
20816 _ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
20817 Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
20818
20819 /* Format a date object into a string value.
20820 * The format can be combinations of the following:
20821 * d - day of month (no leading zero)
20822 * dd - day of month (two digit)
20823 * o - day of year (no leading zeros)
20824 * oo - day of year (three digit)
20825 * D - day name short
20826 * DD - day name long
20827 * m - month of year (no leading zero)
20828 * mm - month of year (two digit)
20829 * M - month name short
20830 * MM - month name long
20831 * y - year (two digit)
20832 * yy - year (four digit)
20833 * @ - Unix timestamp (ms since 01/01/1970)
20834 * ! - Windows ticks (100ns since 01/01/0001)
20835 * "..." - literal text
20836 * '' - single quote
20837 *
20838 * @param format string - the desired format of the date
20839 * @param date Date - the date value to format
20840 * @param settings Object - attributes include:
20841 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
20842 * dayNames string[7] - names of the days from Sunday (optional)
20843 * monthNamesShort string[12] - abbreviated names of the months (optional)
20844 * monthNames string[12] - names of the months (optional)
20845 * @return string - the date in the above format
20846 */
20847 formatDate: function( format, date, settings ) {
20848 if ( !date ) {
20849 return "";
20850 }
20851
20852 var iFormat,
20853 dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
20854 dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
20855 monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
20856 monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
20857
20858 // Check whether a format character is doubled
20859 lookAhead = function( match ) {
20860 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
20861 if ( matches ) {
20862 iFormat++;
20863 }
20864 return matches;
20865 },
20866
20867 // Format a number, with leading zero if necessary
20868 formatNumber = function( match, value, len ) {
20869 var num = "" + value;
20870 if ( lookAhead( match ) ) {
20871 while ( num.length < len ) {
20872 num = "0" + num;
20873 }
20874 }
20875 return num;
20876 },
20877
20878 // Format a name, short or long as requested
20879 formatName = function( match, value, shortNames, longNames ) {
20880 return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
20881 },
20882 output = "",
20883 literal = false;
20884
20885 if ( date ) {
20886 for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
20887 if ( literal ) {
20888 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
20889 literal = false;
20890 } else {
20891 output += format.charAt( iFormat );
20892 }
20893 } else {
20894 switch ( format.charAt( iFormat ) ) {
20895 case "d":
20896 output += formatNumber( "d", date.getDate(), 2 );
20897 break;
20898 case "D":
20899 output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
20900 break;
20901 case "o":
20902 output += formatNumber( "o",
20903 Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
20904 break;
20905 case "m":
20906 output += formatNumber( "m", date.getMonth() + 1, 2 );
20907 break;
20908 case "M":
20909 output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
20910 break;
20911 case "y":
20912 output += ( lookAhead( "y" ) ? date.getFullYear() :
20913 ( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
20914 break;
20915 case "@":
20916 output += date.getTime();
20917 break;
20918 case "!":
20919 output += date.getTime() * 10000 + this._ticksTo1970;
20920 break;
20921 case "'":
20922 if ( lookAhead( "'" ) ) {
20923 output += "'";
20924 } else {
20925 literal = true;
20926 }
20927 break;
20928 default:
20929 output += format.charAt( iFormat );
20930 }
20931 }
20932 }
20933 }
20934 return output;
20935 },
20936
20937 /* Extract all possible characters from the date format. */
20938 _possibleChars: function( format ) {
20939 var iFormat,
20940 chars = "",
20941 literal = false,
20942
20943 // Check whether a format character is doubled
20944 lookAhead = function( match ) {
20945 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
20946 if ( matches ) {
20947 iFormat++;
20948 }
20949 return matches;
20950 };
20951
20952 for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
20953 if ( literal ) {
20954 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
20955 literal = false;
20956 } else {
20957 chars += format.charAt( iFormat );
20958 }
20959 } else {
20960 switch ( format.charAt( iFormat ) ) {
20961 case "d": case "m": case "y": case "@":
20962 chars += "0123456789";
20963 break;
20964 case "D": case "M":
20965 return null; // Accept anything
20966 case "'":
20967 if ( lookAhead( "'" ) ) {
20968 chars += "'";
20969 } else {
20970 literal = true;
20971 }
20972 break;
20973 default:
20974 chars += format.charAt( iFormat );
20975 }
20976 }
20977 }
20978 return chars;
20979 },
20980
20981 /* Get a setting value, defaulting if necessary. */
20982 _get: function( inst, name ) {
20983 return inst.settings[ name ] !== undefined ?
20984 inst.settings[ name ] : this._defaults[ name ];
20985 },
20986
20987 /* Parse existing date and initialise date picker. */
20988 _setDateFromField: function( inst, noDefault ) {
20989 if ( inst.input.val() === inst.lastVal ) {
20990 return;
20991 }
20992
20993 var dateFormat = this._get( inst, "dateFormat" ),
20994 dates = inst.lastVal = inst.input ? inst.input.val() : null,
20995 defaultDate = this._getDefaultDate( inst ),
20996 date = defaultDate,
20997 settings = this._getFormatConfig( inst );
20998
20999 try {
21000 date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
21001 } catch ( event ) {
21002 dates = ( noDefault ? "" : dates );
21003 }
21004 inst.selectedDay = date.getDate();
21005 inst.drawMonth = inst.selectedMonth = date.getMonth();
21006 inst.drawYear = inst.selectedYear = date.getFullYear();
21007 inst.currentDay = ( dates ? date.getDate() : 0 );
21008 inst.currentMonth = ( dates ? date.getMonth() : 0 );
21009 inst.currentYear = ( dates ? date.getFullYear() : 0 );
21010 this._adjustInstDate( inst );
21011 },
21012
21013 /* Retrieve the default date shown on opening. */
21014 _getDefaultDate: function( inst ) {
21015 return this._restrictMinMax( inst,
21016 this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
21017 },
21018
21019 /* A date may be specified as an exact value or a relative one. */
21020 _determineDate: function( inst, date, defaultDate ) {
21021 var offsetNumeric = function( offset ) {
21022 var date = new Date();
21023 date.setDate( date.getDate() + offset );
21024 return date;
21025 },
21026 offsetString = function( offset ) {
21027 try {
21028 return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
21029 offset, $.datepicker._getFormatConfig( inst ) );
21030 } catch ( e ) {
21031
21032 // Ignore
21033 }
21034
21035 var date = ( offset.toLowerCase().match( /^c/ ) ?
21036 $.datepicker._getDate( inst ) : null ) || new Date(),
21037 year = date.getFullYear(),
21038 month = date.getMonth(),
21039 day = date.getDate(),
21040 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
21041 matches = pattern.exec( offset );
21042
21043 while ( matches ) {
21044 switch ( matches[ 2 ] || "d" ) {
21045 case "d" : case "D" :
21046 day += parseInt( matches[ 1 ], 10 ); break;
21047 case "w" : case "W" :
21048 day += parseInt( matches[ 1 ], 10 ) * 7; break;
21049 case "m" : case "M" :
21050 month += parseInt( matches[ 1 ], 10 );
21051 day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
21052 break;
21053 case "y": case "Y" :
21054 year += parseInt( matches[ 1 ], 10 );
21055 day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
21056 break;
21057 }
21058 matches = pattern.exec( offset );
21059 }
21060 return new Date( year, month, day );
21061 },
21062 newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
21063 ( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
21064
21065 newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
21066 if ( newDate ) {
21067 newDate.setHours( 0 );
21068 newDate.setMinutes( 0 );
21069 newDate.setSeconds( 0 );
21070 newDate.setMilliseconds( 0 );
21071 }
21072 return this._daylightSavingAdjust( newDate );
21073 },
21074
21075 /* Handle switch to/from daylight saving.
21076 * Hours may be non-zero on daylight saving cut-over:
21077 * > 12 when midnight changeover, but then cannot generate
21078 * midnight datetime, so jump to 1AM, otherwise reset.
21079 * @param date (Date) the date to check
21080 * @return (Date) the corrected date
21081 */
21082 _daylightSavingAdjust: function( date ) {
21083 if ( !date ) {
21084 return null;
21085 }
21086 date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
21087 return date;
21088 },
21089
21090 /* Set the date(s) directly. */
21091 _setDate: function( inst, date, noChange ) {
21092 var clear = !date,
21093 origMonth = inst.selectedMonth,
21094 origYear = inst.selectedYear,
21095 newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
21096
21097 inst.selectedDay = inst.currentDay = newDate.getDate();
21098 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
21099 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
21100 if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
21101 this._notifyChange( inst );
21102 }
21103 this._adjustInstDate( inst );
21104 if ( inst.input ) {
21105 inst.input.val( clear ? "" : this._formatDate( inst ) );
21106 }
21107 },
21108
21109 /* Retrieve the date(s) directly. */
21110 _getDate: function( inst ) {
21111 var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
21112 this._daylightSavingAdjust( new Date(
21113 inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
21114 return startDate;
21115 },
21116
21117 /* Attach the onxxx handlers. These are declared statically so
21118 * they work with static code transformers like Caja.
21119 */
21120 _attachHandlers: function( inst ) {
21121 var stepMonths = this._get( inst, "stepMonths" ),
21122 id = "#" + inst.id.replace( /\\\\/g, "\\" );
21123 inst.dpDiv.find( "[data-handler]" ).map( function() {
21124 var handler = {
21125 prev: function() {
21126 $.datepicker._adjustDate( id, -stepMonths, "M" );
21127 },
21128 next: function() {
21129 $.datepicker._adjustDate( id, +stepMonths, "M" );
21130 },
21131 hide: function() {
21132 $.datepicker._hideDatepicker();
21133 },
21134 today: function() {
21135 $.datepicker._gotoToday( id );
21136 },
21137 selectDay: function() {
21138 $.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
21139 return false;
21140 },
21141 selectMonth: function() {
21142 $.datepicker._selectMonthYear( id, this, "M" );
21143 return false;
21144 },
21145 selectYear: function() {
21146 $.datepicker._selectMonthYear( id, this, "Y" );
21147 return false;
21148 }
21149 };
21150 $( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
21151 } );
21152 },
21153
21154 /* Generate the HTML for the current state of the date picker. */
21155 _generateHTML: function( inst ) {
21156 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
21157 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
21158 monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
21159 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
21160 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
21161 printDate, dRow, tbody, daySettings, otherMonth, unselectable,
21162 tempDate = new Date(),
21163 today = this._daylightSavingAdjust(
21164 new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
21165 isRTL = this._get( inst, "isRTL" ),
21166 showButtonPanel = this._get( inst, "showButtonPanel" ),
21167 hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
21168 navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
21169 numMonths = this._getNumberOfMonths( inst ),
21170 showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
21171 stepMonths = this._get( inst, "stepMonths" ),
21172 isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
21173 currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
21174 new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
21175 minDate = this._getMinMaxDate( inst, "min" ),
21176 maxDate = this._getMinMaxDate( inst, "max" ),
21177 drawMonth = inst.drawMonth - showCurrentAtPos,
21178 drawYear = inst.drawYear;
21179
21180 if ( drawMonth < 0 ) {
21181 drawMonth += 12;
21182 drawYear--;
21183 }
21184 if ( maxDate ) {
21185 maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
21186 maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
21187 maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
21188 while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
21189 drawMonth--;
21190 if ( drawMonth < 0 ) {
21191 drawMonth = 11;
21192 drawYear--;
21193 }
21194 }
21195 }
21196 inst.drawMonth = drawMonth;
21197 inst.drawYear = drawYear;
21198
21199 prevText = this._get( inst, "prevText" );
21200 prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
21201 this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
21202 this._getFormatConfig( inst ) ) );
21203
21204 if ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ) {
21205 prev = $( "<a>" )
21206 .attr( {
21207 "class": "ui-datepicker-prev ui-corner-all",
21208 "data-handler": "prev",
21209 "data-event": "click",
21210 title: prevText
21211 } )
21212 .append(
21213 $( "<span>" )
21214 .addClass( "ui-icon ui-icon-circle-triangle-" +
21215 ( isRTL ? "e" : "w" ) )
21216 .text( prevText )
21217 )[ 0 ].outerHTML;
21218 } else if ( hideIfNoPrevNext ) {
21219 prev = "";
21220 } else {
21221 prev = $( "<a>" )
21222 .attr( {
21223 "class": "ui-datepicker-prev ui-corner-all ui-state-disabled",
21224 title: prevText
21225 } )
21226 .append(
21227 $( "<span>" )
21228 .addClass( "ui-icon ui-icon-circle-triangle-" +
21229 ( isRTL ? "e" : "w" ) )
21230 .text( prevText )
21231 )[ 0 ].outerHTML;
21232 }
21233
21234 nextText = this._get( inst, "nextText" );
21235 nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
21236 this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),
21237 this._getFormatConfig( inst ) ) );
21238
21239 if ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ) {
21240 next = $( "<a>" )
21241 .attr( {
21242 "class": "ui-datepicker-next ui-corner-all",
21243 "data-handler": "next",
21244 "data-event": "click",
21245 title: nextText
21246 } )
21247 .append(
21248 $( "<span>" )
21249 .addClass( "ui-icon ui-icon-circle-triangle-" +
21250 ( isRTL ? "w" : "e" ) )
21251 .text( nextText )
21252 )[ 0 ].outerHTML;
21253 } else if ( hideIfNoPrevNext ) {
21254 next = "";
21255 } else {
21256 next = $( "<a>" )
21257 .attr( {
21258 "class": "ui-datepicker-next ui-corner-all ui-state-disabled",
21259 title: nextText
21260 } )
21261 .append(
21262 $( "<span>" )
21263 .attr( "class", "ui-icon ui-icon-circle-triangle-" +
21264 ( isRTL ? "w" : "e" ) )
21265 .text( nextText )
21266 )[ 0 ].outerHTML;
21267 }
21268
21269 currentText = this._get( inst, "currentText" );
21270 gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
21271 currentText = ( !navigationAsDateFormat ? currentText :
21272 this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
21273
21274 controls = "";
21275 if ( !inst.inline ) {
21276 controls = $( "<button>" )
21277 .attr( {
21278 type: "button",
21279 "class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all",
21280 "data-handler": "hide",
21281 "data-event": "click"
21282 } )
21283 .text( this._get( inst, "closeText" ) )[ 0 ].outerHTML;
21284 }
21285
21286 buttonPanel = "";
21287 if ( showButtonPanel ) {
21288 buttonPanel = $( "<div class='ui-datepicker-buttonpane ui-widget-content'>" )
21289 .append( isRTL ? controls : "" )
21290 .append( this._isInRange( inst, gotoDate ) ?
21291 $( "<button>" )
21292 .attr( {
21293 type: "button",
21294 "class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all",
21295 "data-handler": "today",
21296 "data-event": "click"
21297 } )
21298 .text( currentText ) :
21299 "" )
21300 .append( isRTL ? "" : controls )[ 0 ].outerHTML;
21301 }
21302
21303 firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
21304 firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
21305
21306 showWeek = this._get( inst, "showWeek" );
21307 dayNames = this._get( inst, "dayNames" );
21308 dayNamesMin = this._get( inst, "dayNamesMin" );
21309 monthNames = this._get( inst, "monthNames" );
21310 monthNamesShort = this._get( inst, "monthNamesShort" );
21311 beforeShowDay = this._get( inst, "beforeShowDay" );
21312 showOtherMonths = this._get( inst, "showOtherMonths" );
21313 selectOtherMonths = this._get( inst, "selectOtherMonths" );
21314 defaultDate = this._getDefaultDate( inst );
21315 html = "";
21316
21317 for ( row = 0; row < numMonths[ 0 ]; row++ ) {
21318 group = "";
21319 this.maxRows = 4;
21320 for ( col = 0; col < numMonths[ 1 ]; col++ ) {
21321 selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
21322 cornerClass = " ui-corner-all";
21323 calender = "";
21324 if ( isMultiMonth ) {
21325 calender += "<div class='ui-datepicker-group";
21326 if ( numMonths[ 1 ] > 1 ) {
21327 switch ( col ) {
21328 case 0: calender += " ui-datepicker-group-first";
21329 cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
21330 case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
21331 cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
21332 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
21333 }
21334 }
21335 calender += "'>";
21336 }
21337 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
21338 ( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
21339 ( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
21340 this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
21341 row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
21342 "</div><table class='ui-datepicker-calendar'><thead>" +
21343 "<tr>";
21344 thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
21345 for ( dow = 0; dow < 7; dow++ ) { // days of the week
21346 day = ( dow + firstDay ) % 7;
21347 thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
21348 "<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
21349 }
21350 calender += thead + "</tr></thead><tbody>";
21351 daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
21352 if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
21353 inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
21354 }
21355 leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
21356 curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
21357 numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
21358 this.maxRows = numRows;
21359 printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
21360 for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
21361 calender += "<tr>";
21362 tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
21363 this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
21364 for ( dow = 0; dow < 7; dow++ ) { // create date picker days
21365 daySettings = ( beforeShowDay ?
21366 beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
21367 otherMonth = ( printDate.getMonth() !== drawMonth );
21368 unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
21369 ( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
21370 tbody += "<td class='" +
21371 ( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
21372 ( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
21373 ( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
21374 ( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
21375
21376 // or defaultDate is current printedDate and defaultDate is selectedDate
21377 " " + this._dayOverClass : "" ) + // highlight selected day
21378 ( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) + // highlight unselectable days
21379 ( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
21380 ( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
21381 ( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
21382 ( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "&#39;" ) + "'" : "" ) + // cell title
21383 ( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
21384 ( otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
21385 ( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
21386 ( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
21387 ( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
21388 ( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
21389 "' href='#' aria-current='" + ( printDate.getTime() === currentDate.getTime() ? "true" : "false" ) + // mark date as selected for screen reader
21390 "' data-date='" + printDate.getDate() + // store date as data
21391 "'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
21392 printDate.setDate( printDate.getDate() + 1 );
21393 printDate = this._daylightSavingAdjust( printDate );
21394 }
21395 calender += tbody + "</tr>";
21396 }
21397 drawMonth++;
21398 if ( drawMonth > 11 ) {
21399 drawMonth = 0;
21400 drawYear++;
21401 }
21402 calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
21403 ( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
21404 group += calender;
21405 }
21406 html += group;
21407 }
21408 html += buttonPanel;
21409 inst._keyEvent = false;
21410 return html;
21411 },
21412
21413 /* Generate the month and year header. */
21414 _generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
21415 secondary, monthNames, monthNamesShort ) {
21416
21417 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
21418 changeMonth = this._get( inst, "changeMonth" ),
21419 changeYear = this._get( inst, "changeYear" ),
21420 showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
21421 selectMonthLabel = this._get( inst, "selectMonthLabel" ),
21422 selectYearLabel = this._get( inst, "selectYearLabel" ),
21423 html = "<div class='ui-datepicker-title'>",
21424 monthHtml = "";
21425
21426 // Month selection
21427 if ( secondary || !changeMonth ) {
21428 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
21429 } else {
21430 inMinYear = ( minDate && minDate.getFullYear() === drawYear );
21431 inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
21432 monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>";
21433 for ( month = 0; month < 12; month++ ) {
21434 if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
21435 monthHtml += "<option value='" + month + "'" +
21436 ( month === drawMonth ? " selected='selected'" : "" ) +
21437 ">" + monthNamesShort[ month ] + "</option>";
21438 }
21439 }
21440 monthHtml += "</select>";
21441 }
21442
21443 if ( !showMonthAfterYear ) {
21444 html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" );
21445 }
21446
21447 // Year selection
21448 if ( !inst.yearshtml ) {
21449 inst.yearshtml = "";
21450 if ( secondary || !changeYear ) {
21451 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
21452 } else {
21453
21454 // determine range of years to display
21455 years = this._get( inst, "yearRange" ).split( ":" );
21456 thisYear = new Date().getFullYear();
21457 determineYear = function( value ) {
21458 var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
21459 ( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
21460 parseInt( value, 10 ) ) );
21461 return ( isNaN( year ) ? thisYear : year );
21462 };
21463 year = determineYear( years[ 0 ] );
21464 endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
21465 year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
21466 endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
21467 inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>";
21468 for ( ; year <= endYear; year++ ) {
21469 inst.yearshtml += "<option value='" + year + "'" +
21470 ( year === drawYear ? " selected='selected'" : "" ) +
21471 ">" + year + "</option>";
21472 }
21473 inst.yearshtml += "</select>";
21474
21475 html += inst.yearshtml;
21476 inst.yearshtml = null;
21477 }
21478 }
21479
21480 html += this._get( inst, "yearSuffix" );
21481 if ( showMonthAfterYear ) {
21482 html += ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" ) + monthHtml;
21483 }
21484 html += "</div>"; // Close datepicker_header
21485 return html;
21486 },
21487
21488 /* Adjust one of the date sub-fields. */
21489 _adjustInstDate: function( inst, offset, period ) {
21490 var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
21491 month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
21492 day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
21493 date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
21494
21495 inst.selectedDay = date.getDate();
21496 inst.drawMonth = inst.selectedMonth = date.getMonth();
21497 inst.drawYear = inst.selectedYear = date.getFullYear();
21498 if ( period === "M" || period === "Y" ) {
21499 this._notifyChange( inst );
21500 }
21501 },
21502
21503 /* Ensure a date is within any min/max bounds. */
21504 _restrictMinMax: function( inst, date ) {
21505 var minDate = this._getMinMaxDate( inst, "min" ),
21506 maxDate = this._getMinMaxDate( inst, "max" ),
21507 newDate = ( minDate && date < minDate ? minDate : date );
21508 return ( maxDate && newDate > maxDate ? maxDate : newDate );
21509 },
21510
21511 /* Notify change of month/year. */
21512 _notifyChange: function( inst ) {
21513 var onChange = this._get( inst, "onChangeMonthYear" );
21514 if ( onChange ) {
21515 onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
21516 [ inst.selectedYear, inst.selectedMonth + 1, inst ] );
21517 }
21518 },
21519
21520 /* Determine the number of months to show. */
21521 _getNumberOfMonths: function( inst ) {
21522 var numMonths = this._get( inst, "numberOfMonths" );
21523 return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
21524 },
21525
21526 /* Determine the current maximum date - ensure no time components are set. */
21527 _getMinMaxDate: function( inst, minMax ) {
21528 return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
21529 },
21530
21531 /* Find the number of days in a given month. */
21532 _getDaysInMonth: function( year, month ) {
21533 return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
21534 },
21535
21536 /* Find the day of the week of the first of a month. */
21537 _getFirstDayOfMonth: function( year, month ) {
21538 return new Date( year, month, 1 ).getDay();
21539 },
21540
21541 /* Determines if we should allow a "next/prev" month display change. */
21542 _canAdjustMonth: function( inst, offset, curYear, curMonth ) {
21543 var numMonths = this._getNumberOfMonths( inst ),
21544 date = this._daylightSavingAdjust( new Date( curYear,
21545 curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
21546
21547 if ( offset < 0 ) {
21548 date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
21549 }
21550 return this._isInRange( inst, date );
21551 },
21552
21553 /* Is the given date in the accepted range? */
21554 _isInRange: function( inst, date ) {
21555 var yearSplit, currentYear,
21556 minDate = this._getMinMaxDate( inst, "min" ),
21557 maxDate = this._getMinMaxDate( inst, "max" ),
21558 minYear = null,
21559 maxYear = null,
21560 years = this._get( inst, "yearRange" );
21561 if ( years ) {
21562 yearSplit = years.split( ":" );
21563 currentYear = new Date().getFullYear();
21564 minYear = parseInt( yearSplit[ 0 ], 10 );
21565 maxYear = parseInt( yearSplit[ 1 ], 10 );
21566 if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
21567 minYear += currentYear;
21568 }
21569 if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
21570 maxYear += currentYear;
21571 }
21572 }
21573
21574 return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
21575 ( !maxDate || date.getTime() <= maxDate.getTime() ) &&
21576 ( !minYear || date.getFullYear() >= minYear ) &&
21577 ( !maxYear || date.getFullYear() <= maxYear ) );
21578 },
21579
21580 /* Provide the configuration settings for formatting/parsing. */
21581 _getFormatConfig: function( inst ) {
21582 var shortYearCutoff = this._get( inst, "shortYearCutoff" );
21583 shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
21584 new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
21585 return { shortYearCutoff: shortYearCutoff,
21586 dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
21587 monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
21588 },
21589
21590 /* Format the given date for display. */
21591 _formatDate: function( inst, day, month, year ) {
21592 if ( !day ) {
21593 inst.currentDay = inst.selectedDay;
21594 inst.currentMonth = inst.selectedMonth;
21595 inst.currentYear = inst.selectedYear;
21596 }
21597 var date = ( day ? ( typeof day === "object" ? day :
21598 this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
21599 this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
21600 return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
21601 }
21602} );
21603
21604/*
21605 * Bind hover events for datepicker elements.
21606 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
21607 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
21608 */
21609function datepicker_bindHover( dpDiv ) {
21610 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
21611 return dpDiv.on( "mouseout", selector, function() {
21612 $( this ).removeClass( "ui-state-hover" );
21613 if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
21614 $( this ).removeClass( "ui-datepicker-prev-hover" );
21615 }
21616 if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
21617 $( this ).removeClass( "ui-datepicker-next-hover" );
21618 }
21619 } )
21620 .on( "mouseover", selector, datepicker_handleMouseover );
21621}
21622
21623function datepicker_handleMouseover() {
21624 if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
21625 $( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
21626 $( this ).addClass( "ui-state-hover" );
21627 if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
21628 $( this ).addClass( "ui-datepicker-prev-hover" );
21629 }
21630 if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
21631 $( this ).addClass( "ui-datepicker-next-hover" );
21632 }
21633 }
21634}
21635
21636/* jQuery extend now ignores nulls! */
21637function datepicker_extendRemove( target, props ) {
21638 $.extend( target, props );
21639 for ( var name in props ) {
21640 if ( props[ name ] == null ) {
21641 target[ name ] = props[ name ];
21642 }
21643 }
21644 return target;
21645}
21646
21647/* Invoke the datepicker functionality.
21648 @param options string - a command, optionally followed by additional parameters or
21649 Object - settings for attaching new datepicker functionality
21650 @return jQuery object */
21651$.fn.datepicker = function( options ) {
21652
21653 /* Verify an empty collection wasn't passed - Fixes #6976 */
21654 if ( !this.length ) {
21655 return this;
21656 }
21657
21658 /* Initialise the date picker. */
21659 if ( !$.datepicker.initialized ) {
21660 $( document ).on( "mousedown", $.datepicker._checkExternalClick );
21661 $.datepicker.initialized = true;
21662 }
21663
21664 /* Append datepicker main container to body if not exist. */
21665 if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
21666 $( "body" ).append( $.datepicker.dpDiv );
21667 }
21668
21669 var otherArgs = Array.prototype.slice.call( arguments, 1 );
21670 if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
21671 return $.datepicker[ "_" + options + "Datepicker" ].
21672 apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
21673 }
21674 if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
21675 return $.datepicker[ "_" + options + "Datepicker" ].
21676 apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
21677 }
21678 return this.each( function() {
21679 if ( typeof options === "string" ) {
21680 $.datepicker[ "_" + options + "Datepicker" ]
21681 .apply( $.datepicker, [ this ].concat( otherArgs ) );
21682 } else {
21683 $.datepicker._attachDatepicker( this, options );
21684 }
21685 } );
21686};
21687
21688$.datepicker = new Datepicker(); // singleton instance
21689$.datepicker.initialized = false;
21690$.datepicker.uuid = new Date().getTime();
21691$.datepicker.version = "1.14.1";
21692
21693return $.datepicker;
21694
21695} );
21696
21697
21698
21699/*!
21700 * jQuery UI Mouse 1.14.1
21701 * https://jqueryui.com
21702 *
21703 * Copyright OpenJS Foundation and other contributors
21704 * Released under the MIT license.
21705 * https://jquery.org/license
21706 */
21707
21708//>>label: Mouse
21709//>>group: Widgets
21710//>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
21711//>>docs: https://api.jqueryui.com/mouse/
21712
21713( function( factory ) {
21714 "use strict";
21715
21716 if ( typeof define === "function" && define.amd ) {
21717
21718 // AMD. Register as an anonymous module.
21719 define( [
21720 "jquery",
21721 "../version",
21722 "../widget"
21723 ], factory );
21724 } else {
21725
21726 // Browser globals
21727 factory( jQuery );
21728 }
21729} )( function( $ ) {
21730"use strict";
21731
21732var mouseHandled = false;
21733$( document ).on( "mouseup", function() {
21734 mouseHandled = false;
21735} );
21736
21737return $.widget( "ui.mouse", {
21738 version: "1.14.1",
21739 options: {
21740 cancel: "input, textarea, button, select, option",
21741 distance: 1,
21742 delay: 0
21743 },
21744 _mouseInit: function() {
21745 var that = this;
21746
21747 this.element
21748 .on( "mousedown." + this.widgetName, function( event ) {
21749 return that._mouseDown( event );
21750 } )
21751 .on( "click." + this.widgetName, function( event ) {
21752 if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
21753 $.removeData( event.target, that.widgetName + ".preventClickEvent" );
21754 event.stopImmediatePropagation();
21755 return false;
21756 }
21757 } );
21758
21759 this.started = false;
21760 },
21761
21762 // TODO: make sure destroying one instance of mouse doesn't mess with
21763 // other instances of mouse
21764 _mouseDestroy: function() {
21765 this.element.off( "." + this.widgetName );
21766 if ( this._mouseMoveDelegate ) {
21767 this.document
21768 .off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
21769 .off( "mouseup." + this.widgetName, this._mouseUpDelegate );
21770 }
21771 },
21772
21773 _mouseDown: function( event ) {
21774
21775 // don't let more than one widget handle mouseStart
21776 if ( mouseHandled ) {
21777 return;
21778 }
21779
21780 this._mouseMoved = false;
21781
21782 // We may have missed mouseup (out of window)
21783 if ( this._mouseStarted ) {
21784 this._mouseUp( event );
21785 }
21786
21787 this._mouseDownEvent = event;
21788
21789 var that = this,
21790 btnIsLeft = event.which === 1,
21791 elIsCancel = typeof this.options.cancel === "string" ?
21792 $( event.target ).closest( this.options.cancel ).length :
21793 false;
21794 if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
21795 return true;
21796 }
21797
21798 this.mouseDelayMet = !this.options.delay;
21799 if ( !this.mouseDelayMet ) {
21800 this._mouseDelayTimer = setTimeout( function() {
21801 that.mouseDelayMet = true;
21802 }, this.options.delay );
21803 }
21804
21805 if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
21806 this._mouseStarted = ( this._mouseStart( event ) !== false );
21807 if ( !this._mouseStarted ) {
21808 event.preventDefault();
21809 return true;
21810 }
21811 }
21812
21813 // Click event may never have fired (Gecko & Opera)
21814 if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
21815 $.removeData( event.target, this.widgetName + ".preventClickEvent" );
21816 }
21817
21818 // These delegates are required to keep context
21819 this._mouseMoveDelegate = function( event ) {
21820 return that._mouseMove( event );
21821 };
21822 this._mouseUpDelegate = function( event ) {
21823 return that._mouseUp( event );
21824 };
21825
21826 this.document
21827 .on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
21828 .on( "mouseup." + this.widgetName, this._mouseUpDelegate );
21829
21830 event.preventDefault();
21831
21832 mouseHandled = true;
21833 return true;
21834 },
21835
21836 _mouseMove: function( event ) {
21837
21838 // Only check for mouseups outside the document if you've moved inside the document
21839 // at least once.
21840 if ( this._mouseMoved && !event.which ) {
21841
21842 // Support: Safari <=8 - 9
21843 // Safari sets which to 0 if you press any of the following keys
21844 // during a drag (#14461)
21845 if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
21846 event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
21847 this.ignoreMissingWhich = true;
21848 } else if ( !this.ignoreMissingWhich ) {
21849 return this._mouseUp( event );
21850 }
21851 }
21852
21853 if ( event.which || event.button ) {
21854 this._mouseMoved = true;
21855 }
21856
21857 if ( this._mouseStarted ) {
21858 this._mouseDrag( event );
21859 return event.preventDefault();
21860 }
21861
21862 if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
21863 this._mouseStarted =
21864 ( this._mouseStart( this._mouseDownEvent, event ) !== false );
21865 if ( this._mouseStarted ) {
21866 this._mouseDrag( event );
21867 } else {
21868 this._mouseUp( event );
21869 }
21870 }
21871
21872 return !this._mouseStarted;
21873 },
21874
21875 _mouseUp: function( event ) {
21876 this.document
21877 .off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
21878 .off( "mouseup." + this.widgetName, this._mouseUpDelegate );
21879
21880 if ( this._mouseStarted ) {
21881 this._mouseStarted = false;
21882
21883 if ( event.target === this._mouseDownEvent.target ) {
21884 $.data( event.target, this.widgetName + ".preventClickEvent", true );
21885 }
21886
21887 this._mouseStop( event );
21888 }
21889
21890 if ( this._mouseDelayTimer ) {
21891 clearTimeout( this._mouseDelayTimer );
21892 delete this._mouseDelayTimer;
21893 }
21894
21895 this.ignoreMissingWhich = false;
21896 mouseHandled = false;
21897 event.preventDefault();
21898 },
21899
21900 _mouseDistanceMet: function( event ) {
21901 return ( Math.max(
21902 Math.abs( this._mouseDownEvent.pageX - event.pageX ),
21903 Math.abs( this._mouseDownEvent.pageY - event.pageY )
21904 ) >= this.options.distance
21905 );
21906 },
21907
21908 _mouseDelayMet: function( /* event */ ) {
21909 return this.mouseDelayMet;
21910 },
21911
21912 // These are placeholder methods, to be overriden by extending plugin
21913 _mouseStart: function( /* event */ ) {},
21914 _mouseDrag: function( /* event */ ) {},
21915 _mouseStop: function( /* event */ ) {},
21916 _mouseCapture: function( /* event */ ) {
21917 return true;
21918 }
21919} );
21920
21921} );
21922
21923
21924
21925
21926
21927
21928
21929/*!
21930 * jQuery UI Draggable 1.14.1
21931 * https://jqueryui.com
21932 *
21933 * Copyright OpenJS Foundation and other contributors
21934 * Released under the MIT license.
21935 * https://jquery.org/license
21936 */
21937
21938//>>label: Draggable
21939//>>group: Interactions
21940//>>description: Enables dragging functionality for any element.
21941//>>docs: https://api.jqueryui.com/draggable/
21942//>>demos: https://jqueryui.com/draggable/
21943//>>css.structure: ../../themes/base/draggable.css
21944
21945( function( factory ) {
21946 "use strict";
21947
21948 if ( typeof define === "function" && define.amd ) {
21949
21950 // AMD. Register as an anonymous module.
21951 define( [
21952 "jquery",
21953 "./mouse",
21954 "../data",
21955 "../plugin",
21956 "../scroll-parent",
21957 "../version",
21958 "../widget"
21959 ], factory );
21960 } else {
21961
21962 // Browser globals
21963 factory( jQuery );
21964 }
21965} )( function( $ ) {
21966"use strict";
21967
21968$.widget( "ui.draggable", $.ui.mouse, {
21969 version: "1.14.1",
21970 widgetEventPrefix: "drag",
21971 options: {
21972 addClasses: true,
21973 appendTo: "parent",
21974 axis: false,
21975 connectToSortable: false,
21976 containment: false,
21977 cursor: "auto",
21978 cursorAt: false,
21979 grid: false,
21980 handle: false,
21981 helper: "original",
21982 iframeFix: false,
21983 opacity: false,
21984 refreshPositions: false,
21985 revert: false,
21986 revertDuration: 500,
21987 scope: "default",
21988 scroll: true,
21989 scrollSensitivity: 20,
21990 scrollSpeed: 20,
21991 snap: false,
21992 snapMode: "both",
21993 snapTolerance: 20,
21994 stack: false,
21995 zIndex: false,
21996
21997 // Callbacks
21998 drag: null,
21999 start: null,
22000 stop: null
22001 },
22002 _create: function() {
22003
22004 if ( this.options.helper === "original" ) {
22005 this._setPositionRelative();
22006 }
22007 if ( this.options.addClasses ) {
22008 this._addClass( "ui-draggable" );
22009 }
22010 this._setHandleClassName();
22011
22012 this._mouseInit();
22013 },
22014
22015 _setOption: function( key, value ) {
22016 this._super( key, value );
22017 if ( key === "handle" ) {
22018 this._removeHandleClassName();
22019 this._setHandleClassName();
22020 }
22021 },
22022
22023 _destroy: function() {
22024 if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
22025 this.destroyOnClear = true;
22026 return;
22027 }
22028 this._removeHandleClassName();
22029 this._mouseDestroy();
22030 },
22031
22032 _mouseCapture: function( event ) {
22033 var o = this.options;
22034
22035 // Among others, prevent a drag on a resizable-handle
22036 if ( this.helper || o.disabled ||
22037 $( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) {
22038 return false;
22039 }
22040
22041 //Quit if we're not on a valid handle
22042 this.handle = this._getHandle( event );
22043 if ( !this.handle ) {
22044 return false;
22045 }
22046
22047 this._blurActiveElement( event );
22048
22049 this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
22050
22051 return true;
22052
22053 },
22054
22055 _blockFrames: function( selector ) {
22056 this.iframeBlocks = this.document.find( selector ).map( function() {
22057 var iframe = $( this );
22058
22059 return $( "<div>" )
22060 .css( "position", "absolute" )
22061 .appendTo( iframe.parent() )
22062 .outerWidth( iframe.outerWidth() )
22063 .outerHeight( iframe.outerHeight() )
22064 .offset( iframe.offset() )[ 0 ];
22065 } );
22066 },
22067
22068 _unblockFrames: function() {
22069 if ( this.iframeBlocks ) {
22070 this.iframeBlocks.remove();
22071 delete this.iframeBlocks;
22072 }
22073 },
22074
22075 _blurActiveElement: function( event ) {
22076 var activeElement = this.document[ 0 ].activeElement,
22077 target = $( event.target );
22078
22079 // Don't blur if the event occurred on an element that is within
22080 // the currently focused element
22081 // See #10527, #12472
22082 if ( target.closest( activeElement ).length ) {
22083 return;
22084 }
22085
22086 // Blur any element that currently has focus, see #4261
22087 $( activeElement ).trigger( "blur" );
22088 },
22089
22090 _mouseStart: function( event ) {
22091
22092 var o = this.options;
22093
22094 //Create and append the visible helper
22095 this.helper = this._createHelper( event );
22096
22097 this._addClass( this.helper, "ui-draggable-dragging" );
22098
22099 //Cache the helper size
22100 this._cacheHelperProportions();
22101
22102 //If ddmanager is used for droppables, set the global draggable
22103 if ( $.ui.ddmanager ) {
22104 $.ui.ddmanager.current = this;
22105 }
22106
22107 /*
22108 * - Position generation -
22109 * This block generates everything position related - it's the core of draggables.
22110 */
22111
22112 //Cache the margins of the original element
22113 this._cacheMargins();
22114
22115 //Store the helper's css position
22116 this.cssPosition = this.helper.css( "position" );
22117 this.scrollParent = this.helper.scrollParent( true );
22118 this.offsetParent = this.helper.offsetParent();
22119 this.hasFixedAncestor = this.helper.parents().filter( function() {
22120 return $( this ).css( "position" ) === "fixed";
22121 } ).length > 0;
22122
22123 //The element's absolute position on the page minus margins
22124 this.positionAbs = this.element.offset();
22125 this._refreshOffsets( event );
22126
22127 //Generate the original position
22128 this.originalPosition = this.position = this._generatePosition( event, false );
22129 this.originalPageX = event.pageX;
22130 this.originalPageY = event.pageY;
22131
22132 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
22133 if ( o.cursorAt ) {
22134 this._adjustOffsetFromHelper( o.cursorAt );
22135 }
22136
22137 //Set a containment if given in the options
22138 this._setContainment();
22139
22140 //Trigger event + callbacks
22141 if ( this._trigger( "start", event ) === false ) {
22142 this._clear();
22143 return false;
22144 }
22145
22146 //Recache the helper size
22147 this._cacheHelperProportions();
22148
22149 //Prepare the droppable offsets
22150 if ( $.ui.ddmanager && !o.dropBehaviour ) {
22151 $.ui.ddmanager.prepareOffsets( this, event );
22152 }
22153
22154 // Execute the drag once - this causes the helper not to be visible before getting its
22155 // correct position
22156 this._mouseDrag( event, true );
22157
22158 // If the ddmanager is used for droppables, inform the manager that dragging has started
22159 // (see #5003)
22160 if ( $.ui.ddmanager ) {
22161 $.ui.ddmanager.dragStart( this, event );
22162 }
22163
22164 return true;
22165 },
22166
22167 _refreshOffsets: function( event ) {
22168 this.offset = {
22169 top: this.positionAbs.top - this.margins.top,
22170 left: this.positionAbs.left - this.margins.left,
22171 scroll: false,
22172 parent: this._getParentOffset(),
22173 relative: this._getRelativeOffset()
22174 };
22175
22176 this.offset.click = {
22177 left: event.pageX - this.offset.left,
22178 top: event.pageY - this.offset.top
22179 };
22180 },
22181
22182 _mouseDrag: function( event, noPropagation ) {
22183
22184 // reset any necessary cached properties (see #5009)
22185 if ( this.hasFixedAncestor ) {
22186 this.offset.parent = this._getParentOffset();
22187 }
22188
22189 //Compute the helpers position
22190 this.position = this._generatePosition( event, true );
22191 this.positionAbs = this._convertPositionTo( "absolute" );
22192
22193 //Call plugins and callbacks and use the resulting position if something is returned
22194 if ( !noPropagation ) {
22195 var ui = this._uiHash();
22196 if ( this._trigger( "drag", event, ui ) === false ) {
22197 this._mouseUp( new $.Event( "mouseup", event ) );
22198 return false;
22199 }
22200 this.position = ui.position;
22201 }
22202
22203 this.helper[ 0 ].style.left = this.position.left + "px";
22204 this.helper[ 0 ].style.top = this.position.top + "px";
22205
22206 if ( $.ui.ddmanager ) {
22207 $.ui.ddmanager.drag( this, event );
22208 }
22209
22210 return false;
22211 },
22212
22213 _mouseStop: function( event ) {
22214
22215 //If we are using droppables, inform the manager about the drop
22216 var that = this,
22217 dropped = false;
22218 if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
22219 dropped = $.ui.ddmanager.drop( this, event );
22220 }
22221
22222 //if a drop comes from outside (a sortable)
22223 if ( this.dropped ) {
22224 dropped = this.dropped;
22225 this.dropped = false;
22226 }
22227
22228 if ( ( this.options.revert === "invalid" && !dropped ) ||
22229 ( this.options.revert === "valid" && dropped ) ||
22230 this.options.revert === true || ( typeof this.options.revert === "function" &&
22231 this.options.revert.call( this.element, dropped ) )
22232 ) {
22233 $( this.helper ).animate(
22234 this.originalPosition,
22235 parseInt( this.options.revertDuration, 10 ),
22236 function() {
22237 if ( that._trigger( "stop", event ) !== false ) {
22238 that._clear();
22239 }
22240 }
22241 );
22242 } else {
22243 if ( this._trigger( "stop", event ) !== false ) {
22244 this._clear();
22245 }
22246 }
22247
22248 return false;
22249 },
22250
22251 _mouseUp: function( event ) {
22252 this._unblockFrames();
22253
22254 // If the ddmanager is used for droppables, inform the manager that dragging has stopped
22255 // (see #5003)
22256 if ( $.ui.ddmanager ) {
22257 $.ui.ddmanager.dragStop( this, event );
22258 }
22259
22260 // Only need to focus if the event occurred on the draggable itself, see #10527
22261 if ( this.handleElement.is( event.target ) ) {
22262
22263 // The interaction is over; whether or not the click resulted in a drag,
22264 // focus the element
22265 this.element.trigger( "focus" );
22266 }
22267
22268 return $.ui.mouse.prototype._mouseUp.call( this, event );
22269 },
22270
22271 cancel: function() {
22272
22273 if ( this.helper.is( ".ui-draggable-dragging" ) ) {
22274 this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) );
22275 } else {
22276 this._clear();
22277 }
22278
22279 return this;
22280
22281 },
22282
22283 _getHandle: function( event ) {
22284 return this.options.handle ?
22285 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
22286 true;
22287 },
22288
22289 _setHandleClassName: function() {
22290 this.handleElement = this.options.handle ?
22291 this.element.find( this.options.handle ) : this.element;
22292 this._addClass( this.handleElement, "ui-draggable-handle" );
22293 },
22294
22295 _removeHandleClassName: function() {
22296 this._removeClass( this.handleElement, "ui-draggable-handle" );
22297 },
22298
22299 _createHelper: function( event ) {
22300
22301 var o = this.options,
22302 helperIsFunction = typeof o.helper === "function",
22303 helper = helperIsFunction ?
22304 $( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
22305 ( o.helper === "clone" ?
22306 this.element.clone().removeAttr( "id" ) :
22307 this.element );
22308
22309 if ( !helper.parents( "body" ).length ) {
22310 helper.appendTo( ( o.appendTo === "parent" ?
22311 this.element[ 0 ].parentNode :
22312 o.appendTo ) );
22313 }
22314
22315 // https://bugs.jqueryui.com/ticket/9446
22316 // a helper function can return the original element
22317 // which wouldn't have been set to relative in _create
22318 if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
22319 this._setPositionRelative();
22320 }
22321
22322 if ( helper[ 0 ] !== this.element[ 0 ] &&
22323 !( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
22324 helper.css( "position", "absolute" );
22325 }
22326
22327 return helper;
22328
22329 },
22330
22331 _setPositionRelative: function() {
22332 if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
22333 this.element[ 0 ].style.position = "relative";
22334 }
22335 },
22336
22337 _adjustOffsetFromHelper: function( obj ) {
22338 if ( typeof obj === "string" ) {
22339 obj = obj.split( " " );
22340 }
22341 if ( Array.isArray( obj ) ) {
22342 obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
22343 }
22344 if ( "left" in obj ) {
22345 this.offset.click.left = obj.left + this.margins.left;
22346 }
22347 if ( "right" in obj ) {
22348 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
22349 }
22350 if ( "top" in obj ) {
22351 this.offset.click.top = obj.top + this.margins.top;
22352 }
22353 if ( "bottom" in obj ) {
22354 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
22355 }
22356 },
22357
22358 _isRootNode: function( element ) {
22359 return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
22360 },
22361
22362 _getParentOffset: function() {
22363
22364 //Get the offsetParent and cache its position
22365 var po = this.offsetParent.offset(),
22366 document = this.document[ 0 ];
22367
22368 // This is a special case where we need to modify a offset calculated on start, since the
22369 // following happened:
22370 // 1. The position of the helper is absolute, so it's position is calculated based on the
22371 // next positioned parent
22372 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
22373 // the document, which means that the scroll is included in the initial calculation of the
22374 // offset of the parent, and never recalculated upon drag
22375 if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document &&
22376 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
22377 po.left += this.scrollParent.scrollLeft();
22378 po.top += this.scrollParent.scrollTop();
22379 }
22380
22381 if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
22382 po = { top: 0, left: 0 };
22383 }
22384
22385 return {
22386 top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
22387 left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
22388 };
22389
22390 },
22391
22392 _getRelativeOffset: function() {
22393 if ( this.cssPosition !== "relative" ) {
22394 return { top: 0, left: 0 };
22395 }
22396
22397 var p = this.element.position(),
22398 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
22399
22400 return {
22401 top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
22402 ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
22403 left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
22404 ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
22405 };
22406
22407 },
22408
22409 _cacheMargins: function() {
22410 this.margins = {
22411 left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ),
22412 top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ),
22413 right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ),
22414 bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 )
22415 };
22416 },
22417
22418 _cacheHelperProportions: function() {
22419 this.helperProportions = {
22420 width: this.helper.outerWidth(),
22421 height: this.helper.outerHeight()
22422 };
22423 },
22424
22425 _setContainment: function() {
22426
22427 var isUserScrollable, c, ce,
22428 o = this.options,
22429 document = this.document[ 0 ];
22430
22431 this.relativeContainer = null;
22432
22433 if ( !o.containment ) {
22434 this.containment = null;
22435 return;
22436 }
22437
22438 if ( o.containment === "window" ) {
22439 this.containment = [
22440 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
22441 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
22442 $( window ).scrollLeft() + $( window ).width() -
22443 this.helperProportions.width - this.margins.left,
22444 $( window ).scrollTop() +
22445 ( $( window ).height() || document.body.parentNode.scrollHeight ) -
22446 this.helperProportions.height - this.margins.top
22447 ];
22448 return;
22449 }
22450
22451 if ( o.containment === "document" ) {
22452 this.containment = [
22453 0,
22454 0,
22455 $( document ).width() - this.helperProportions.width - this.margins.left,
22456 ( $( document ).height() || document.body.parentNode.scrollHeight ) -
22457 this.helperProportions.height - this.margins.top
22458 ];
22459 return;
22460 }
22461
22462 if ( o.containment.constructor === Array ) {
22463 this.containment = o.containment;
22464 return;
22465 }
22466
22467 if ( o.containment === "parent" ) {
22468 o.containment = this.helper[ 0 ].parentNode;
22469 }
22470
22471 c = $( o.containment );
22472 ce = c[ 0 ];
22473
22474 if ( !ce ) {
22475 return;
22476 }
22477
22478 isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
22479
22480 this.containment = [
22481 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
22482 ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
22483 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
22484 ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
22485 ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
22486 ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
22487 ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
22488 this.helperProportions.width -
22489 this.margins.left -
22490 this.margins.right,
22491 ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
22492 ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
22493 ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
22494 this.helperProportions.height -
22495 this.margins.top -
22496 this.margins.bottom
22497 ];
22498 this.relativeContainer = c;
22499 },
22500
22501 _convertPositionTo: function( d, pos ) {
22502
22503 if ( !pos ) {
22504 pos = this.position;
22505 }
22506
22507 var mod = d === "absolute" ? 1 : -1,
22508 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
22509
22510 return {
22511 top: (
22512
22513 // The absolute mouse position
22514 pos.top +
22515
22516 // Only for relative positioned nodes: Relative offset from element to offset parent
22517 this.offset.relative.top * mod +
22518
22519 // The offsetParent's offset without borders (offset + border)
22520 this.offset.parent.top * mod -
22521 ( ( this.cssPosition === "fixed" ?
22522 -this.offset.scroll.top :
22523 ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
22524 ),
22525 left: (
22526
22527 // The absolute mouse position
22528 pos.left +
22529
22530 // Only for relative positioned nodes: Relative offset from element to offset parent
22531 this.offset.relative.left * mod +
22532
22533 // The offsetParent's offset without borders (offset + border)
22534 this.offset.parent.left * mod -
22535 ( ( this.cssPosition === "fixed" ?
22536 -this.offset.scroll.left :
22537 ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
22538 )
22539 };
22540
22541 },
22542
22543 _generatePosition: function( event, constrainPosition ) {
22544
22545 var containment, co, top, left,
22546 o = this.options,
22547 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
22548 pageX = event.pageX,
22549 pageY = event.pageY;
22550
22551 // Cache the scroll
22552 if ( !scrollIsRootNode || !this.offset.scroll ) {
22553 this.offset.scroll = {
22554 top: this.scrollParent.scrollTop(),
22555 left: this.scrollParent.scrollLeft()
22556 };
22557 }
22558
22559 /*
22560 * - Position constraining -
22561 * Constrain the position to a mix of grid, containment.
22562 */
22563
22564 // If we are not dragging yet, we won't check for options
22565 if ( constrainPosition ) {
22566 if ( this.containment ) {
22567 if ( this.relativeContainer ) {
22568 co = this.relativeContainer.offset();
22569 containment = [
22570 this.containment[ 0 ] + co.left,
22571 this.containment[ 1 ] + co.top,
22572 this.containment[ 2 ] + co.left,
22573 this.containment[ 3 ] + co.top
22574 ];
22575 } else {
22576 containment = this.containment;
22577 }
22578
22579 if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
22580 pageX = containment[ 0 ] + this.offset.click.left;
22581 }
22582 if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
22583 pageY = containment[ 1 ] + this.offset.click.top;
22584 }
22585 if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
22586 pageX = containment[ 2 ] + this.offset.click.left;
22587 }
22588 if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
22589 pageY = containment[ 3 ] + this.offset.click.top;
22590 }
22591 }
22592
22593 if ( o.grid ) {
22594
22595 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid
22596 // argument errors in IE (see ticket #6950)
22597 top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
22598 this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;
22599 pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||
22600 top - this.offset.click.top > containment[ 3 ] ) ?
22601 top :
22602 ( ( top - this.offset.click.top >= containment[ 1 ] ) ?
22603 top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;
22604
22605 left = o.grid[ 0 ] ? this.originalPageX +
22606 Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :
22607 this.originalPageX;
22608 pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||
22609 left - this.offset.click.left > containment[ 2 ] ) ?
22610 left :
22611 ( ( left - this.offset.click.left >= containment[ 0 ] ) ?
22612 left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
22613 }
22614
22615 if ( o.axis === "y" ) {
22616 pageX = this.originalPageX;
22617 }
22618
22619 if ( o.axis === "x" ) {
22620 pageY = this.originalPageY;
22621 }
22622 }
22623
22624 return {
22625 top: (
22626
22627 // The absolute mouse position
22628 pageY -
22629
22630 // Click offset (relative to the element)
22631 this.offset.click.top -
22632
22633 // Only for relative positioned nodes: Relative offset from element to offset parent
22634 this.offset.relative.top -
22635
22636 // The offsetParent's offset without borders (offset + border)
22637 this.offset.parent.top +
22638 ( this.cssPosition === "fixed" ?
22639 -this.offset.scroll.top :
22640 ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
22641 ),
22642 left: (
22643
22644 // The absolute mouse position
22645 pageX -
22646
22647 // Click offset (relative to the element)
22648 this.offset.click.left -
22649
22650 // Only for relative positioned nodes: Relative offset from element to offset parent
22651 this.offset.relative.left -
22652
22653 // The offsetParent's offset without borders (offset + border)
22654 this.offset.parent.left +
22655 ( this.cssPosition === "fixed" ?
22656 -this.offset.scroll.left :
22657 ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
22658 )
22659 };
22660
22661 },
22662
22663 _clear: function() {
22664 this._removeClass( this.helper, "ui-draggable-dragging" );
22665 if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {
22666 this.helper.remove();
22667 }
22668 this.helper = null;
22669 this.cancelHelperRemoval = false;
22670 if ( this.destroyOnClear ) {
22671 this.destroy();
22672 }
22673 },
22674
22675 // From now on bulk stuff - mainly helpers
22676
22677 _trigger: function( type, event, ui ) {
22678 ui = ui || this._uiHash();
22679 $.ui.plugin.call( this, type, [ event, ui, this ], true );
22680
22681 // Absolute position and offset (see #6884 ) have to be recalculated after plugins
22682 if ( /^(drag|start|stop)/.test( type ) ) {
22683 this.positionAbs = this._convertPositionTo( "absolute" );
22684 ui.offset = this.positionAbs;
22685 }
22686 return $.Widget.prototype._trigger.call( this, type, event, ui );
22687 },
22688
22689 plugins: {},
22690
22691 _uiHash: function() {
22692 return {
22693 helper: this.helper,
22694 position: this.position,
22695 originalPosition: this.originalPosition,
22696 offset: this.positionAbs
22697 };
22698 }
22699
22700} );
22701
22702$.ui.plugin.add( "draggable", "connectToSortable", {
22703 start: function( event, ui, draggable ) {
22704 var uiSortable = $.extend( {}, ui, {
22705 item: draggable.element
22706 } );
22707
22708 draggable.sortables = [];
22709 $( draggable.options.connectToSortable ).each( function() {
22710 var sortable = $( this ).sortable( "instance" );
22711
22712 if ( sortable && !sortable.options.disabled ) {
22713 draggable.sortables.push( sortable );
22714
22715 // RefreshPositions is called at drag start to refresh the containerCache
22716 // which is used in drag. This ensures it's initialized and synchronized
22717 // with any changes that might have happened on the page since initialization.
22718 sortable.refreshPositions();
22719 sortable._trigger( "activate", event, uiSortable );
22720 }
22721 } );
22722 },
22723 stop: function( event, ui, draggable ) {
22724 var uiSortable = $.extend( {}, ui, {
22725 item: draggable.element
22726 } );
22727
22728 draggable.cancelHelperRemoval = false;
22729
22730 $.each( draggable.sortables, function() {
22731 var sortable = this;
22732
22733 if ( sortable.isOver ) {
22734 sortable.isOver = 0;
22735
22736 // Allow this sortable to handle removing the helper
22737 draggable.cancelHelperRemoval = true;
22738 sortable.cancelHelperRemoval = false;
22739
22740 // Use _storedCSS To restore properties in the sortable,
22741 // as this also handles revert (#9675) since the draggable
22742 // may have modified them in unexpected ways (#8809)
22743 sortable._storedCSS = {
22744 position: sortable.placeholder.css( "position" ),
22745 top: sortable.placeholder.css( "top" ),
22746 left: sortable.placeholder.css( "left" )
22747 };
22748
22749 sortable._mouseStop( event );
22750
22751 // Once drag has ended, the sortable should return to using
22752 // its original helper, not the shared helper from draggable
22753 sortable.options.helper = sortable.options._helper;
22754 } else {
22755
22756 // Prevent this Sortable from removing the helper.
22757 // However, don't set the draggable to remove the helper
22758 // either as another connected Sortable may yet handle the removal.
22759 sortable.cancelHelperRemoval = true;
22760
22761 sortable._trigger( "deactivate", event, uiSortable );
22762 }
22763 } );
22764 },
22765 drag: function( event, ui, draggable ) {
22766 $.each( draggable.sortables, function() {
22767 var innermostIntersecting = false,
22768 sortable = this;
22769
22770 // Copy over variables that sortable's _intersectsWith uses
22771 sortable.positionAbs = draggable.positionAbs;
22772 sortable.helperProportions = draggable.helperProportions;
22773 sortable.offset.click = draggable.offset.click;
22774
22775 if ( sortable._intersectsWith( sortable.containerCache ) ) {
22776 innermostIntersecting = true;
22777
22778 $.each( draggable.sortables, function() {
22779
22780 // Copy over variables that sortable's _intersectsWith uses
22781 this.positionAbs = draggable.positionAbs;
22782 this.helperProportions = draggable.helperProportions;
22783 this.offset.click = draggable.offset.click;
22784
22785 if ( this !== sortable &&
22786 this._intersectsWith( this.containerCache ) &&
22787 $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
22788 innermostIntersecting = false;
22789 }
22790
22791 return innermostIntersecting;
22792 } );
22793 }
22794
22795 if ( innermostIntersecting ) {
22796
22797 // If it intersects, we use a little isOver variable and set it once,
22798 // so that the move-in stuff gets fired only once.
22799 if ( !sortable.isOver ) {
22800 sortable.isOver = 1;
22801
22802 // Store draggable's parent in case we need to reappend to it later.
22803 draggable._parent = ui.helper.parent();
22804
22805 sortable.currentItem = ui.helper
22806 .appendTo( sortable.element )
22807 .data( "ui-sortable-item", true );
22808
22809 // Store helper option to later restore it
22810 sortable.options._helper = sortable.options.helper;
22811
22812 sortable.options.helper = function() {
22813 return ui.helper[ 0 ];
22814 };
22815
22816 // Fire the start events of the sortable with our passed browser event,
22817 // and our own helper (so it doesn't create a new one)
22818 event.target = sortable.currentItem[ 0 ];
22819 sortable._mouseCapture( event, true );
22820 sortable._mouseStart( event, true, true );
22821
22822 // Because the browser event is way off the new appended portlet,
22823 // modify necessary variables to reflect the changes
22824 sortable.offset.click.top = draggable.offset.click.top;
22825 sortable.offset.click.left = draggable.offset.click.left;
22826 sortable.offset.parent.left -= draggable.offset.parent.left -
22827 sortable.offset.parent.left;
22828 sortable.offset.parent.top -= draggable.offset.parent.top -
22829 sortable.offset.parent.top;
22830
22831 draggable._trigger( "toSortable", event );
22832
22833 // Inform draggable that the helper is in a valid drop zone,
22834 // used solely in the revert option to handle "valid/invalid".
22835 draggable.dropped = sortable.element;
22836
22837 // Need to refreshPositions of all sortables in the case that
22838 // adding to one sortable changes the location of the other sortables (#9675)
22839 $.each( draggable.sortables, function() {
22840 this.refreshPositions();
22841 } );
22842
22843 // Hack so receive/update callbacks work (mostly)
22844 draggable.currentItem = draggable.element;
22845 sortable.fromOutside = draggable;
22846 }
22847
22848 if ( sortable.currentItem ) {
22849 sortable._mouseDrag( event );
22850
22851 // Copy the sortable's position because the draggable's can potentially reflect
22852 // a relative position, while sortable is always absolute, which the dragged
22853 // element has now become. (#8809)
22854 ui.position = sortable.position;
22855 }
22856 } else {
22857
22858 // If it doesn't intersect with the sortable, and it intersected before,
22859 // we fake the drag stop of the sortable, but make sure it doesn't remove
22860 // the helper by using cancelHelperRemoval.
22861 if ( sortable.isOver ) {
22862
22863 sortable.isOver = 0;
22864 sortable.cancelHelperRemoval = true;
22865
22866 // Calling sortable's mouseStop would trigger a revert,
22867 // so revert must be temporarily false until after mouseStop is called.
22868 sortable.options._revert = sortable.options.revert;
22869 sortable.options.revert = false;
22870
22871 sortable._trigger( "out", event, sortable._uiHash( sortable ) );
22872 sortable._mouseStop( event, true );
22873
22874 // Restore sortable behaviors that were modfied
22875 // when the draggable entered the sortable area (#9481)
22876 sortable.options.revert = sortable.options._revert;
22877 sortable.options.helper = sortable.options._helper;
22878
22879 if ( sortable.placeholder ) {
22880 sortable.placeholder.remove();
22881 }
22882
22883 // Restore and recalculate the draggable's offset considering the sortable
22884 // may have modified them in unexpected ways. (#8809, #10669)
22885 ui.helper.appendTo( draggable._parent );
22886 draggable._refreshOffsets( event );
22887 ui.position = draggable._generatePosition( event, true );
22888
22889 draggable._trigger( "fromSortable", event );
22890
22891 // Inform draggable that the helper is no longer in a valid drop zone
22892 draggable.dropped = false;
22893
22894 // Need to refreshPositions of all sortables just in case removing
22895 // from one sortable changes the location of other sortables (#9675)
22896 $.each( draggable.sortables, function() {
22897 this.refreshPositions();
22898 } );
22899 }
22900 }
22901 } );
22902 }
22903} );
22904
22905$.ui.plugin.add( "draggable", "cursor", {
22906 start: function( event, ui, instance ) {
22907 var t = $( "body" ),
22908 o = instance.options;
22909
22910 if ( t.css( "cursor" ) ) {
22911 o._cursor = t.css( "cursor" );
22912 }
22913 t.css( "cursor", o.cursor );
22914 },
22915 stop: function( event, ui, instance ) {
22916 var o = instance.options;
22917 if ( o._cursor ) {
22918 $( "body" ).css( "cursor", o._cursor );
22919 }
22920 }
22921} );
22922
22923$.ui.plugin.add( "draggable", "opacity", {
22924 start: function( event, ui, instance ) {
22925 var t = $( ui.helper ),
22926 o = instance.options;
22927 if ( t.css( "opacity" ) ) {
22928 o._opacity = t.css( "opacity" );
22929 }
22930 t.css( "opacity", o.opacity );
22931 },
22932 stop: function( event, ui, instance ) {
22933 var o = instance.options;
22934 if ( o._opacity ) {
22935 $( ui.helper ).css( "opacity", o._opacity );
22936 }
22937 }
22938} );
22939
22940$.ui.plugin.add( "draggable", "scroll", {
22941 start: function( event, ui, i ) {
22942 if ( !i.scrollParentNotHidden ) {
22943 i.scrollParentNotHidden = i.helper.scrollParent( false );
22944 }
22945
22946 if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
22947 i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
22948 i.overflowOffset = i.scrollParentNotHidden.offset();
22949 }
22950 },
22951 drag: function( event, ui, i ) {
22952
22953 var o = i.options,
22954 scrolled = false,
22955 scrollParent = i.scrollParentNotHidden[ 0 ],
22956 document = i.document[ 0 ];
22957
22958 if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
22959 if ( !o.axis || o.axis !== "x" ) {
22960 if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <
22961 o.scrollSensitivity ) {
22962 scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
22963 } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
22964 scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
22965 }
22966 }
22967
22968 if ( !o.axis || o.axis !== "y" ) {
22969 if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <
22970 o.scrollSensitivity ) {
22971 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
22972 } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
22973 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
22974 }
22975 }
22976
22977 } else {
22978
22979 if ( !o.axis || o.axis !== "x" ) {
22980 if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {
22981 scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );
22982 } else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <
22983 o.scrollSensitivity ) {
22984 scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );
22985 }
22986 }
22987
22988 if ( !o.axis || o.axis !== "y" ) {
22989 if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {
22990 scrolled = $( document ).scrollLeft(
22991 $( document ).scrollLeft() - o.scrollSpeed
22992 );
22993 } else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <
22994 o.scrollSensitivity ) {
22995 scrolled = $( document ).scrollLeft(
22996 $( document ).scrollLeft() + o.scrollSpeed
22997 );
22998 }
22999 }
23000
23001 }
23002
23003 if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
23004 $.ui.ddmanager.prepareOffsets( i, event );
23005 }
23006
23007 }
23008} );
23009
23010$.ui.plugin.add( "draggable", "snap", {
23011 start: function( event, ui, i ) {
23012
23013 var o = i.options;
23014
23015 i.snapElements = [];
23016
23017 $( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap )
23018 .each( function() {
23019 var $t = $( this ),
23020 $o = $t.offset();
23021 if ( this !== i.element[ 0 ] ) {
23022 i.snapElements.push( {
23023 item: this,
23024 width: $t.outerWidth(), height: $t.outerHeight(),
23025 top: $o.top, left: $o.left
23026 } );
23027 }
23028 } );
23029
23030 },
23031 drag: function( event, ui, inst ) {
23032
23033 var ts, bs, ls, rs, l, r, t, b, i, first,
23034 o = inst.options,
23035 d = o.snapTolerance,
23036 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
23037 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
23038
23039 for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {
23040
23041 l = inst.snapElements[ i ].left - inst.margins.left;
23042 r = l + inst.snapElements[ i ].width;
23043 t = inst.snapElements[ i ].top - inst.margins.top;
23044 b = t + inst.snapElements[ i ].height;
23045
23046 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
23047 !$.contains( inst.snapElements[ i ].item.ownerDocument,
23048 inst.snapElements[ i ].item ) ) {
23049 if ( inst.snapElements[ i ].snapping ) {
23050 if ( inst.options.snap.release ) {
23051 inst.options.snap.release.call(
23052 inst.element,
23053 event,
23054 $.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )
23055 );
23056 }
23057 }
23058 inst.snapElements[ i ].snapping = false;
23059 continue;
23060 }
23061
23062 if ( o.snapMode !== "inner" ) {
23063 ts = Math.abs( t - y2 ) <= d;
23064 bs = Math.abs( b - y1 ) <= d;
23065 ls = Math.abs( l - x2 ) <= d;
23066 rs = Math.abs( r - x1 ) <= d;
23067 if ( ts ) {
23068 ui.position.top = inst._convertPositionTo( "relative", {
23069 top: t - inst.helperProportions.height,
23070 left: 0
23071 } ).top;
23072 }
23073 if ( bs ) {
23074 ui.position.top = inst._convertPositionTo( "relative", {
23075 top: b,
23076 left: 0
23077 } ).top;
23078 }
23079 if ( ls ) {
23080 ui.position.left = inst._convertPositionTo( "relative", {
23081 top: 0,
23082 left: l - inst.helperProportions.width
23083 } ).left;
23084 }
23085 if ( rs ) {
23086 ui.position.left = inst._convertPositionTo( "relative", {
23087 top: 0,
23088 left: r
23089 } ).left;
23090 }
23091 }
23092
23093 first = ( ts || bs || ls || rs );
23094
23095 if ( o.snapMode !== "outer" ) {
23096 ts = Math.abs( t - y1 ) <= d;
23097 bs = Math.abs( b - y2 ) <= d;
23098 ls = Math.abs( l - x1 ) <= d;
23099 rs = Math.abs( r - x2 ) <= d;
23100 if ( ts ) {
23101 ui.position.top = inst._convertPositionTo( "relative", {
23102 top: t,
23103 left: 0
23104 } ).top;
23105 }
23106 if ( bs ) {
23107 ui.position.top = inst._convertPositionTo( "relative", {
23108 top: b - inst.helperProportions.height,
23109 left: 0
23110 } ).top;
23111 }
23112 if ( ls ) {
23113 ui.position.left = inst._convertPositionTo( "relative", {
23114 top: 0,
23115 left: l
23116 } ).left;
23117 }
23118 if ( rs ) {
23119 ui.position.left = inst._convertPositionTo( "relative", {
23120 top: 0,
23121 left: r - inst.helperProportions.width
23122 } ).left;
23123 }
23124 }
23125
23126 if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {
23127 if ( inst.options.snap.snap ) {
23128 inst.options.snap.snap.call(
23129 inst.element,
23130 event,
23131 $.extend( inst._uiHash(), {
23132 snapItem: inst.snapElements[ i ].item
23133 } ) );
23134 }
23135 }
23136 inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );
23137
23138 }
23139
23140 }
23141} );
23142
23143$.ui.plugin.add( "draggable", "stack", {
23144 start: function( event, ui, instance ) {
23145 var min,
23146 o = instance.options,
23147 group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
23148 return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
23149 ( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
23150 } );
23151
23152 if ( !group.length ) {
23153 return;
23154 }
23155
23156 min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
23157 $( group ).each( function( i ) {
23158 $( this ).css( "zIndex", min + i );
23159 } );
23160 this.css( "zIndex", ( min + group.length ) );
23161 }
23162} );
23163
23164$.ui.plugin.add( "draggable", "zIndex", {
23165 start: function( event, ui, instance ) {
23166 var t = $( ui.helper ),
23167 o = instance.options;
23168
23169 if ( t.css( "zIndex" ) ) {
23170 o._zIndex = t.css( "zIndex" );
23171 }
23172 t.css( "zIndex", o.zIndex );
23173 },
23174 stop: function( event, ui, instance ) {
23175 var o = instance.options;
23176
23177 if ( o._zIndex ) {
23178 $( ui.helper ).css( "zIndex", o._zIndex );
23179 }
23180 }
23181} );
23182
23183return $.ui.draggable;
23184
23185} );
23186
23187
23188
23189
23190
23191
23192/*!
23193 * jQuery UI Resizable 1.14.1
23194 * https://jqueryui.com
23195 *
23196 * Copyright OpenJS Foundation and other contributors
23197 * Released under the MIT license.
23198 * https://jquery.org/license
23199 */
23200
23201//>>label: Resizable
23202//>>group: Interactions
23203//>>description: Enables resize functionality for any element.
23204//>>docs: https://api.jqueryui.com/resizable/
23205//>>demos: https://jqueryui.com/resizable/
23206//>>css.structure: ../../themes/base/core.css
23207//>>css.structure: ../../themes/base/resizable.css
23208//>>css.theme: ../../themes/base/theme.css
23209
23210( function( factory ) {
23211 "use strict";
23212
23213 if ( typeof define === "function" && define.amd ) {
23214
23215 // AMD. Register as an anonymous module.
23216 define( [
23217 "jquery",
23218 "./mouse",
23219 "../disable-selection",
23220 "../plugin",
23221 "../version",
23222 "../widget"
23223 ], factory );
23224 } else {
23225
23226 // Browser globals
23227 factory( jQuery );
23228 }
23229} )( function( $ ) {
23230"use strict";
23231
23232$.widget( "ui.resizable", $.ui.mouse, {
23233 version: "1.14.1",
23234 widgetEventPrefix: "resize",
23235 options: {
23236 alsoResize: false,
23237 animate: false,
23238 animateDuration: "slow",
23239 animateEasing: "swing",
23240 aspectRatio: false,
23241 autoHide: false,
23242 classes: {
23243 "ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
23244 },
23245 containment: false,
23246 ghost: false,
23247 grid: false,
23248 handles: "e,s,se",
23249 helper: false,
23250 maxHeight: null,
23251 maxWidth: null,
23252 minHeight: 10,
23253 minWidth: 10,
23254
23255 // See #7960
23256 zIndex: 90,
23257
23258 // Callbacks
23259 resize: null,
23260 start: null,
23261 stop: null
23262 },
23263
23264 _num: function( value ) {
23265 return parseFloat( value ) || 0;
23266 },
23267
23268 _isNumber: function( value ) {
23269 return !isNaN( parseFloat( value ) );
23270 },
23271
23272 _hasScroll: function( el, a ) {
23273
23274 var scroll,
23275 has = false,
23276 overflow = $( el ).css( "overflow" );
23277
23278 if ( overflow === "hidden" ) {
23279 return false;
23280 }
23281 if ( overflow === "scroll" ) {
23282 return true;
23283 }
23284
23285 scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop";
23286
23287 if ( el[ scroll ] > 0 ) {
23288 return true;
23289 }
23290
23291 // TODO: determine which cases actually cause this to happen
23292 // if the element doesn't have the scroll set, see if it's possible to
23293 // set the scroll
23294 try {
23295 el[ scroll ] = 1;
23296 has = ( el[ scroll ] > 0 );
23297 el[ scroll ] = 0;
23298 } catch ( e ) {
23299
23300 // `el` might be a string, then setting `scroll` will throw
23301 // an error in strict mode; ignore it.
23302 }
23303 return has;
23304 },
23305
23306 _create: function() {
23307
23308 var margins,
23309 o = this.options,
23310 that = this;
23311 this._addClass( "ui-resizable" );
23312
23313 $.extend( this, {
23314 _aspectRatio: !!( o.aspectRatio ),
23315 aspectRatio: o.aspectRatio,
23316 originalElement: this.element,
23317 _proportionallyResizeElements: [],
23318 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
23319 } );
23320
23321 // Wrap the element if it cannot hold child nodes
23322 if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
23323
23324 this.element.wrap(
23325 $( "<div class='ui-wrapper'></div>" ).css( {
23326 overflow: "hidden",
23327 position: this.element.css( "position" ),
23328 width: this.element.outerWidth(),
23329 height: this.element.outerHeight(),
23330 top: this.element.css( "top" ),
23331 left: this.element.css( "left" )
23332 } )
23333 );
23334
23335 this.element = this.element.parent().data(
23336 "ui-resizable", this.element.resizable( "instance" )
23337 );
23338
23339 this.elementIsWrapper = true;
23340
23341 margins = {
23342 marginTop: this.originalElement.css( "marginTop" ),
23343 marginRight: this.originalElement.css( "marginRight" ),
23344 marginBottom: this.originalElement.css( "marginBottom" ),
23345 marginLeft: this.originalElement.css( "marginLeft" )
23346 };
23347
23348 this.element.css( margins );
23349
23350 // Support: Safari
23351 // Prevent Safari textarea resize
23352 this.originalResizeStyle = this.originalElement.css( "resize" );
23353 this.originalElement.css( "resize", "none" );
23354
23355 this._proportionallyResizeElements.push( this.originalElement.css( {
23356 position: "static",
23357 zoom: 1,
23358 display: "block"
23359 } ) );
23360
23361 this._proportionallyResize();
23362 }
23363
23364 this._setupHandles();
23365
23366 if ( o.autoHide ) {
23367 $( this.element )
23368 .on( "mouseenter", function() {
23369 if ( o.disabled ) {
23370 return;
23371 }
23372 that._removeClass( "ui-resizable-autohide" );
23373 that._handles.show();
23374 } )
23375 .on( "mouseleave", function() {
23376 if ( o.disabled ) {
23377 return;
23378 }
23379 if ( !that.resizing ) {
23380 that._addClass( "ui-resizable-autohide" );
23381 that._handles.hide();
23382 }
23383 } );
23384 }
23385
23386 this._mouseInit();
23387 },
23388
23389 _destroy: function() {
23390
23391 this._mouseDestroy();
23392 this._addedHandles.remove();
23393
23394 var wrapper,
23395 _destroy = function( exp ) {
23396 $( exp )
23397 .removeData( "resizable" )
23398 .removeData( "ui-resizable" )
23399 .off( ".resizable" );
23400 };
23401
23402 // TODO: Unwrap at same DOM position
23403 if ( this.elementIsWrapper ) {
23404 _destroy( this.element );
23405 wrapper = this.element;
23406 this.originalElement.css( {
23407 position: wrapper.css( "position" ),
23408 width: wrapper.outerWidth(),
23409 height: wrapper.outerHeight(),
23410 top: wrapper.css( "top" ),
23411 left: wrapper.css( "left" )
23412 } ).insertAfter( wrapper );
23413 wrapper.remove();
23414 }
23415
23416 this.originalElement.css( "resize", this.originalResizeStyle );
23417 _destroy( this.originalElement );
23418
23419 return this;
23420 },
23421
23422 _setOption: function( key, value ) {
23423 this._super( key, value );
23424
23425 switch ( key ) {
23426 case "handles":
23427 this._removeHandles();
23428 this._setupHandles();
23429 break;
23430 case "aspectRatio":
23431 this._aspectRatio = !!value;
23432 break;
23433 default:
23434 break;
23435 }
23436 },
23437
23438 _setupHandles: function() {
23439 var o = this.options, handle, i, n, hname, axis, that = this;
23440 this.handles = o.handles ||
23441 ( !$( ".ui-resizable-handle", this.element ).length ?
23442 "e,s,se" : {
23443 n: ".ui-resizable-n",
23444 e: ".ui-resizable-e",
23445 s: ".ui-resizable-s",
23446 w: ".ui-resizable-w",
23447 se: ".ui-resizable-se",
23448 sw: ".ui-resizable-sw",
23449 ne: ".ui-resizable-ne",
23450 nw: ".ui-resizable-nw"
23451 } );
23452
23453 this._handles = $();
23454 this._addedHandles = $();
23455 if ( this.handles.constructor === String ) {
23456
23457 if ( this.handles === "all" ) {
23458 this.handles = "n,e,s,w,se,sw,ne,nw";
23459 }
23460
23461 n = this.handles.split( "," );
23462 this.handles = {};
23463
23464 for ( i = 0; i < n.length; i++ ) {
23465
23466 handle = String.prototype.trim.call( n[ i ] );
23467 hname = "ui-resizable-" + handle;
23468 axis = $( "<div>" );
23469 this._addClass( axis, "ui-resizable-handle " + hname );
23470
23471 axis.css( { zIndex: o.zIndex } );
23472
23473 this.handles[ handle ] = ".ui-resizable-" + handle;
23474 if ( !this.element.children( this.handles[ handle ] ).length ) {
23475 this.element.append( axis );
23476 this._addedHandles = this._addedHandles.add( axis );
23477 }
23478 }
23479
23480 }
23481
23482 this._renderAxis = function( target ) {
23483
23484 var i, axis, padPos, padWrapper;
23485
23486 target = target || this.element;
23487
23488 for ( i in this.handles ) {
23489
23490 if ( this.handles[ i ].constructor === String ) {
23491 this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
23492 } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
23493 this.handles[ i ] = $( this.handles[ i ] );
23494 this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
23495 }
23496
23497 if ( this.elementIsWrapper &&
23498 this.originalElement[ 0 ]
23499 .nodeName
23500 .match( /^(textarea|input|select|button)$/i ) ) {
23501 axis = $( this.handles[ i ], this.element );
23502
23503 padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
23504 axis.outerHeight() :
23505 axis.outerWidth();
23506
23507 padPos = [ "padding",
23508 /ne|nw|n/.test( i ) ? "Top" :
23509 /se|sw|s/.test( i ) ? "Bottom" :
23510 /^e$/.test( i ) ? "Right" : "Left" ].join( "" );
23511
23512 target.css( padPos, padWrapper );
23513
23514 this._proportionallyResize();
23515 }
23516
23517 this._handles = this._handles.add( this.handles[ i ] );
23518 }
23519 };
23520
23521 // TODO: make renderAxis a prototype function
23522 this._renderAxis( this.element );
23523
23524 this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
23525 this._handles.disableSelection();
23526
23527 this._handles.on( "mouseover", function() {
23528 if ( !that.resizing ) {
23529 if ( this.className ) {
23530 axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
23531 }
23532 that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
23533 }
23534 } );
23535
23536 if ( o.autoHide ) {
23537 this._handles.hide();
23538 this._addClass( "ui-resizable-autohide" );
23539 }
23540 },
23541
23542 _removeHandles: function() {
23543 this._addedHandles.remove();
23544 },
23545
23546 _mouseCapture: function( event ) {
23547 var i, handle,
23548 capture = false;
23549
23550 for ( i in this.handles ) {
23551 handle = $( this.handles[ i ] )[ 0 ];
23552 if ( handle === event.target || $.contains( handle, event.target ) ) {
23553 capture = true;
23554 }
23555 }
23556
23557 return !this.options.disabled && capture;
23558 },
23559
23560 _mouseStart: function( event ) {
23561
23562 var curleft, curtop, cursor, calculatedSize,
23563 o = this.options,
23564 el = this.element;
23565
23566 this.resizing = true;
23567
23568 this._renderProxy();
23569
23570 curleft = this._num( this.helper.css( "left" ) );
23571 curtop = this._num( this.helper.css( "top" ) );
23572
23573 if ( o.containment ) {
23574 curleft += $( o.containment ).scrollLeft() || 0;
23575 curtop += $( o.containment ).scrollTop() || 0;
23576 }
23577
23578 this.offset = this.helper.offset();
23579 this.position = { left: curleft, top: curtop };
23580
23581 if ( !this._helper ) {
23582 calculatedSize = this._calculateAdjustedElementDimensions( el );
23583 }
23584
23585 this.size = this._helper ? {
23586 width: this.helper.width(),
23587 height: this.helper.height()
23588 } : {
23589 width: calculatedSize.width,
23590 height: calculatedSize.height
23591 };
23592
23593 this.originalSize = this._helper ? {
23594 width: el.outerWidth(),
23595 height: el.outerHeight()
23596 } : {
23597 width: calculatedSize.width,
23598 height: calculatedSize.height
23599 };
23600
23601 this.sizeDiff = {
23602 width: el.outerWidth() - el.width(),
23603 height: el.outerHeight() - el.height()
23604 };
23605
23606 this.originalPosition = { left: curleft, top: curtop };
23607 this.originalMousePosition = { left: event.pageX, top: event.pageY };
23608
23609 this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
23610 o.aspectRatio :
23611 ( ( this.originalSize.width / this.originalSize.height ) || 1 );
23612
23613 cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
23614 $( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
23615
23616 this._addClass( "ui-resizable-resizing" );
23617 this._propagate( "start", event );
23618 return true;
23619 },
23620
23621 _mouseDrag: function( event ) {
23622
23623 var data, props,
23624 smp = this.originalMousePosition,
23625 a = this.axis,
23626 dx = ( event.pageX - smp.left ) || 0,
23627 dy = ( event.pageY - smp.top ) || 0,
23628 trigger = this._change[ a ];
23629
23630 this._updatePrevProperties();
23631
23632 if ( !trigger ) {
23633 return false;
23634 }
23635
23636 data = trigger.apply( this, [ event, dx, dy ] );
23637
23638 this._updateVirtualBoundaries( event.shiftKey );
23639 if ( this._aspectRatio || event.shiftKey ) {
23640 data = this._updateRatio( data, event );
23641 }
23642
23643 data = this._respectSize( data, event );
23644
23645 this._updateCache( data );
23646
23647 this._propagate( "resize", event );
23648
23649 props = this._applyChanges();
23650
23651 if ( !this._helper && this._proportionallyResizeElements.length ) {
23652 this._proportionallyResize();
23653 }
23654
23655 if ( !$.isEmptyObject( props ) ) {
23656 this._updatePrevProperties();
23657 this._trigger( "resize", event, this.ui() );
23658 this._applyChanges();
23659 }
23660
23661 return false;
23662 },
23663
23664 _mouseStop: function( event ) {
23665
23666 this.resizing = false;
23667 var pr, ista, soffseth, soffsetw, s, left, top,
23668 o = this.options, that = this;
23669
23670 if ( this._helper ) {
23671
23672 pr = this._proportionallyResizeElements;
23673 ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
23674 soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
23675 soffsetw = ista ? 0 : that.sizeDiff.width;
23676
23677 s = {
23678 width: ( that.helper.width() - soffsetw ),
23679 height: ( that.helper.height() - soffseth )
23680 };
23681 left = ( parseFloat( that.element.css( "left" ) ) +
23682 ( that.position.left - that.originalPosition.left ) ) || null;
23683 top = ( parseFloat( that.element.css( "top" ) ) +
23684 ( that.position.top - that.originalPosition.top ) ) || null;
23685
23686 if ( !o.animate ) {
23687 this.element.css( $.extend( s, { top: top, left: left } ) );
23688 }
23689
23690 that.helper.height( that.size.height );
23691 that.helper.width( that.size.width );
23692
23693 if ( this._helper && !o.animate ) {
23694 this._proportionallyResize();
23695 }
23696 }
23697
23698 $( "body" ).css( "cursor", "auto" );
23699
23700 this._removeClass( "ui-resizable-resizing" );
23701
23702 this._propagate( "stop", event );
23703
23704 if ( this._helper ) {
23705 this.helper.remove();
23706 }
23707
23708 return false;
23709
23710 },
23711
23712 _updatePrevProperties: function() {
23713 this.prevPosition = {
23714 top: this.position.top,
23715 left: this.position.left
23716 };
23717 this.prevSize = {
23718 width: this.size.width,
23719 height: this.size.height
23720 };
23721 },
23722
23723 _applyChanges: function() {
23724 var props = {};
23725
23726 if ( this.position.top !== this.prevPosition.top ) {
23727 props.top = this.position.top + "px";
23728 }
23729 if ( this.position.left !== this.prevPosition.left ) {
23730 props.left = this.position.left + "px";
23731 }
23732
23733 this.helper.css( props );
23734
23735 if ( this.size.width !== this.prevSize.width ) {
23736 props.width = this.size.width + "px";
23737 this.helper.width( props.width );
23738 }
23739 if ( this.size.height !== this.prevSize.height ) {
23740 props.height = this.size.height + "px";
23741 this.helper.height( props.height );
23742 }
23743
23744 return props;
23745 },
23746
23747 _updateVirtualBoundaries: function( forceAspectRatio ) {
23748 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
23749 o = this.options;
23750
23751 b = {
23752 minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
23753 maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
23754 minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
23755 maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
23756 };
23757
23758 if ( this._aspectRatio || forceAspectRatio ) {
23759 pMinWidth = b.minHeight * this.aspectRatio;
23760 pMinHeight = b.minWidth / this.aspectRatio;
23761 pMaxWidth = b.maxHeight * this.aspectRatio;
23762 pMaxHeight = b.maxWidth / this.aspectRatio;
23763
23764 if ( pMinWidth > b.minWidth ) {
23765 b.minWidth = pMinWidth;
23766 }
23767 if ( pMinHeight > b.minHeight ) {
23768 b.minHeight = pMinHeight;
23769 }
23770 if ( pMaxWidth < b.maxWidth ) {
23771 b.maxWidth = pMaxWidth;
23772 }
23773 if ( pMaxHeight < b.maxHeight ) {
23774 b.maxHeight = pMaxHeight;
23775 }
23776 }
23777 this._vBoundaries = b;
23778 },
23779
23780 _updateCache: function( data ) {
23781 this.offset = this.helper.offset();
23782 if ( this._isNumber( data.left ) ) {
23783 this.position.left = data.left;
23784 }
23785 if ( this._isNumber( data.top ) ) {
23786 this.position.top = data.top;
23787 }
23788 if ( this._isNumber( data.height ) ) {
23789 this.size.height = data.height;
23790 }
23791 if ( this._isNumber( data.width ) ) {
23792 this.size.width = data.width;
23793 }
23794 },
23795
23796 _updateRatio: function( data ) {
23797
23798 var cpos = this.position,
23799 csize = this.size,
23800 a = this.axis;
23801
23802 if ( this._isNumber( data.height ) ) {
23803 data.width = ( data.height * this.aspectRatio );
23804 } else if ( this._isNumber( data.width ) ) {
23805 data.height = ( data.width / this.aspectRatio );
23806 }
23807
23808 if ( a === "sw" ) {
23809 data.left = cpos.left + ( csize.width - data.width );
23810 data.top = null;
23811 }
23812 if ( a === "nw" ) {
23813 data.top = cpos.top + ( csize.height - data.height );
23814 data.left = cpos.left + ( csize.width - data.width );
23815 }
23816
23817 return data;
23818 },
23819
23820 _respectSize: function( data ) {
23821
23822 var o = this._vBoundaries,
23823 a = this.axis,
23824 ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
23825 ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
23826 isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
23827 isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
23828 dw = this.originalPosition.left + this.originalSize.width,
23829 dh = this.originalPosition.top + this.originalSize.height,
23830 cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
23831 if ( isminw ) {
23832 data.width = o.minWidth;
23833 }
23834 if ( isminh ) {
23835 data.height = o.minHeight;
23836 }
23837 if ( ismaxw ) {
23838 data.width = o.maxWidth;
23839 }
23840 if ( ismaxh ) {
23841 data.height = o.maxHeight;
23842 }
23843
23844 if ( isminw && cw ) {
23845 data.left = dw - o.minWidth;
23846 }
23847 if ( ismaxw && cw ) {
23848 data.left = dw - o.maxWidth;
23849 }
23850 if ( isminh && ch ) {
23851 data.top = dh - o.minHeight;
23852 }
23853 if ( ismaxh && ch ) {
23854 data.top = dh - o.maxHeight;
23855 }
23856
23857 // Fixing jump error on top/left - bug #2330
23858 if ( !data.width && !data.height && !data.left && data.top ) {
23859 data.top = null;
23860 } else if ( !data.width && !data.height && !data.top && data.left ) {
23861 data.left = null;
23862 }
23863
23864 return data;
23865 },
23866
23867 _getPaddingPlusBorderDimensions: function( element ) {
23868 var i = 0,
23869 widths = [],
23870 borders = [
23871 element.css( "borderTopWidth" ),
23872 element.css( "borderRightWidth" ),
23873 element.css( "borderBottomWidth" ),
23874 element.css( "borderLeftWidth" )
23875 ],
23876 paddings = [
23877 element.css( "paddingTop" ),
23878 element.css( "paddingRight" ),
23879 element.css( "paddingBottom" ),
23880 element.css( "paddingLeft" )
23881 ];
23882
23883 for ( ; i < 4; i++ ) {
23884 widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
23885 widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
23886 }
23887
23888 return {
23889 height: widths[ 0 ] + widths[ 2 ],
23890 width: widths[ 1 ] + widths[ 3 ]
23891 };
23892 },
23893
23894 _calculateAdjustedElementDimensions: function( element ) {
23895 var elWidth, elHeight, paddingBorder,
23896 ce = element.get( 0 );
23897
23898 if ( element.css( "box-sizing" ) !== "content-box" ||
23899 ( !this._hasScroll( ce ) && !this._hasScroll( ce, "left" ) ) ) {
23900 return {
23901 height: parseFloat( element.css( "height" ) ),
23902 width: parseFloat( element.css( "width" ) )
23903 };
23904 }
23905
23906 // Check if CSS inline styles are set and use those (usually from previous resizes)
23907 elWidth = parseFloat( ce.style.width );
23908 elHeight = parseFloat( ce.style.height );
23909
23910 paddingBorder = this._getPaddingPlusBorderDimensions( element );
23911 elWidth = isNaN( elWidth ) ?
23912 this._getElementTheoreticalSize( element, paddingBorder, "width" ) :
23913 elWidth;
23914 elHeight = isNaN( elHeight ) ?
23915 this._getElementTheoreticalSize( element, paddingBorder, "height" ) :
23916 elHeight;
23917
23918 return {
23919 height: elHeight,
23920 width: elWidth
23921 };
23922 },
23923
23924 _getElementTheoreticalSize: function( element, extraSize, dimension ) {
23925
23926 // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border
23927 var size = Math.max( 0, Math.ceil(
23928 element.get( 0 )[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
23929 extraSize[ dimension ] -
23930 0.5
23931
23932 // If offsetWidth/offsetHeight is unknown, then we can't determine theoretical size.
23933 // Use an explicit zero to avoid NaN.
23934 // See https://github.com/jquery/jquery/issues/3964
23935 ) ) || 0;
23936
23937 return size;
23938 },
23939
23940 _proportionallyResize: function() {
23941
23942 if ( !this._proportionallyResizeElements.length ) {
23943 return;
23944 }
23945
23946 var prel,
23947 i = 0,
23948 element = this.helper || this.element;
23949
23950 for ( ; i < this._proportionallyResizeElements.length; i++ ) {
23951
23952 prel = this._proportionallyResizeElements[ i ];
23953
23954 // TODO: Seems like a bug to cache this.outerDimensions
23955 // considering that we are in a loop.
23956 if ( !this.outerDimensions ) {
23957 this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
23958 }
23959
23960 prel.css( {
23961 height: ( element.height() - this.outerDimensions.height ) || 0,
23962 width: ( element.width() - this.outerDimensions.width ) || 0
23963 } );
23964
23965 }
23966
23967 },
23968
23969 _renderProxy: function() {
23970
23971 var el = this.element, o = this.options;
23972 this.elementOffset = el.offset();
23973
23974 if ( this._helper ) {
23975
23976 this.helper = this.helper || $( "<div></div>" ).css( { overflow: "hidden" } );
23977
23978 this._addClass( this.helper, this._helper );
23979 this.helper.css( {
23980 width: this.element.outerWidth(),
23981 height: this.element.outerHeight(),
23982 position: "absolute",
23983 left: this.elementOffset.left + "px",
23984 top: this.elementOffset.top + "px",
23985 zIndex: ++o.zIndex //TODO: Don't modify option
23986 } );
23987
23988 this.helper
23989 .appendTo( "body" )
23990 .disableSelection();
23991
23992 } else {
23993 this.helper = this.element;
23994 }
23995
23996 },
23997
23998 _change: {
23999 e: function( event, dx ) {
24000 return { width: this.originalSize.width + dx };
24001 },
24002 w: function( event, dx ) {
24003 var cs = this.originalSize, sp = this.originalPosition;
24004 return { left: sp.left + dx, width: cs.width - dx };
24005 },
24006 n: function( event, dx, dy ) {
24007 var cs = this.originalSize, sp = this.originalPosition;
24008 return { top: sp.top + dy, height: cs.height - dy };
24009 },
24010 s: function( event, dx, dy ) {
24011 return { height: this.originalSize.height + dy };
24012 },
24013 se: function( event, dx, dy ) {
24014 return $.extend( this._change.s.apply( this, arguments ),
24015 this._change.e.apply( this, [ event, dx, dy ] ) );
24016 },
24017 sw: function( event, dx, dy ) {
24018 return $.extend( this._change.s.apply( this, arguments ),
24019 this._change.w.apply( this, [ event, dx, dy ] ) );
24020 },
24021 ne: function( event, dx, dy ) {
24022 return $.extend( this._change.n.apply( this, arguments ),
24023 this._change.e.apply( this, [ event, dx, dy ] ) );
24024 },
24025 nw: function( event, dx, dy ) {
24026 return $.extend( this._change.n.apply( this, arguments ),
24027 this._change.w.apply( this, [ event, dx, dy ] ) );
24028 }
24029 },
24030
24031 _propagate: function( n, event ) {
24032 $.ui.plugin.call( this, n, [ event, this.ui() ] );
24033 if ( n !== "resize" ) {
24034 this._trigger( n, event, this.ui() );
24035 }
24036 },
24037
24038 plugins: {},
24039
24040 ui: function() {
24041 return {
24042 originalElement: this.originalElement,
24043 element: this.element,
24044 helper: this.helper,
24045 position: this.position,
24046 size: this.size,
24047 originalSize: this.originalSize,
24048 originalPosition: this.originalPosition
24049 };
24050 }
24051
24052} );
24053
24054/*
24055 * Resizable Extensions
24056 */
24057
24058$.ui.plugin.add( "resizable", "animate", {
24059
24060 stop: function( event ) {
24061 var that = $( this ).resizable( "instance" ),
24062 o = that.options,
24063 pr = that._proportionallyResizeElements,
24064 ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
24065 soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
24066 soffsetw = ista ? 0 : that.sizeDiff.width,
24067 style = {
24068 width: ( that.size.width - soffsetw ),
24069 height: ( that.size.height - soffseth )
24070 },
24071 left = ( parseFloat( that.element.css( "left" ) ) +
24072 ( that.position.left - that.originalPosition.left ) ) || null,
24073 top = ( parseFloat( that.element.css( "top" ) ) +
24074 ( that.position.top - that.originalPosition.top ) ) || null;
24075
24076 that.element.animate(
24077 $.extend( style, top && left ? { top: top, left: left } : {} ), {
24078 duration: o.animateDuration,
24079 easing: o.animateEasing,
24080 step: function() {
24081
24082 var data = {
24083 width: parseFloat( that.element.css( "width" ) ),
24084 height: parseFloat( that.element.css( "height" ) ),
24085 top: parseFloat( that.element.css( "top" ) ),
24086 left: parseFloat( that.element.css( "left" ) )
24087 };
24088
24089 if ( pr && pr.length ) {
24090 $( pr[ 0 ] ).css( { width: data.width, height: data.height } );
24091 }
24092
24093 // Propagating resize, and updating values for each animation step
24094 that._updateCache( data );
24095 that._propagate( "resize", event );
24096
24097 }
24098 }
24099 );
24100 }
24101
24102} );
24103
24104$.ui.plugin.add( "resizable", "containment", {
24105
24106 start: function() {
24107 var element, p, co, ch, cw, width, height,
24108 that = $( this ).resizable( "instance" ),
24109 o = that.options,
24110 el = that.element,
24111 oc = o.containment,
24112 ce = ( oc instanceof $ ) ?
24113 oc.get( 0 ) :
24114 ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
24115
24116 if ( !ce ) {
24117 return;
24118 }
24119
24120 that.containerElement = $( ce );
24121
24122 if ( /document/.test( oc ) || oc === document ) {
24123 that.containerOffset = {
24124 left: 0,
24125 top: 0
24126 };
24127 that.containerPosition = {
24128 left: 0,
24129 top: 0
24130 };
24131
24132 that.parentData = {
24133 element: $( document ),
24134 left: 0,
24135 top: 0,
24136 width: $( document ).width(),
24137 height: $( document ).height() || document.body.parentNode.scrollHeight
24138 };
24139 } else {
24140 element = $( ce );
24141 p = [];
24142 $( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
24143 p[ i ] = that._num( element.css( "padding" + name ) );
24144 } );
24145
24146 that.containerOffset = element.offset();
24147 that.containerPosition = element.position();
24148 that.containerSize = {
24149 height: ( element.innerHeight() - p[ 3 ] ),
24150 width: ( element.innerWidth() - p[ 1 ] )
24151 };
24152
24153 co = that.containerOffset;
24154 ch = that.containerSize.height;
24155 cw = that.containerSize.width;
24156 width = ( that._hasScroll( ce, "left" ) ? ce.scrollWidth : cw );
24157 height = ( that._hasScroll( ce ) ? ce.scrollHeight : ch );
24158
24159 that.parentData = {
24160 element: ce,
24161 left: co.left,
24162 top: co.top,
24163 width: width,
24164 height: height
24165 };
24166 }
24167 },
24168
24169 resize: function( event ) {
24170 var woset, hoset, isParent, isOffsetRelative,
24171 that = $( this ).resizable( "instance" ),
24172 o = that.options,
24173 co = that.containerOffset,
24174 cp = that.position,
24175 pRatio = that._aspectRatio || event.shiftKey,
24176 cop = {
24177 top: 0,
24178 left: 0
24179 },
24180 ce = that.containerElement,
24181 continueResize = true;
24182
24183 if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
24184 cop = co;
24185 }
24186
24187 if ( cp.left < ( that._helper ? co.left : 0 ) ) {
24188 that.size.width = that.size.width +
24189 ( that._helper ?
24190 ( that.position.left - co.left ) :
24191 ( that.position.left - cop.left ) );
24192
24193 if ( pRatio ) {
24194 that.size.height = that.size.width / that.aspectRatio;
24195 continueResize = false;
24196 }
24197 that.position.left = o.helper ? co.left : 0;
24198 }
24199
24200 if ( cp.top < ( that._helper ? co.top : 0 ) ) {
24201 that.size.height = that.size.height +
24202 ( that._helper ?
24203 ( that.position.top - co.top ) :
24204 that.position.top );
24205
24206 if ( pRatio ) {
24207 that.size.width = that.size.height * that.aspectRatio;
24208 continueResize = false;
24209 }
24210 that.position.top = that._helper ? co.top : 0;
24211 }
24212
24213 isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
24214 isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
24215
24216 if ( isParent && isOffsetRelative ) {
24217 that.offset.left = that.parentData.left + that.position.left;
24218 that.offset.top = that.parentData.top + that.position.top;
24219 } else {
24220 that.offset.left = that.element.offset().left;
24221 that.offset.top = that.element.offset().top;
24222 }
24223
24224 woset = Math.abs( that.sizeDiff.width +
24225 ( that._helper ?
24226 that.offset.left - cop.left :
24227 ( that.offset.left - co.left ) ) );
24228
24229 hoset = Math.abs( that.sizeDiff.height +
24230 ( that._helper ?
24231 that.offset.top - cop.top :
24232 ( that.offset.top - co.top ) ) );
24233
24234 if ( woset + that.size.width >= that.parentData.width ) {
24235 that.size.width = that.parentData.width - woset;
24236 if ( pRatio ) {
24237 that.size.height = that.size.width / that.aspectRatio;
24238 continueResize = false;
24239 }
24240 }
24241
24242 if ( hoset + that.size.height >= that.parentData.height ) {
24243 that.size.height = that.parentData.height - hoset;
24244 if ( pRatio ) {
24245 that.size.width = that.size.height * that.aspectRatio;
24246 continueResize = false;
24247 }
24248 }
24249
24250 if ( !continueResize ) {
24251 that.position.left = that.prevPosition.left;
24252 that.position.top = that.prevPosition.top;
24253 that.size.width = that.prevSize.width;
24254 that.size.height = that.prevSize.height;
24255 }
24256 },
24257
24258 stop: function() {
24259 var that = $( this ).resizable( "instance" ),
24260 o = that.options,
24261 co = that.containerOffset,
24262 cop = that.containerPosition,
24263 ce = that.containerElement,
24264 helper = $( that.helper ),
24265 ho = helper.offset(),
24266 w = helper.outerWidth() - that.sizeDiff.width,
24267 h = helper.outerHeight() - that.sizeDiff.height;
24268
24269 if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
24270 $( this ).css( {
24271 left: ho.left - cop.left - co.left,
24272 width: w,
24273 height: h
24274 } );
24275 }
24276
24277 if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
24278 $( this ).css( {
24279 left: ho.left - cop.left - co.left,
24280 width: w,
24281 height: h
24282 } );
24283 }
24284 }
24285} );
24286
24287$.ui.plugin.add( "resizable", "alsoResize", {
24288
24289 start: function() {
24290 var that = $( this ).resizable( "instance" ),
24291 o = that.options;
24292
24293 $( o.alsoResize ).each( function() {
24294 var el = $( this ),
24295 elSize = that._calculateAdjustedElementDimensions( el );
24296
24297 el.data( "ui-resizable-alsoresize", {
24298 width: elSize.width, height: elSize.height,
24299 left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
24300 } );
24301 } );
24302 },
24303
24304 resize: function( event, ui ) {
24305 var that = $( this ).resizable( "instance" ),
24306 o = that.options,
24307 os = that.originalSize,
24308 op = that.originalPosition,
24309 delta = {
24310 height: ( that.size.height - os.height ) || 0,
24311 width: ( that.size.width - os.width ) || 0,
24312 top: ( that.position.top - op.top ) || 0,
24313 left: ( that.position.left - op.left ) || 0
24314 };
24315
24316 $( o.alsoResize ).each( function() {
24317 var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
24318 css = el.parents( ui.originalElement[ 0 ] ).length ?
24319 [ "width", "height" ] :
24320 [ "width", "height", "top", "left" ];
24321
24322 $.each( css, function( i, prop ) {
24323 var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
24324 if ( sum && sum >= 0 ) {
24325 style[ prop ] = sum || null;
24326 }
24327 } );
24328
24329 el.css( style );
24330 } );
24331 },
24332
24333 stop: function() {
24334 $( this ).removeData( "ui-resizable-alsoresize" );
24335 }
24336} );
24337
24338$.ui.plugin.add( "resizable", "ghost", {
24339
24340 start: function() {
24341
24342 var that = $( this ).resizable( "instance" ), cs = that.size;
24343
24344 that.ghost = that.originalElement.clone();
24345 that.ghost.css( {
24346 opacity: 0.25,
24347 display: "block",
24348 position: "relative",
24349 height: cs.height,
24350 width: cs.width,
24351 margin: 0,
24352 left: 0,
24353 top: 0
24354 } );
24355
24356 that._addClass( that.ghost, "ui-resizable-ghost" );
24357
24358 // DEPRECATED
24359 // TODO: remove after 1.12
24360 if ( $.uiBackCompat === true && typeof that.options.ghost === "string" ) {
24361
24362 // Ghost option
24363 that.ghost.addClass( this.options.ghost );
24364 }
24365
24366 that.ghost.appendTo( that.helper );
24367
24368 },
24369
24370 resize: function() {
24371 var that = $( this ).resizable( "instance" );
24372 if ( that.ghost ) {
24373 that.ghost.css( {
24374 position: "relative",
24375 height: that.size.height,
24376 width: that.size.width
24377 } );
24378 }
24379 },
24380
24381 stop: function() {
24382 var that = $( this ).resizable( "instance" );
24383 if ( that.ghost && that.helper ) {
24384 that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
24385 }
24386 }
24387
24388} );
24389
24390$.ui.plugin.add( "resizable", "grid", {
24391
24392 resize: function() {
24393 var outerDimensions,
24394 that = $( this ).resizable( "instance" ),
24395 o = that.options,
24396 cs = that.size,
24397 os = that.originalSize,
24398 op = that.originalPosition,
24399 a = that.axis,
24400 grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
24401 gridX = ( grid[ 0 ] || 1 ),
24402 gridY = ( grid[ 1 ] || 1 ),
24403 ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
24404 oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
24405 newWidth = os.width + ox,
24406 newHeight = os.height + oy,
24407 isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
24408 isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
24409 isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
24410 isMinHeight = o.minHeight && ( o.minHeight > newHeight );
24411
24412 o.grid = grid;
24413
24414 if ( isMinWidth ) {
24415 newWidth += gridX;
24416 }
24417 if ( isMinHeight ) {
24418 newHeight += gridY;
24419 }
24420 if ( isMaxWidth ) {
24421 newWidth -= gridX;
24422 }
24423 if ( isMaxHeight ) {
24424 newHeight -= gridY;
24425 }
24426
24427 if ( /^(se|s|e)$/.test( a ) ) {
24428 that.size.width = newWidth;
24429 that.size.height = newHeight;
24430 } else if ( /^(ne)$/.test( a ) ) {
24431 that.size.width = newWidth;
24432 that.size.height = newHeight;
24433 that.position.top = op.top - oy;
24434 } else if ( /^(sw)$/.test( a ) ) {
24435 that.size.width = newWidth;
24436 that.size.height = newHeight;
24437 that.position.left = op.left - ox;
24438 } else {
24439 if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
24440 outerDimensions = that._getPaddingPlusBorderDimensions( this );
24441 }
24442
24443 if ( newHeight - gridY > 0 ) {
24444 that.size.height = newHeight;
24445 that.position.top = op.top - oy;
24446 } else {
24447 newHeight = gridY - outerDimensions.height;
24448 that.size.height = newHeight;
24449 that.position.top = op.top + os.height - newHeight;
24450 }
24451 if ( newWidth - gridX > 0 ) {
24452 that.size.width = newWidth;
24453 that.position.left = op.left - ox;
24454 } else {
24455 newWidth = gridX - outerDimensions.width;
24456 that.size.width = newWidth;
24457 that.position.left = op.left + os.width - newWidth;
24458 }
24459 }
24460 }
24461
24462} );
24463
24464return $.ui.resizable;
24465
24466} );
24467
24468
24469
24470
24471
24472
24473
24474
24475
24476
24477
24478
24479/*!
24480 * jQuery UI Dialog 1.14.1
24481 * https://jqueryui.com
24482 *
24483 * Copyright OpenJS Foundation and other contributors
24484 * Released under the MIT license.
24485 * https://jquery.org/license
24486 */
24487
24488//>>label: Dialog
24489//>>group: Widgets
24490//>>description: Displays customizable dialog windows.
24491//>>docs: https://api.jqueryui.com/dialog/
24492//>>demos: https://jqueryui.com/dialog/
24493//>>css.structure: ../../themes/base/core.css
24494//>>css.structure: ../../themes/base/dialog.css
24495//>>css.theme: ../../themes/base/theme.css
24496
24497( function( factory ) {
24498 "use strict";
24499
24500 if ( typeof define === "function" && define.amd ) {
24501
24502 // AMD. Register as an anonymous module.
24503 define( [
24504 "jquery",
24505 "./button",
24506 "./draggable",
24507 "./mouse",
24508 "./resizable",
24509 "../focusable",
24510 "../keycode",
24511 "../position",
24512 "../tabbable",
24513 "../unique-id",
24514 "../version",
24515 "../widget"
24516 ], factory );
24517 } else {
24518
24519 // Browser globals
24520 factory( jQuery );
24521 }
24522} )( function( $ ) {
24523"use strict";
24524
24525$.widget( "ui.dialog", {
24526 version: "1.14.1",
24527 options: {
24528 appendTo: "body",
24529 autoOpen: true,
24530 buttons: [],
24531 classes: {
24532 "ui-dialog": "ui-corner-all",
24533 "ui-dialog-titlebar": "ui-corner-all"
24534 },
24535 closeOnEscape: true,
24536 closeText: "Close",
24537 draggable: true,
24538 hide: null,
24539 height: "auto",
24540 maxHeight: null,
24541 maxWidth: null,
24542 minHeight: 150,
24543 minWidth: 150,
24544 modal: false,
24545 position: {
24546 my: "center",
24547 at: "center",
24548 of: window,
24549 collision: "fit",
24550
24551 // Ensure the titlebar is always visible
24552 using: function( pos ) {
24553 var topOffset = $( this ).css( pos ).offset().top;
24554 if ( topOffset < 0 ) {
24555 $( this ).css( "top", pos.top - topOffset );
24556 }
24557 }
24558 },
24559 resizable: true,
24560 show: null,
24561 title: null,
24562 uiDialogTitleHeadingLevel: 0,
24563 width: 300,
24564
24565 // Callbacks
24566 beforeClose: null,
24567 close: null,
24568 drag: null,
24569 dragStart: null,
24570 dragStop: null,
24571 focus: null,
24572 open: null,
24573 resize: null,
24574 resizeStart: null,
24575 resizeStop: null
24576 },
24577
24578 sizeRelatedOptions: {
24579 buttons: true,
24580 height: true,
24581 maxHeight: true,
24582 maxWidth: true,
24583 minHeight: true,
24584 minWidth: true,
24585 width: true
24586 },
24587
24588 resizableRelatedOptions: {
24589 maxHeight: true,
24590 maxWidth: true,
24591 minHeight: true,
24592 minWidth: true
24593 },
24594
24595 _create: function() {
24596 this.originalCss = {
24597 display: this.element[ 0 ].style.display,
24598 width: this.element[ 0 ].style.width,
24599 minHeight: this.element[ 0 ].style.minHeight,
24600 maxHeight: this.element[ 0 ].style.maxHeight,
24601 height: this.element[ 0 ].style.height
24602 };
24603 this.originalPosition = {
24604 parent: this.element.parent(),
24605 index: this.element.parent().children().index( this.element )
24606 };
24607 this.originalTitle = this.element.attr( "title" );
24608 if ( this.options.title == null && this.originalTitle != null ) {
24609 this.options.title = this.originalTitle;
24610 }
24611
24612 // Dialogs can't be disabled
24613 if ( this.options.disabled ) {
24614 this.options.disabled = false;
24615 }
24616
24617 this._createWrapper();
24618
24619 this.element
24620 .show()
24621 .removeAttr( "title" )
24622 .appendTo( this.uiDialog );
24623
24624 this._addClass( "ui-dialog-content", "ui-widget-content" );
24625
24626 this._createTitlebar();
24627 this._createButtonPane();
24628
24629 if ( this.options.draggable && $.fn.draggable ) {
24630 this._makeDraggable();
24631 }
24632 if ( this.options.resizable && $.fn.resizable ) {
24633 this._makeResizable();
24634 }
24635
24636 this._isOpen = false;
24637
24638 this._trackFocus();
24639 },
24640
24641 _init: function() {
24642 if ( this.options.autoOpen ) {
24643 this.open();
24644 }
24645 },
24646
24647 _appendTo: function() {
24648 var element = this.options.appendTo;
24649 if ( element && ( element.jquery || element.nodeType ) ) {
24650 return $( element );
24651 }
24652 return this.document.find( element || "body" ).eq( 0 );
24653 },
24654
24655 _destroy: function() {
24656 var next,
24657 originalPosition = this.originalPosition;
24658
24659 this._untrackInstance();
24660 this._destroyOverlay();
24661
24662 this.element
24663 .removeUniqueId()
24664 .css( this.originalCss )
24665
24666 // Without detaching first, the following becomes really slow
24667 .detach();
24668
24669 this.uiDialog.remove();
24670
24671 if ( this.originalTitle ) {
24672 this.element.attr( "title", this.originalTitle );
24673 }
24674
24675 next = originalPosition.parent.children().eq( originalPosition.index );
24676
24677 // Don't try to place the dialog next to itself (#8613)
24678 if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
24679 next.before( this.element );
24680 } else {
24681 originalPosition.parent.append( this.element );
24682 }
24683 },
24684
24685 widget: function() {
24686 return this.uiDialog;
24687 },
24688
24689 disable: $.noop,
24690 enable: $.noop,
24691
24692 close: function( event ) {
24693 var that = this;
24694
24695 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
24696 return;
24697 }
24698
24699 this._isOpen = false;
24700 this._focusedElement = null;
24701 this._destroyOverlay();
24702 this._untrackInstance();
24703
24704 if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
24705
24706 // Hiding a focused element doesn't trigger blur in WebKit
24707 // so in case we have nothing to focus on, explicitly blur the active element
24708 // https://bugs.webkit.org/show_bug.cgi?id=47182
24709 $( this.document[ 0 ].activeElement ).trigger( "blur" );
24710 }
24711
24712 this._hide( this.uiDialog, this.options.hide, function() {
24713 that._trigger( "close", event );
24714 } );
24715 },
24716
24717 isOpen: function() {
24718 return this._isOpen;
24719 },
24720
24721 moveToTop: function() {
24722 this._moveToTop();
24723 },
24724
24725 _moveToTop: function( event, silent ) {
24726 var moved = false,
24727 zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
24728 return +$( this ).css( "z-index" );
24729 } ).get(),
24730 zIndexMax = Math.max.apply( null, zIndices );
24731
24732 if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
24733 this.uiDialog.css( "z-index", zIndexMax + 1 );
24734 moved = true;
24735 }
24736
24737 if ( moved && !silent ) {
24738 this._trigger( "focus", event );
24739 }
24740 return moved;
24741 },
24742
24743 open: function() {
24744 var that = this;
24745 if ( this._isOpen ) {
24746 if ( this._moveToTop() ) {
24747 this._focusTabbable();
24748 }
24749 return;
24750 }
24751
24752 this._isOpen = true;
24753 this.opener = $( this.document[ 0 ].activeElement );
24754
24755 this._size();
24756 this._position();
24757 this._createOverlay();
24758 this._moveToTop( null, true );
24759
24760 // Ensure the overlay is moved to the top with the dialog, but only when
24761 // opening. The overlay shouldn't move after the dialog is open so that
24762 // modeless dialogs opened after the modal dialog stack properly.
24763 if ( this.overlay ) {
24764 this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
24765 }
24766
24767 this._show( this.uiDialog, this.options.show, function() {
24768 that._focusTabbable();
24769 that._trigger( "focus" );
24770 } );
24771
24772 // Track the dialog immediately upon opening in case a focus event
24773 // somehow occurs outside of the dialog before an element inside the
24774 // dialog is focused (#10152)
24775 this._makeFocusTarget();
24776
24777 this._trigger( "open" );
24778 },
24779
24780 _focusTabbable: function() {
24781
24782 // Set focus to the first match:
24783 // 1. An element that was focused previously
24784 // 2. First element inside the dialog matching [autofocus]
24785 // 3. Tabbable element inside the content element
24786 // 4. Tabbable element inside the buttonpane
24787 // 5. The close button
24788 // 6. The dialog itself
24789 var hasFocus = this._focusedElement;
24790 if ( !hasFocus ) {
24791 hasFocus = this.element.find( "[autofocus]" );
24792 }
24793 if ( !hasFocus.length ) {
24794 hasFocus = this.element.find( ":tabbable" );
24795 }
24796 if ( !hasFocus.length ) {
24797 hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
24798 }
24799 if ( !hasFocus.length ) {
24800 hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
24801 }
24802 if ( !hasFocus.length ) {
24803 hasFocus = this.uiDialog;
24804 }
24805 hasFocus.eq( 0 ).trigger( "focus" );
24806 },
24807
24808 _restoreTabbableFocus: function() {
24809 var activeElement = this.document[ 0 ].activeElement,
24810 isActive = this.uiDialog[ 0 ] === activeElement ||
24811 $.contains( this.uiDialog[ 0 ], activeElement );
24812 if ( !isActive ) {
24813 this._focusTabbable();
24814 }
24815 },
24816
24817 _keepFocus: function( event ) {
24818 event.preventDefault();
24819 this._restoreTabbableFocus();
24820 },
24821
24822 _createWrapper: function() {
24823 this.uiDialog = $( "<div>" )
24824 .hide()
24825 .attr( {
24826
24827 // Setting tabIndex makes the div focusable
24828 tabIndex: -1,
24829 role: "dialog",
24830 "aria-modal": this.options.modal ? "true" : null
24831 } )
24832 .appendTo( this._appendTo() );
24833
24834 this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
24835 this._on( this.uiDialog, {
24836 keydown: function( event ) {
24837 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
24838 event.keyCode === $.ui.keyCode.ESCAPE ) {
24839 event.preventDefault();
24840 this.close( event );
24841 return;
24842 }
24843
24844 // Prevent tabbing out of dialogs
24845 if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
24846 return;
24847 }
24848 var tabbables = this.uiDialog.find( ":tabbable" ),
24849 first = tabbables.first(),
24850 last = tabbables.last();
24851
24852 if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
24853 !event.shiftKey ) {
24854 this._delay( function() {
24855 first.trigger( "focus" );
24856 } );
24857 event.preventDefault();
24858 } else if ( ( event.target === first[ 0 ] ||
24859 event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
24860 this._delay( function() {
24861 last.trigger( "focus" );
24862 } );
24863 event.preventDefault();
24864 }
24865 },
24866 mousedown: function( event ) {
24867 if ( this._moveToTop( event ) ) {
24868 this._focusTabbable();
24869 }
24870 }
24871 } );
24872
24873 // We assume that any existing aria-describedby attribute means
24874 // that the dialog content is marked up properly
24875 // otherwise we brute force the content as the description
24876 if ( !this.element.find( "[aria-describedby]" ).length ) {
24877 this.uiDialog.attr( {
24878 "aria-describedby": this.element.uniqueId().attr( "id" )
24879 } );
24880 }
24881 },
24882
24883 _createTitlebar: function() {
24884 var uiDialogTitle;
24885
24886 this.uiDialogTitlebar = $( "<div>" );
24887 this._addClass( this.uiDialogTitlebar,
24888 "ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
24889 this._on( this.uiDialogTitlebar, {
24890 mousedown: function( event ) {
24891
24892 // Don't prevent click on close button (#8838)
24893 // Focusing a dialog that is partially scrolled out of view
24894 // causes the browser to scroll it into view, preventing the click event
24895 if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
24896
24897 // Dialog isn't getting focus when dragging (#8063)
24898 this.uiDialog.trigger( "focus" );
24899 }
24900 }
24901 } );
24902
24903 this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
24904 .button( {
24905 label: $( "<a>" ).text( this.options.closeText ).html(),
24906 icon: "ui-icon-closethick",
24907 showLabel: false
24908 } )
24909 .appendTo( this.uiDialogTitlebar );
24910
24911 this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
24912 this._on( this.uiDialogTitlebarClose, {
24913 click: function( event ) {
24914 event.preventDefault();
24915 this.close( event );
24916 }
24917 } );
24918
24919 var uiDialogHeadingLevel = Number.isInteger( this.options.uiDialogTitleHeadingLevel ) &&
24920 this.options.uiDialogTitleHeadingLevel > 0 &&
24921 this.options.uiDialogTitleHeadingLevel <= 6 ?
24922 "h" + this.options.uiDialogTitleHeadingLevel : "span";
24923
24924 uiDialogTitle = $( "<" + uiDialogHeadingLevel + ">" )
24925 .uniqueId().prependTo( this.uiDialogTitlebar );
24926 this._addClass( uiDialogTitle, "ui-dialog-title" );
24927 this._title( uiDialogTitle );
24928
24929 this.uiDialogTitlebar.prependTo( this.uiDialog );
24930
24931 this.uiDialog.attr( {
24932 "aria-labelledby": uiDialogTitle.attr( "id" )
24933 } );
24934 },
24935
24936 _title: function( title ) {
24937 if ( this.options.title ) {
24938 title.text( this.options.title );
24939 } else {
24940 title.html( "&#160;" );
24941 }
24942 },
24943
24944 _createButtonPane: function() {
24945 this.uiDialogButtonPane = $( "<div>" );
24946 this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
24947 "ui-widget-content ui-helper-clearfix" );
24948
24949 this.uiButtonSet = $( "<div>" )
24950 .appendTo( this.uiDialogButtonPane );
24951 this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
24952
24953 this._createButtons();
24954 },
24955
24956 _createButtons: function() {
24957 var that = this,
24958 buttons = this.options.buttons;
24959
24960 // If we already have a button pane, remove it
24961 this.uiDialogButtonPane.remove();
24962 this.uiButtonSet.empty();
24963
24964 if ( $.isEmptyObject( buttons ) || ( Array.isArray( buttons ) && !buttons.length ) ) {
24965 this._removeClass( this.uiDialog, "ui-dialog-buttons" );
24966 return;
24967 }
24968
24969 $.each( buttons, function( name, props ) {
24970 var click, buttonOptions;
24971 props = typeof props === "function" ?
24972 { click: props, text: name } :
24973 props;
24974
24975 // Default to a non-submitting button
24976 props = $.extend( { type: "button" }, props );
24977
24978 // Change the context for the click callback to be the main element
24979 click = props.click;
24980 buttonOptions = {
24981 icon: props.icon,
24982 iconPosition: props.iconPosition,
24983 showLabel: props.showLabel,
24984
24985 // Deprecated options
24986 icons: props.icons,
24987 text: props.text
24988 };
24989
24990 delete props.click;
24991 delete props.icon;
24992 delete props.iconPosition;
24993 delete props.showLabel;
24994
24995 // Deprecated options
24996 delete props.icons;
24997 if ( typeof props.text === "boolean" ) {
24998 delete props.text;
24999 }
25000
25001 $( "<button></button>", props )
25002 .button( buttonOptions )
25003 .appendTo( that.uiButtonSet )
25004 .on( "click", function() {
25005 click.apply( that.element[ 0 ], arguments );
25006 } );
25007 } );
25008 this._addClass( this.uiDialog, "ui-dialog-buttons" );
25009 this.uiDialogButtonPane.appendTo( this.uiDialog );
25010 },
25011
25012 _makeDraggable: function() {
25013 var that = this,
25014 options = this.options;
25015
25016 function filteredUi( ui ) {
25017 return {
25018 position: ui.position,
25019 offset: ui.offset
25020 };
25021 }
25022
25023 this.uiDialog.draggable( {
25024 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
25025 handle: ".ui-dialog-titlebar",
25026 containment: "document",
25027 start: function( event, ui ) {
25028 that._addClass( $( this ), "ui-dialog-dragging" );
25029 that._blockFrames();
25030 that._trigger( "dragStart", event, filteredUi( ui ) );
25031 },
25032 drag: function( event, ui ) {
25033 that._trigger( "drag", event, filteredUi( ui ) );
25034 },
25035 stop: function( event, ui ) {
25036 var left = ui.offset.left - that.document.scrollLeft(),
25037 top = ui.offset.top - that.document.scrollTop();
25038
25039 options.position = {
25040 my: "left top",
25041 at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
25042 "top" + ( top >= 0 ? "+" : "" ) + top,
25043 of: that.window
25044 };
25045 that._removeClass( $( this ), "ui-dialog-dragging" );
25046 that._unblockFrames();
25047 that._trigger( "dragStop", event, filteredUi( ui ) );
25048 }
25049 } );
25050 },
25051
25052 _makeResizable: function() {
25053 var that = this,
25054 options = this.options,
25055 handles = options.resizable,
25056
25057 // .ui-resizable has position: relative defined in the stylesheet
25058 // but dialogs have to use absolute or fixed positioning
25059 position = this.uiDialog.css( "position" ),
25060 resizeHandles = typeof handles === "string" ?
25061 handles :
25062 "n,e,s,w,se,sw,ne,nw";
25063
25064 function filteredUi( ui ) {
25065 return {
25066 originalPosition: ui.originalPosition,
25067 originalSize: ui.originalSize,
25068 position: ui.position,
25069 size: ui.size
25070 };
25071 }
25072
25073 this.uiDialog.resizable( {
25074 cancel: ".ui-dialog-content",
25075 containment: "document",
25076 alsoResize: this.element,
25077 maxWidth: options.maxWidth,
25078 maxHeight: options.maxHeight,
25079 minWidth: options.minWidth,
25080 minHeight: this._minHeight(),
25081 handles: resizeHandles,
25082 start: function( event, ui ) {
25083 that._addClass( $( this ), "ui-dialog-resizing" );
25084 that._blockFrames();
25085 that._trigger( "resizeStart", event, filteredUi( ui ) );
25086 },
25087 resize: function( event, ui ) {
25088 that._trigger( "resize", event, filteredUi( ui ) );
25089 },
25090 stop: function( event, ui ) {
25091 var offset = that.uiDialog.offset(),
25092 left = offset.left - that.document.scrollLeft(),
25093 top = offset.top - that.document.scrollTop();
25094
25095 options.height = that.uiDialog.height();
25096 options.width = that.uiDialog.width();
25097 options.position = {
25098 my: "left top",
25099 at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
25100 "top" + ( top >= 0 ? "+" : "" ) + top,
25101 of: that.window
25102 };
25103 that._removeClass( $( this ), "ui-dialog-resizing" );
25104 that._unblockFrames();
25105 that._trigger( "resizeStop", event, filteredUi( ui ) );
25106 }
25107 } )
25108 .css( "position", position );
25109 },
25110
25111 _trackFocus: function() {
25112 this._on( this.widget(), {
25113 focusin: function( event ) {
25114 this._makeFocusTarget();
25115 this._focusedElement = $( event.target );
25116 }
25117 } );
25118 },
25119
25120 _makeFocusTarget: function() {
25121 this._untrackInstance();
25122 this._trackingInstances().unshift( this );
25123 },
25124
25125 _untrackInstance: function() {
25126 var instances = this._trackingInstances(),
25127 exists = $.inArray( this, instances );
25128 if ( exists !== -1 ) {
25129 instances.splice( exists, 1 );
25130 }
25131 },
25132
25133 _trackingInstances: function() {
25134 var instances = this.document.data( "ui-dialog-instances" );
25135 if ( !instances ) {
25136 instances = [];
25137 this.document.data( "ui-dialog-instances", instances );
25138 }
25139 return instances;
25140 },
25141
25142 _minHeight: function() {
25143 var options = this.options;
25144
25145 return options.height === "auto" ?
25146 options.minHeight :
25147 Math.min( options.minHeight, options.height );
25148 },
25149
25150 _position: function() {
25151
25152 // Need to show the dialog to get the actual offset in the position plugin
25153 var isVisible = this.uiDialog.is( ":visible" );
25154 if ( !isVisible ) {
25155 this.uiDialog.show();
25156 }
25157 this.uiDialog.position( this.options.position );
25158 if ( !isVisible ) {
25159 this.uiDialog.hide();
25160 }
25161 },
25162
25163 _setOptions: function( options ) {
25164 var that = this,
25165 resize = false,
25166 resizableOptions = {};
25167
25168 $.each( options, function( key, value ) {
25169 that._setOption( key, value );
25170
25171 if ( key in that.sizeRelatedOptions ) {
25172 resize = true;
25173 }
25174 if ( key in that.resizableRelatedOptions ) {
25175 resizableOptions[ key ] = value;
25176 }
25177 } );
25178
25179 if ( resize ) {
25180 this._size();
25181 this._position();
25182 }
25183 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
25184 this.uiDialog.resizable( "option", resizableOptions );
25185 }
25186 },
25187
25188 _setOption: function( key, value ) {
25189 var isDraggable, isResizable,
25190 uiDialog = this.uiDialog;
25191
25192 if ( key === "disabled" ) {
25193 return;
25194 }
25195
25196 this._super( key, value );
25197
25198 if ( key === "appendTo" ) {
25199 this.uiDialog.appendTo( this._appendTo() );
25200 }
25201
25202 if ( key === "buttons" ) {
25203 this._createButtons();
25204 }
25205
25206 if ( key === "closeText" ) {
25207 this.uiDialogTitlebarClose.button( {
25208
25209 // Ensure that we always pass a string
25210 label: $( "<a>" ).text( "" + this.options.closeText ).html()
25211 } );
25212 }
25213
25214 if ( key === "draggable" ) {
25215 isDraggable = uiDialog.is( ":data(ui-draggable)" );
25216 if ( isDraggable && !value ) {
25217 uiDialog.draggable( "destroy" );
25218 }
25219
25220 if ( !isDraggable && value ) {
25221 this._makeDraggable();
25222 }
25223 }
25224
25225 if ( key === "position" ) {
25226 this._position();
25227 }
25228
25229 if ( key === "resizable" ) {
25230
25231 // currently resizable, becoming non-resizable
25232 isResizable = uiDialog.is( ":data(ui-resizable)" );
25233 if ( isResizable && !value ) {
25234 uiDialog.resizable( "destroy" );
25235 }
25236
25237 // Currently resizable, changing handles
25238 if ( isResizable && typeof value === "string" ) {
25239 uiDialog.resizable( "option", "handles", value );
25240 }
25241
25242 // Currently non-resizable, becoming resizable
25243 if ( !isResizable && value !== false ) {
25244 this._makeResizable();
25245 }
25246 }
25247
25248 if ( key === "title" ) {
25249 this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
25250 }
25251
25252 if ( key === "modal" ) {
25253 uiDialog.attr( "aria-modal", value ? "true" : null );
25254 }
25255 },
25256
25257 _size: function() {
25258
25259 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
25260 // divs will both have width and height set, so we need to reset them
25261 var nonContentHeight, minContentHeight, maxContentHeight,
25262 options = this.options;
25263
25264 // Reset content sizing
25265 this.element.show().css( {
25266 width: "auto",
25267 minHeight: 0,
25268 maxHeight: "none",
25269 height: 0
25270 } );
25271
25272 if ( options.minWidth > options.width ) {
25273 options.width = options.minWidth;
25274 }
25275
25276 // Reset wrapper sizing
25277 // determine the height of all the non-content elements
25278 nonContentHeight = this.uiDialog.css( {
25279 height: "auto",
25280 width: options.width
25281 } )
25282 .outerHeight();
25283 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
25284 maxContentHeight = typeof options.maxHeight === "number" ?
25285 Math.max( 0, options.maxHeight - nonContentHeight ) :
25286 "none";
25287
25288 if ( options.height === "auto" ) {
25289 this.element.css( {
25290 minHeight: minContentHeight,
25291 maxHeight: maxContentHeight,
25292 height: "auto"
25293 } );
25294 } else {
25295 this.element.height( Math.max( 0, options.height - nonContentHeight ) );
25296 }
25297
25298 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
25299 this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
25300 }
25301 },
25302
25303 _blockFrames: function() {
25304 this.iframeBlocks = this.document.find( "iframe" ).map( function() {
25305 var iframe = $( this );
25306
25307 return $( "<div>" )
25308 .css( {
25309 position: "absolute",
25310 width: iframe.outerWidth(),
25311 height: iframe.outerHeight()
25312 } )
25313 .appendTo( iframe.parent() )
25314 .offset( iframe.offset() )[ 0 ];
25315 } );
25316 },
25317
25318 _unblockFrames: function() {
25319 if ( this.iframeBlocks ) {
25320 this.iframeBlocks.remove();
25321 delete this.iframeBlocks;
25322 }
25323 },
25324
25325 _allowInteraction: function( event ) {
25326 if ( $( event.target ).closest( ".ui-dialog" ).length ) {
25327 return true;
25328 }
25329
25330 // TODO: Remove hack when datepicker implements
25331 // the .ui-front logic (#8989)
25332 return !!$( event.target ).closest( ".ui-datepicker" ).length;
25333 },
25334
25335 _createOverlay: function() {
25336 if ( !this.options.modal ) {
25337 return;
25338 }
25339
25340 // We use a delay in case the overlay is created from an
25341 // event that we're going to be cancelling (#2804)
25342 var isOpening = true;
25343 this._delay( function() {
25344 isOpening = false;
25345 } );
25346
25347 if ( !this.document.data( "ui-dialog-overlays" ) ) {
25348
25349 // Prevent use of anchors and inputs
25350 // This doesn't use `_on()` because it is a shared event handler
25351 // across all open modal dialogs.
25352 this.document.on( "focusin.ui-dialog", function( event ) {
25353 if ( isOpening ) {
25354 return;
25355 }
25356
25357 var instance = this._trackingInstances()[ 0 ];
25358 if ( !instance._allowInteraction( event ) ) {
25359 event.preventDefault();
25360 instance._focusTabbable();
25361 }
25362 }.bind( this ) );
25363 }
25364
25365 this.overlay = $( "<div>" )
25366 .appendTo( this._appendTo() );
25367
25368 this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
25369 this._on( this.overlay, {
25370 mousedown: "_keepFocus"
25371 } );
25372 this.document.data( "ui-dialog-overlays",
25373 ( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
25374 },
25375
25376 _destroyOverlay: function() {
25377 if ( !this.options.modal ) {
25378 return;
25379 }
25380
25381 if ( this.overlay ) {
25382 var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
25383
25384 if ( !overlays ) {
25385 this.document.off( "focusin.ui-dialog" );
25386 this.document.removeData( "ui-dialog-overlays" );
25387 } else {
25388 this.document.data( "ui-dialog-overlays", overlays );
25389 }
25390
25391 this.overlay.remove();
25392 this.overlay = null;
25393 }
25394 }
25395} );
25396
25397// DEPRECATED
25398// TODO: switch return back to widget declaration at top of file when this is removed
25399if ( $.uiBackCompat === true ) {
25400
25401 // Backcompat for dialogClass option
25402 $.widget( "ui.dialog", $.ui.dialog, {
25403 options: {
25404 dialogClass: ""
25405 },
25406 _createWrapper: function() {
25407 this._super();
25408 this.uiDialog.addClass( this.options.dialogClass );
25409 },
25410 _setOption: function( key, value ) {
25411 if ( key === "dialogClass" ) {
25412 this.uiDialog
25413 .removeClass( this.options.dialogClass )
25414 .addClass( value );
25415 }
25416 this._superApply( arguments );
25417 }
25418 } );
25419}
25420
25421return $.ui.dialog;
25422
25423} );
25424
25425
25426
25427
25428
25429/*!
25430 * jQuery UI Droppable 1.14.1
25431 * https://jqueryui.com
25432 *
25433 * Copyright OpenJS Foundation and other contributors
25434 * Released under the MIT license.
25435 * https://jquery.org/license
25436 */
25437
25438//>>label: Droppable
25439//>>group: Interactions
25440//>>description: Enables drop targets for draggable elements.
25441//>>docs: https://api.jqueryui.com/droppable/
25442//>>demos: https://jqueryui.com/droppable/
25443
25444( function( factory ) {
25445 "use strict";
25446
25447 if ( typeof define === "function" && define.amd ) {
25448
25449 // AMD. Register as an anonymous module.
25450 define( [
25451 "jquery",
25452 "./draggable",
25453 "./mouse",
25454 "../version",
25455 "../widget"
25456 ], factory );
25457 } else {
25458
25459 // Browser globals
25460 factory( jQuery );
25461 }
25462} )( function( $ ) {
25463"use strict";
25464
25465$.widget( "ui.droppable", {
25466 version: "1.14.1",
25467 widgetEventPrefix: "drop",
25468 options: {
25469 accept: "*",
25470 addClasses: true,
25471 greedy: false,
25472 scope: "default",
25473 tolerance: "intersect",
25474
25475 // Callbacks
25476 activate: null,
25477 deactivate: null,
25478 drop: null,
25479 out: null,
25480 over: null
25481 },
25482 _create: function() {
25483
25484 var proportions,
25485 o = this.options,
25486 accept = o.accept;
25487
25488 this.isover = false;
25489 this.isout = true;
25490
25491 this.accept = typeof accept === "function" ? accept : function( d ) {
25492 return d.is( accept );
25493 };
25494
25495 this.proportions = function( /* valueToWrite */ ) {
25496 if ( arguments.length ) {
25497
25498 // Store the droppable's proportions
25499 proportions = arguments[ 0 ];
25500 } else {
25501
25502 // Retrieve or derive the droppable's proportions
25503 return proportions ?
25504 proportions :
25505 proportions = {
25506 width: this.element[ 0 ].offsetWidth,
25507 height: this.element[ 0 ].offsetHeight
25508 };
25509 }
25510 };
25511
25512 this._addToManager( o.scope );
25513
25514 if ( o.addClasses ) {
25515 this._addClass( "ui-droppable" );
25516 }
25517
25518 },
25519
25520 _addToManager: function( scope ) {
25521
25522 // Add the reference and positions to the manager
25523 $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
25524 $.ui.ddmanager.droppables[ scope ].push( this );
25525 },
25526
25527 _splice: function( drop ) {
25528 var i = 0;
25529 for ( ; i < drop.length; i++ ) {
25530 if ( drop[ i ] === this ) {
25531 drop.splice( i, 1 );
25532 }
25533 }
25534 },
25535
25536 _destroy: function() {
25537 var drop = $.ui.ddmanager.droppables[ this.options.scope ];
25538
25539 this._splice( drop );
25540 },
25541
25542 _setOption: function( key, value ) {
25543
25544 if ( key === "accept" ) {
25545 this.accept = typeof value === "function" ? value : function( d ) {
25546 return d.is( value );
25547 };
25548 } else if ( key === "scope" ) {
25549 var drop = $.ui.ddmanager.droppables[ this.options.scope ];
25550
25551 this._splice( drop );
25552 this._addToManager( value );
25553 }
25554
25555 this._super( key, value );
25556 },
25557
25558 _activate: function( event ) {
25559 var draggable = $.ui.ddmanager.current;
25560
25561 this._addActiveClass();
25562 if ( draggable ) {
25563 this._trigger( "activate", event, this.ui( draggable ) );
25564 }
25565 },
25566
25567 _deactivate: function( event ) {
25568 var draggable = $.ui.ddmanager.current;
25569
25570 this._removeActiveClass();
25571 if ( draggable ) {
25572 this._trigger( "deactivate", event, this.ui( draggable ) );
25573 }
25574 },
25575
25576 _over: function( event ) {
25577
25578 var draggable = $.ui.ddmanager.current;
25579
25580 // Bail if draggable and droppable are same element
25581 if ( !draggable || ( draggable.currentItem ||
25582 draggable.element )[ 0 ] === this.element[ 0 ] ) {
25583 return;
25584 }
25585
25586 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
25587 draggable.element ) ) ) {
25588 this._addHoverClass();
25589 this._trigger( "over", event, this.ui( draggable ) );
25590 }
25591
25592 },
25593
25594 _out: function( event ) {
25595
25596 var draggable = $.ui.ddmanager.current;
25597
25598 // Bail if draggable and droppable are same element
25599 if ( !draggable || ( draggable.currentItem ||
25600 draggable.element )[ 0 ] === this.element[ 0 ] ) {
25601 return;
25602 }
25603
25604 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
25605 draggable.element ) ) ) {
25606 this._removeHoverClass();
25607 this._trigger( "out", event, this.ui( draggable ) );
25608 }
25609
25610 },
25611
25612 _drop: function( event, custom ) {
25613
25614 var draggable = custom || $.ui.ddmanager.current,
25615 childrenIntersection = false;
25616
25617 // Bail if draggable and droppable are same element
25618 if ( !draggable || ( draggable.currentItem ||
25619 draggable.element )[ 0 ] === this.element[ 0 ] ) {
25620 return false;
25621 }
25622
25623 this.element
25624 .find( ":data(ui-droppable)" )
25625 .not( ".ui-draggable-dragging" )
25626 .each( function() {
25627 var inst = $( this ).droppable( "instance" );
25628 if (
25629 inst.options.greedy &&
25630 !inst.options.disabled &&
25631 inst.options.scope === draggable.options.scope &&
25632 inst.accept.call(
25633 inst.element[ 0 ], ( draggable.currentItem || draggable.element )
25634 ) &&
25635 $.ui.intersect(
25636 draggable,
25637 $.extend( inst, { offset: inst.element.offset() } ),
25638 inst.options.tolerance, event
25639 )
25640 ) {
25641 childrenIntersection = true;
25642 return false;
25643 }
25644 } );
25645 if ( childrenIntersection ) {
25646 return false;
25647 }
25648
25649 if ( this.accept.call( this.element[ 0 ],
25650 ( draggable.currentItem || draggable.element ) ) ) {
25651 this._removeActiveClass();
25652 this._removeHoverClass();
25653
25654 this._trigger( "drop", event, this.ui( draggable ) );
25655 return this.element;
25656 }
25657
25658 return false;
25659
25660 },
25661
25662 ui: function( c ) {
25663 return {
25664 draggable: ( c.currentItem || c.element ),
25665 helper: c.helper,
25666 position: c.position,
25667 offset: c.positionAbs
25668 };
25669 },
25670
25671 // Extension points just to make backcompat sane and avoid duplicating logic
25672 // TODO: Remove in 1.14 along with call to it below
25673 _addHoverClass: function() {
25674 this._addClass( "ui-droppable-hover" );
25675 },
25676
25677 _removeHoverClass: function() {
25678 this._removeClass( "ui-droppable-hover" );
25679 },
25680
25681 _addActiveClass: function() {
25682 this._addClass( "ui-droppable-active" );
25683 },
25684
25685 _removeActiveClass: function() {
25686 this._removeClass( "ui-droppable-active" );
25687 }
25688} );
25689
25690$.ui.intersect = ( function() {
25691 function isOverAxis( x, reference, size ) {
25692 return ( x >= reference ) && ( x < ( reference + size ) );
25693 }
25694
25695 return function( draggable, droppable, toleranceMode, event ) {
25696
25697 if ( !droppable.offset ) {
25698 return false;
25699 }
25700
25701 var x1 = ( draggable.positionAbs ||
25702 draggable.position.absolute ).left + draggable.margins.left,
25703 y1 = ( draggable.positionAbs ||
25704 draggable.position.absolute ).top + draggable.margins.top,
25705 x2 = x1 + draggable.helperProportions.width,
25706 y2 = y1 + draggable.helperProportions.height,
25707 l = droppable.offset.left,
25708 t = droppable.offset.top,
25709 r = l + droppable.proportions().width,
25710 b = t + droppable.proportions().height;
25711
25712 switch ( toleranceMode ) {
25713 case "fit":
25714 return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
25715 case "intersect":
25716 return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
25717 x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
25718 t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
25719 y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
25720 case "pointer":
25721 return isOverAxis( event.pageY, t, droppable.proportions().height ) &&
25722 isOverAxis( event.pageX, l, droppable.proportions().width );
25723 case "touch":
25724 return (
25725 ( y1 >= t && y1 <= b ) || // Top edge touching
25726 ( y2 >= t && y2 <= b ) || // Bottom edge touching
25727 ( y1 < t && y2 > b ) // Surrounded vertically
25728 ) && (
25729 ( x1 >= l && x1 <= r ) || // Left edge touching
25730 ( x2 >= l && x2 <= r ) || // Right edge touching
25731 ( x1 < l && x2 > r ) // Surrounded horizontally
25732 );
25733 default:
25734 return false;
25735 }
25736 };
25737} )();
25738
25739/*
25740 This manager tracks offsets of draggables and droppables
25741*/
25742$.ui.ddmanager = {
25743 current: null,
25744 droppables: { "default": [] },
25745 prepareOffsets: function( t, event ) {
25746
25747 var i, j,
25748 m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
25749 type = event ? event.type : null, // workaround for #2317
25750 list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
25751
25752 droppablesLoop: for ( i = 0; i < m.length; i++ ) {
25753
25754 // No disabled and non-accepted
25755 if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],
25756 ( t.currentItem || t.element ) ) ) ) {
25757 continue;
25758 }
25759
25760 // Filter out elements in the current dragged item
25761 for ( j = 0; j < list.length; j++ ) {
25762 if ( list[ j ] === m[ i ].element[ 0 ] ) {
25763 m[ i ].proportions().height = 0;
25764 continue droppablesLoop;
25765 }
25766 }
25767
25768 m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
25769 if ( !m[ i ].visible ) {
25770 continue;
25771 }
25772
25773 // Activate the droppable if used directly from draggables
25774 if ( type === "mousedown" ) {
25775 m[ i ]._activate.call( m[ i ], event );
25776 }
25777
25778 m[ i ].offset = m[ i ].element.offset();
25779 m[ i ].proportions( {
25780 width: m[ i ].element[ 0 ].offsetWidth,
25781 height: m[ i ].element[ 0 ].offsetHeight
25782 } );
25783
25784 }
25785
25786 },
25787 drop: function( draggable, event ) {
25788
25789 var dropped = false;
25790
25791 // Create a copy of the droppables in case the list changes during the drop (#9116)
25792 $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
25793
25794 if ( !this.options ) {
25795 return;
25796 }
25797 if ( !this.options.disabled && this.visible &&
25798 $.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
25799 dropped = this._drop.call( this, event ) || dropped;
25800 }
25801
25802 if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],
25803 ( draggable.currentItem || draggable.element ) ) ) {
25804 this.isout = true;
25805 this.isover = false;
25806 this._deactivate.call( this, event );
25807 }
25808
25809 } );
25810 return dropped;
25811
25812 },
25813 dragStart: function( draggable, event ) {
25814
25815 // Listen for scrolling so that if the dragging causes scrolling the position of the
25816 // droppables can be recalculated (see #5003)
25817 draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() {
25818 if ( !draggable.options.refreshPositions ) {
25819 $.ui.ddmanager.prepareOffsets( draggable, event );
25820 }
25821 } );
25822 },
25823 drag: function( draggable, event ) {
25824
25825 // If you have a highly dynamic page, you might try this option. It renders positions
25826 // every time you move the mouse.
25827 if ( draggable.options.refreshPositions ) {
25828 $.ui.ddmanager.prepareOffsets( draggable, event );
25829 }
25830
25831 // Run through all droppables and check their positions based on specific tolerance options
25832 $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
25833
25834 if ( this.options.disabled || this.greedyChild || !this.visible ) {
25835 return;
25836 }
25837
25838 var parentInstance, scope, parent,
25839 intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
25840 c = !intersects && this.isover ?
25841 "isout" :
25842 ( intersects && !this.isover ? "isover" : null );
25843 if ( !c ) {
25844 return;
25845 }
25846
25847 if ( this.options.greedy ) {
25848
25849 // find droppable parents with same scope
25850 scope = this.options.scope;
25851 parent = this.element.parents( ":data(ui-droppable)" ).filter( function() {
25852 return $( this ).droppable( "instance" ).options.scope === scope;
25853 } );
25854
25855 if ( parent.length ) {
25856 parentInstance = $( parent[ 0 ] ).droppable( "instance" );
25857 parentInstance.greedyChild = ( c === "isover" );
25858 }
25859 }
25860
25861 // We just moved into a greedy child
25862 if ( parentInstance && c === "isover" ) {
25863 parentInstance.isover = false;
25864 parentInstance.isout = true;
25865 parentInstance._out.call( parentInstance, event );
25866 }
25867
25868 this[ c ] = true;
25869 this[ c === "isout" ? "isover" : "isout" ] = false;
25870 this[ c === "isover" ? "_over" : "_out" ].call( this, event );
25871
25872 // We just moved out of a greedy child
25873 if ( parentInstance && c === "isout" ) {
25874 parentInstance.isout = false;
25875 parentInstance.isover = true;
25876 parentInstance._over.call( parentInstance, event );
25877 }
25878 } );
25879
25880 },
25881 dragStop: function( draggable, event ) {
25882 draggable.element.parentsUntil( "body" ).off( "scroll.droppable" );
25883
25884 // Call prepareOffsets one final time since IE does not fire return scroll events when
25885 // overflow was caused by drag (see #5003)
25886 if ( !draggable.options.refreshPositions ) {
25887 $.ui.ddmanager.prepareOffsets( draggable, event );
25888 }
25889 }
25890};
25891
25892// DEPRECATED
25893// TODO: switch return back to widget declaration at top of file when this is removed
25894if ( $.uiBackCompat === true ) {
25895
25896 // Backcompat for activeClass and hoverClass options
25897 $.widget( "ui.droppable", $.ui.droppable, {
25898 options: {
25899 hoverClass: false,
25900 activeClass: false
25901 },
25902 _addActiveClass: function() {
25903 this._super();
25904 if ( this.options.activeClass ) {
25905 this.element.addClass( this.options.activeClass );
25906 }
25907 },
25908 _removeActiveClass: function() {
25909 this._super();
25910 if ( this.options.activeClass ) {
25911 this.element.removeClass( this.options.activeClass );
25912 }
25913 },
25914 _addHoverClass: function() {
25915 this._super();
25916 if ( this.options.hoverClass ) {
25917 this.element.addClass( this.options.hoverClass );
25918 }
25919 },
25920 _removeHoverClass: function() {
25921 this._super();
25922 if ( this.options.hoverClass ) {
25923 this.element.removeClass( this.options.hoverClass );
25924 }
25925 }
25926 } );
25927}
25928
25929return $.ui.droppable;
25930
25931} );
25932
25933
25934
25935/*!
25936 * jQuery UI Progressbar 1.14.1
25937 * https://jqueryui.com
25938 *
25939 * Copyright OpenJS Foundation and other contributors
25940 * Released under the MIT license.
25941 * https://jquery.org/license
25942 */
25943
25944//>>label: Progressbar
25945//>>group: Widgets
25946/* eslint-disable max-len */
25947//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.
25948/* eslint-enable max-len */
25949//>>docs: https://api.jqueryui.com/progressbar/
25950//>>demos: https://jqueryui.com/progressbar/
25951//>>css.structure: ../../themes/base/core.css
25952//>>css.structure: ../../themes/base/progressbar.css
25953//>>css.theme: ../../themes/base/theme.css
25954
25955( function( factory ) {
25956 "use strict";
25957
25958 if ( typeof define === "function" && define.amd ) {
25959
25960 // AMD. Register as an anonymous module.
25961 define( [
25962 "jquery",
25963 "../version",
25964 "../widget"
25965 ], factory );
25966 } else {
25967
25968 // Browser globals
25969 factory( jQuery );
25970 }
25971} )( function( $ ) {
25972"use strict";
25973
25974return $.widget( "ui.progressbar", {
25975 version: "1.14.1",
25976 options: {
25977 classes: {
25978 "ui-progressbar": "ui-corner-all",
25979 "ui-progressbar-value": "ui-corner-left",
25980 "ui-progressbar-complete": "ui-corner-right"
25981 },
25982 max: 100,
25983 value: 0,
25984
25985 change: null,
25986 complete: null
25987 },
25988
25989 min: 0,
25990
25991 _create: function() {
25992
25993 // Constrain initial value
25994 this.oldValue = this.options.value = this._constrainedValue();
25995
25996 this.element.attr( {
25997
25998 // Only set static values; aria-valuenow and aria-valuemax are
25999 // set inside _refreshValue()
26000 role: "progressbar",
26001 "aria-valuemin": this.min
26002 } );
26003 this._addClass( "ui-progressbar", "ui-widget ui-widget-content" );
26004
26005 this.valueDiv = $( "<div>" ).appendTo( this.element );
26006 this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" );
26007 this._refreshValue();
26008 },
26009
26010 _destroy: function() {
26011 this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" );
26012
26013 this.valueDiv.remove();
26014 },
26015
26016 value: function( newValue ) {
26017 if ( newValue === undefined ) {
26018 return this.options.value;
26019 }
26020
26021 this.options.value = this._constrainedValue( newValue );
26022 this._refreshValue();
26023 },
26024
26025 _constrainedValue: function( newValue ) {
26026 if ( newValue === undefined ) {
26027 newValue = this.options.value;
26028 }
26029
26030 this.indeterminate = newValue === false;
26031
26032 // Sanitize value
26033 if ( typeof newValue !== "number" ) {
26034 newValue = 0;
26035 }
26036
26037 return this.indeterminate ? false :
26038 Math.min( this.options.max, Math.max( this.min, newValue ) );
26039 },
26040
26041 _setOptions: function( options ) {
26042
26043 // Ensure "value" option is set after other values (like max)
26044 var value = options.value;
26045 delete options.value;
26046
26047 this._super( options );
26048
26049 this.options.value = this._constrainedValue( value );
26050 this._refreshValue();
26051 },
26052
26053 _setOption: function( key, value ) {
26054 if ( key === "max" ) {
26055
26056 // Don't allow a max less than min
26057 value = Math.max( this.min, value );
26058 }
26059 this._super( key, value );
26060 },
26061
26062 _setOptionDisabled: function( value ) {
26063 this._super( value );
26064
26065 this.element.attr( "aria-disabled", value );
26066 this._toggleClass( null, "ui-state-disabled", !!value );
26067 },
26068
26069 _percentage: function() {
26070 return this.indeterminate ?
26071 100 :
26072 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
26073 },
26074
26075 _refreshValue: function() {
26076 var value = this.options.value,
26077 percentage = this._percentage();
26078
26079 this.valueDiv
26080 .toggle( this.indeterminate || value > this.min )
26081 .width( percentage.toFixed( 0 ) + "%" );
26082
26083 this
26084 ._toggleClass( this.valueDiv, "ui-progressbar-complete", null,
26085 value === this.options.max )
26086 ._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate );
26087
26088 if ( this.indeterminate ) {
26089 this.element.removeAttr( "aria-valuenow" );
26090 if ( !this.overlayDiv ) {
26091 this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv );
26092 this._addClass( this.overlayDiv, "ui-progressbar-overlay" );
26093 }
26094 } else {
26095 this.element.attr( {
26096 "aria-valuemax": this.options.max,
26097 "aria-valuenow": value
26098 } );
26099 if ( this.overlayDiv ) {
26100 this.overlayDiv.remove();
26101 this.overlayDiv = null;
26102 }
26103 }
26104
26105 if ( this.oldValue !== value ) {
26106 this.oldValue = value;
26107 this._trigger( "change" );
26108 }
26109 if ( value === this.options.max ) {
26110 this._trigger( "complete" );
26111 }
26112 }
26113} );
26114
26115} );
26116
26117
26118
26119
26120/*!
26121 * jQuery UI Selectable 1.14.1
26122 * https://jqueryui.com
26123 *
26124 * Copyright OpenJS Foundation and other contributors
26125 * Released under the MIT license.
26126 * https://jquery.org/license
26127 */
26128
26129//>>label: Selectable
26130//>>group: Interactions
26131//>>description: Allows groups of elements to be selected with the mouse.
26132//>>docs: https://api.jqueryui.com/selectable/
26133//>>demos: https://jqueryui.com/selectable/
26134//>>css.structure: ../../themes/base/selectable.css
26135
26136( function( factory ) {
26137 "use strict";
26138
26139 if ( typeof define === "function" && define.amd ) {
26140
26141 // AMD. Register as an anonymous module.
26142 define( [
26143 "jquery",
26144 "./mouse",
26145 "../version",
26146 "../widget"
26147 ], factory );
26148 } else {
26149
26150 // Browser globals
26151 factory( jQuery );
26152 }
26153} )( function( $ ) {
26154"use strict";
26155
26156return $.widget( "ui.selectable", $.ui.mouse, {
26157 version: "1.14.1",
26158 options: {
26159 appendTo: "body",
26160 autoRefresh: true,
26161 distance: 0,
26162 filter: "*",
26163 tolerance: "touch",
26164
26165 // Callbacks
26166 selected: null,
26167 selecting: null,
26168 start: null,
26169 stop: null,
26170 unselected: null,
26171 unselecting: null
26172 },
26173 _create: function() {
26174 var that = this;
26175
26176 this._addClass( "ui-selectable" );
26177
26178 this.dragged = false;
26179
26180 // Cache selectee children based on filter
26181 this.refresh = function() {
26182 that.elementPos = $( that.element[ 0 ] ).offset();
26183 that.selectees = $( that.options.filter, that.element[ 0 ] );
26184 that._addClass( that.selectees, "ui-selectee" );
26185 that.selectees.each( function() {
26186 var $this = $( this ),
26187 selecteeOffset = $this.offset(),
26188 pos = {
26189 left: selecteeOffset.left - that.elementPos.left,
26190 top: selecteeOffset.top - that.elementPos.top
26191 };
26192 $.data( this, "selectable-item", {
26193 element: this,
26194 $element: $this,
26195 left: pos.left,
26196 top: pos.top,
26197 right: pos.left + $this.outerWidth(),
26198 bottom: pos.top + $this.outerHeight(),
26199 startselected: false,
26200 selected: $this.hasClass( "ui-selected" ),
26201 selecting: $this.hasClass( "ui-selecting" ),
26202 unselecting: $this.hasClass( "ui-unselecting" )
26203 } );
26204 } );
26205 };
26206 this.refresh();
26207
26208 this._mouseInit();
26209
26210 this.helper = $( "<div>" );
26211 this._addClass( this.helper, "ui-selectable-helper" );
26212 },
26213
26214 _destroy: function() {
26215 this.selectees.removeData( "selectable-item" );
26216 this._mouseDestroy();
26217 },
26218
26219 _mouseStart: function( event ) {
26220 var that = this,
26221 options = this.options;
26222
26223 this.opos = [ event.pageX, event.pageY ];
26224 this.elementPos = $( this.element[ 0 ] ).offset();
26225
26226 if ( this.options.disabled ) {
26227 return;
26228 }
26229
26230 this.selectees = $( options.filter, this.element[ 0 ] );
26231
26232 this._trigger( "start", event );
26233
26234 $( options.appendTo ).append( this.helper );
26235
26236 // position helper (lasso)
26237 this.helper.css( {
26238 "left": event.pageX,
26239 "top": event.pageY,
26240 "width": 0,
26241 "height": 0
26242 } );
26243
26244 if ( options.autoRefresh ) {
26245 this.refresh();
26246 }
26247
26248 this.selectees.filter( ".ui-selected" ).each( function() {
26249 var selectee = $.data( this, "selectable-item" );
26250 selectee.startselected = true;
26251 if ( !event.metaKey && !event.ctrlKey ) {
26252 that._removeClass( selectee.$element, "ui-selected" );
26253 selectee.selected = false;
26254 that._addClass( selectee.$element, "ui-unselecting" );
26255 selectee.unselecting = true;
26256
26257 // selectable UNSELECTING callback
26258 that._trigger( "unselecting", event, {
26259 unselecting: selectee.element
26260 } );
26261 }
26262 } );
26263
26264 $( event.target ).parents().addBack().each( function() {
26265 var doSelect,
26266 selectee = $.data( this, "selectable-item" );
26267 if ( selectee ) {
26268 doSelect = ( !event.metaKey && !event.ctrlKey ) ||
26269 !selectee.$element.hasClass( "ui-selected" );
26270 that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" )
26271 ._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" );
26272 selectee.unselecting = !doSelect;
26273 selectee.selecting = doSelect;
26274 selectee.selected = doSelect;
26275
26276 // selectable (UN)SELECTING callback
26277 if ( doSelect ) {
26278 that._trigger( "selecting", event, {
26279 selecting: selectee.element
26280 } );
26281 } else {
26282 that._trigger( "unselecting", event, {
26283 unselecting: selectee.element
26284 } );
26285 }
26286 return false;
26287 }
26288 } );
26289
26290 },
26291
26292 _mouseDrag: function( event ) {
26293
26294 this.dragged = true;
26295
26296 if ( this.options.disabled ) {
26297 return;
26298 }
26299
26300 var tmp,
26301 that = this,
26302 options = this.options,
26303 x1 = this.opos[ 0 ],
26304 y1 = this.opos[ 1 ],
26305 x2 = event.pageX,
26306 y2 = event.pageY;
26307
26308 if ( x1 > x2 ) {
26309 tmp = x2; x2 = x1; x1 = tmp;
26310 }
26311 if ( y1 > y2 ) {
26312 tmp = y2; y2 = y1; y1 = tmp;
26313 }
26314 this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } );
26315
26316 this.selectees.each( function() {
26317 var selectee = $.data( this, "selectable-item" ),
26318 hit = false,
26319 offset = {};
26320
26321 //prevent helper from being selected if appendTo: selectable
26322 if ( !selectee || selectee.element === that.element[ 0 ] ) {
26323 return;
26324 }
26325
26326 offset.left = selectee.left + that.elementPos.left;
26327 offset.right = selectee.right + that.elementPos.left;
26328 offset.top = selectee.top + that.elementPos.top;
26329 offset.bottom = selectee.bottom + that.elementPos.top;
26330
26331 if ( options.tolerance === "touch" ) {
26332 hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 ||
26333 offset.bottom < y1 ) );
26334 } else if ( options.tolerance === "fit" ) {
26335 hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 &&
26336 offset.bottom < y2 );
26337 }
26338
26339 if ( hit ) {
26340
26341 // SELECT
26342 if ( selectee.selected ) {
26343 that._removeClass( selectee.$element, "ui-selected" );
26344 selectee.selected = false;
26345 }
26346 if ( selectee.unselecting ) {
26347 that._removeClass( selectee.$element, "ui-unselecting" );
26348 selectee.unselecting = false;
26349 }
26350 if ( !selectee.selecting ) {
26351 that._addClass( selectee.$element, "ui-selecting" );
26352 selectee.selecting = true;
26353
26354 // selectable SELECTING callback
26355 that._trigger( "selecting", event, {
26356 selecting: selectee.element
26357 } );
26358 }
26359 } else {
26360
26361 // UNSELECT
26362 if ( selectee.selecting ) {
26363 if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) {
26364 that._removeClass( selectee.$element, "ui-selecting" );
26365 selectee.selecting = false;
26366 that._addClass( selectee.$element, "ui-selected" );
26367 selectee.selected = true;
26368 } else {
26369 that._removeClass( selectee.$element, "ui-selecting" );
26370 selectee.selecting = false;
26371 if ( selectee.startselected ) {
26372 that._addClass( selectee.$element, "ui-unselecting" );
26373 selectee.unselecting = true;
26374 }
26375
26376 // selectable UNSELECTING callback
26377 that._trigger( "unselecting", event, {
26378 unselecting: selectee.element
26379 } );
26380 }
26381 }
26382 if ( selectee.selected ) {
26383 if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) {
26384 that._removeClass( selectee.$element, "ui-selected" );
26385 selectee.selected = false;
26386
26387 that._addClass( selectee.$element, "ui-unselecting" );
26388 selectee.unselecting = true;
26389
26390 // selectable UNSELECTING callback
26391 that._trigger( "unselecting", event, {
26392 unselecting: selectee.element
26393 } );
26394 }
26395 }
26396 }
26397 } );
26398
26399 return false;
26400 },
26401
26402 _mouseStop: function( event ) {
26403 var that = this;
26404
26405 this.dragged = false;
26406
26407 $( ".ui-unselecting", this.element[ 0 ] ).each( function() {
26408 var selectee = $.data( this, "selectable-item" );
26409 that._removeClass( selectee.$element, "ui-unselecting" );
26410 selectee.unselecting = false;
26411 selectee.startselected = false;
26412 that._trigger( "unselected", event, {
26413 unselected: selectee.element
26414 } );
26415 } );
26416 $( ".ui-selecting", this.element[ 0 ] ).each( function() {
26417 var selectee = $.data( this, "selectable-item" );
26418 that._removeClass( selectee.$element, "ui-selecting" )
26419 ._addClass( selectee.$element, "ui-selected" );
26420 selectee.selecting = false;
26421 selectee.selected = true;
26422 selectee.startselected = true;
26423 that._trigger( "selected", event, {
26424 selected: selectee.element
26425 } );
26426 } );
26427 this._trigger( "stop", event );
26428
26429 this.helper.remove();
26430
26431 return false;
26432 }
26433
26434} );
26435
26436} );
26437
26438
26439
26440
26441
26442
26443
26444
26445
26446/*!
26447 * jQuery UI Selectmenu 1.14.1
26448 * https://jqueryui.com
26449 *
26450 * Copyright OpenJS Foundation and other contributors
26451 * Released under the MIT license.
26452 * https://jquery.org/license
26453 */
26454
26455//>>label: Selectmenu
26456//>>group: Widgets
26457/* eslint-disable max-len */
26458//>>description: Duplicates and extends the functionality of a native HTML select element, allowing it to be customizable in behavior and appearance far beyond the limitations of a native select.
26459/* eslint-enable max-len */
26460//>>docs: https://api.jqueryui.com/selectmenu/
26461//>>demos: https://jqueryui.com/selectmenu/
26462//>>css.structure: ../../themes/base/core.css
26463//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css
26464//>>css.theme: ../../themes/base/theme.css
26465
26466( function( factory ) {
26467 "use strict";
26468
26469 if ( typeof define === "function" && define.amd ) {
26470
26471 // AMD. Register as an anonymous module.
26472 define( [
26473 "jquery",
26474 "./menu",
26475 "../form-reset-mixin",
26476 "../keycode",
26477 "../labels",
26478 "../position",
26479 "../unique-id",
26480 "../version",
26481 "../widget"
26482 ], factory );
26483 } else {
26484
26485 // Browser globals
26486 factory( jQuery );
26487 }
26488} )( function( $ ) {
26489"use strict";
26490
26491return $.widget( "ui.selectmenu", [ $.ui.formResetMixin, {
26492 version: "1.14.1",
26493 defaultElement: "<select>",
26494 options: {
26495 appendTo: null,
26496 classes: {
26497 "ui-selectmenu-button-open": "ui-corner-top",
26498 "ui-selectmenu-button-closed": "ui-corner-all"
26499 },
26500 disabled: null,
26501 icons: {
26502 button: "ui-icon-triangle-1-s"
26503 },
26504 position: {
26505 my: "left top",
26506 at: "left bottom",
26507 collision: "none"
26508 },
26509 width: false,
26510
26511 // Callbacks
26512 change: null,
26513 close: null,
26514 focus: null,
26515 open: null,
26516 select: null
26517 },
26518
26519 _create: function() {
26520 var selectmenuId = this.element.uniqueId().attr( "id" );
26521 this.ids = {
26522 element: selectmenuId,
26523 button: selectmenuId + "-button",
26524 menu: selectmenuId + "-menu"
26525 };
26526
26527 this._drawButton();
26528 this._drawMenu();
26529 this._bindFormResetHandler();
26530
26531 this._rendered = false;
26532 this.menuItems = $();
26533 },
26534
26535 _drawButton: function() {
26536 var icon,
26537 that = this,
26538 item = this._parseOption(
26539 this.element.find( "option:selected" ),
26540 this.element[ 0 ].selectedIndex
26541 );
26542
26543 // Associate existing label with the new button
26544 this.labels = this.element.labels().attr( "for", this.ids.button );
26545 this._on( this.labels, {
26546 click: function( event ) {
26547 this.button.trigger( "focus" );
26548 event.preventDefault();
26549 }
26550 } );
26551
26552 // Hide original select element
26553 this.element.hide();
26554
26555 // Create button
26556 this.button = $( "<span>", {
26557 tabindex: this.options.disabled ? -1 : 0,
26558 id: this.ids.button,
26559 role: "combobox",
26560 "aria-expanded": "false",
26561 "aria-autocomplete": "list",
26562 "aria-owns": this.ids.menu,
26563 "aria-haspopup": "true",
26564 title: this.element.attr( "title" )
26565 } )
26566 .insertAfter( this.element );
26567
26568 this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed",
26569 "ui-button ui-widget" );
26570
26571 icon = $( "<span>" ).appendTo( this.button );
26572 this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button );
26573 this.buttonItem = this._renderButtonItem( item )
26574 .appendTo( this.button );
26575
26576 if ( this.options.width !== false ) {
26577 this._resizeButton();
26578 }
26579
26580 this._on( this.button, this._buttonEvents );
26581 this.button.one( "focusin", function() {
26582
26583 // Delay rendering the menu items until the button receives focus.
26584 // The menu may have already been rendered via a programmatic open.
26585 if ( !that._rendered ) {
26586 that._refreshMenu();
26587 }
26588 } );
26589 },
26590
26591 _drawMenu: function() {
26592 var that = this;
26593
26594 // Create menu
26595 this.menu = $( "<ul>", {
26596 "aria-hidden": "true",
26597 "aria-labelledby": this.ids.button,
26598 id: this.ids.menu
26599 } );
26600
26601 // Wrap menu
26602 this.menuWrap = $( "<div>" ).append( this.menu );
26603 this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" );
26604 this.menuWrap.appendTo( this._appendTo() );
26605
26606 // Initialize menu widget
26607 this.menuInstance = this.menu
26608 .menu( {
26609 classes: {
26610 "ui-menu": "ui-corner-bottom"
26611 },
26612 role: "listbox",
26613 select: function( event, ui ) {
26614 event.preventDefault();
26615 that._select( ui.item.data( "ui-selectmenu-item" ), event );
26616 },
26617 focus: function( event, ui ) {
26618 var item = ui.item.data( "ui-selectmenu-item" );
26619
26620 // Prevent inital focus from firing and check if its a newly focused item
26621 if ( that.focusIndex != null && item.index !== that.focusIndex ) {
26622 that._trigger( "focus", event, { item: item } );
26623 if ( !that.isOpen ) {
26624 that._select( item, event );
26625 }
26626 }
26627 that.focusIndex = item.index;
26628
26629 that.button.attr( "aria-activedescendant",
26630 that.menuItems.eq( item.index ).attr( "id" ) );
26631 }
26632 } )
26633 .menu( "instance" );
26634
26635 // Don't close the menu on mouseleave
26636 this.menuInstance._off( this.menu, "mouseleave" );
26637
26638 // Cancel the menu's collapseAll on document click
26639 this.menuInstance._closeOnDocumentClick = function() {
26640 return false;
26641 };
26642
26643 // Selects often contain empty items, but never contain dividers
26644 this.menuInstance._isDivider = function() {
26645 return false;
26646 };
26647 },
26648
26649 refresh: function() {
26650 this._refreshMenu();
26651 this.buttonItem.replaceWith(
26652 this.buttonItem = this._renderButtonItem(
26653
26654 // Fall back to an empty object in case there are no options
26655 this._getSelectedItem().data( "ui-selectmenu-item" ) || {}
26656 )
26657 );
26658 if ( this.options.width === null ) {
26659 this._resizeButton();
26660 }
26661 },
26662
26663 _refreshMenu: function() {
26664 var item,
26665 options = this.element.find( "option" );
26666
26667 this.menu.empty();
26668
26669 this._parseOptions( options );
26670 this._renderMenu( this.menu, this.items );
26671
26672 this.menuInstance.refresh();
26673 this.menuItems = this.menu.find( "li" )
26674 .not( ".ui-selectmenu-optgroup" )
26675 .find( ".ui-menu-item-wrapper" );
26676
26677 this._rendered = true;
26678
26679 if ( !options.length ) {
26680 return;
26681 }
26682
26683 item = this._getSelectedItem();
26684
26685 // Update the menu to have the correct item focused
26686 this.menuInstance.focus( null, item );
26687 this._setAria( item.data( "ui-selectmenu-item" ) );
26688
26689 // Set disabled state
26690 this._setOption( "disabled", this.element.prop( "disabled" ) );
26691 },
26692
26693 open: function( event ) {
26694 if ( this.options.disabled ) {
26695 return;
26696 }
26697
26698 // If this is the first time the menu is being opened, render the items
26699 if ( !this._rendered ) {
26700 this._refreshMenu();
26701 } else {
26702
26703 // Menu clears focus on close, reset focus to selected item
26704 this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" );
26705 this.menuInstance.focus( null, this._getSelectedItem() );
26706 }
26707
26708 // If there are no options, don't open the menu
26709 if ( !this.menuItems.length ) {
26710 return;
26711 }
26712
26713 this.isOpen = true;
26714 this._toggleAttr();
26715 this._resizeMenu();
26716 this._position();
26717
26718 this._on( this.document, this._documentClick );
26719
26720 this._trigger( "open", event );
26721 },
26722
26723 _position: function() {
26724 this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
26725 },
26726
26727 close: function( event ) {
26728 if ( !this.isOpen ) {
26729 return;
26730 }
26731
26732 this.isOpen = false;
26733 this._toggleAttr();
26734
26735 this.range = null;
26736 this._off( this.document );
26737
26738 this._trigger( "close", event );
26739 },
26740
26741 widget: function() {
26742 return this.button;
26743 },
26744
26745 menuWidget: function() {
26746 return this.menu;
26747 },
26748
26749 _renderButtonItem: function( item ) {
26750 var buttonItem = $( "<span>" );
26751
26752 this._setText( buttonItem, item.label );
26753 this._addClass( buttonItem, "ui-selectmenu-text" );
26754
26755 return buttonItem;
26756 },
26757
26758 _renderMenu: function( ul, items ) {
26759 var that = this,
26760 currentOptgroup = "";
26761
26762 $.each( items, function( index, item ) {
26763 var li;
26764
26765 if ( item.optgroup !== currentOptgroup ) {
26766 li = $( "<li>", {
26767 text: item.optgroup
26768 } );
26769 that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" +
26770 ( item.element.parent( "optgroup" ).prop( "disabled" ) ?
26771 " ui-state-disabled" :
26772 "" ) );
26773
26774 li.appendTo( ul );
26775
26776 currentOptgroup = item.optgroup;
26777 }
26778
26779 that._renderItemData( ul, item );
26780 } );
26781 },
26782
26783 _renderItemData: function( ul, item ) {
26784 return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
26785 },
26786
26787 _renderItem: function( ul, item ) {
26788 var li = $( "<li>" ),
26789 wrapper = $( "<div>", {
26790 title: item.element.attr( "title" )
26791 } );
26792
26793 if ( item.disabled ) {
26794 this._addClass( li, null, "ui-state-disabled" );
26795 }
26796
26797 if ( item.hidden ) {
26798 li.prop( "hidden", true );
26799 } else {
26800 this._setText( wrapper, item.label );
26801 }
26802
26803 return li.append( wrapper ).appendTo( ul );
26804 },
26805
26806 _setText: function( element, value ) {
26807 if ( value ) {
26808 element.text( value );
26809 } else {
26810 element.html( "&#160;" );
26811 }
26812 },
26813
26814 _move: function( direction, event ) {
26815 var item, next,
26816 filter = ".ui-menu-item";
26817
26818 if ( this.isOpen ) {
26819 item = this.menuItems.eq( this.focusIndex ).parent( "li" );
26820 } else {
26821 item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
26822 filter += ":not(.ui-state-disabled)";
26823 }
26824
26825 if ( direction === "first" || direction === "last" ) {
26826 next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
26827 } else {
26828 next = item[ direction + "All" ]( filter ).eq( 0 );
26829 }
26830
26831 if ( next.length ) {
26832 this.menuInstance.focus( event, next );
26833 }
26834 },
26835
26836 _getSelectedItem: function() {
26837 return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
26838 },
26839
26840 _toggle: function( event ) {
26841 this[ this.isOpen ? "close" : "open" ]( event );
26842 },
26843
26844 _setSelection: function() {
26845 var selection;
26846
26847 if ( !this.range ) {
26848 return;
26849 }
26850
26851 selection = window.getSelection();
26852 selection.removeAllRanges();
26853 selection.addRange( this.range );
26854 },
26855
26856 _documentClick: {
26857 mousedown: function( event ) {
26858 if ( !this.isOpen ) {
26859 return;
26860 }
26861
26862 if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" +
26863 CSS.escape( this.ids.button ) ).length ) {
26864 this.close( event );
26865 }
26866 }
26867 },
26868
26869 _buttonEvents: {
26870
26871 // Prevent text selection from being reset when interacting with the selectmenu (#10144)
26872 mousedown: function() {
26873 var selection = window.getSelection();
26874 if ( selection.rangeCount ) {
26875 this.range = selection.getRangeAt( 0 );
26876 }
26877 },
26878
26879 click: function( event ) {
26880 this._setSelection();
26881 this._toggle( event );
26882 },
26883
26884 keydown: function( event ) {
26885 var preventDefault = true;
26886 switch ( event.keyCode ) {
26887 case $.ui.keyCode.TAB:
26888 case $.ui.keyCode.ESCAPE:
26889 this.close( event );
26890 preventDefault = false;
26891 break;
26892 case $.ui.keyCode.ENTER:
26893 if ( this.isOpen ) {
26894 this._selectFocusedItem( event );
26895 }
26896 break;
26897 case $.ui.keyCode.UP:
26898 if ( event.altKey ) {
26899 this._toggle( event );
26900 } else {
26901 this._move( "prev", event );
26902 }
26903 break;
26904 case $.ui.keyCode.DOWN:
26905 if ( event.altKey ) {
26906 this._toggle( event );
26907 } else {
26908 this._move( "next", event );
26909 }
26910 break;
26911 case $.ui.keyCode.SPACE:
26912 if ( this.isOpen ) {
26913 this._selectFocusedItem( event );
26914 } else {
26915 this._toggle( event );
26916 }
26917 break;
26918 case $.ui.keyCode.LEFT:
26919 this._move( "prev", event );
26920 break;
26921 case $.ui.keyCode.RIGHT:
26922 this._move( "next", event );
26923 break;
26924 case $.ui.keyCode.HOME:
26925 case $.ui.keyCode.PAGE_UP:
26926 this._move( "first", event );
26927 break;
26928 case $.ui.keyCode.END:
26929 case $.ui.keyCode.PAGE_DOWN:
26930 this._move( "last", event );
26931 break;
26932 default:
26933 this.menu.trigger( event );
26934 preventDefault = false;
26935 }
26936
26937 if ( preventDefault ) {
26938 event.preventDefault();
26939 }
26940 }
26941 },
26942
26943 _selectFocusedItem: function( event ) {
26944 var item = this.menuItems.eq( this.focusIndex ).parent( "li" );
26945 if ( !item.hasClass( "ui-state-disabled" ) ) {
26946 this._select( item.data( "ui-selectmenu-item" ), event );
26947 }
26948 },
26949
26950 _select: function( item, event ) {
26951 var oldIndex = this.element[ 0 ].selectedIndex;
26952
26953 // Change native select element
26954 this.element[ 0 ].selectedIndex = item.index;
26955 this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );
26956 this._setAria( item );
26957 this._trigger( "select", event, { item: item } );
26958
26959 if ( item.index !== oldIndex ) {
26960 this._trigger( "change", event, { item: item } );
26961 }
26962
26963 this.close( event );
26964 },
26965
26966 _setAria: function( item ) {
26967 var id = this.menuItems.eq( item.index ).attr( "id" );
26968
26969 this.button.attr( {
26970 "aria-labelledby": id,
26971 "aria-activedescendant": id
26972 } );
26973 this.menu.attr( "aria-activedescendant", id );
26974 },
26975
26976 _setOption: function( key, value ) {
26977 if ( key === "icons" ) {
26978 var icon = this.button.find( "span.ui-icon" );
26979 this._removeClass( icon, null, this.options.icons.button )
26980 ._addClass( icon, null, value.button );
26981 }
26982
26983 this._super( key, value );
26984
26985 if ( key === "appendTo" ) {
26986 this.menuWrap.appendTo( this._appendTo() );
26987 }
26988
26989 if ( key === "width" ) {
26990 this._resizeButton();
26991 }
26992 },
26993
26994 _setOptionDisabled: function( value ) {
26995 this._super( value );
26996
26997 this.menuInstance.option( "disabled", value );
26998 this.button.attr( "aria-disabled", value );
26999 this._toggleClass( this.button, null, "ui-state-disabled", value );
27000
27001 this.element.prop( "disabled", value );
27002 if ( value ) {
27003 this.button.attr( "tabindex", -1 );
27004 this.close();
27005 } else {
27006 this.button.attr( "tabindex", 0 );
27007 }
27008 },
27009
27010 _appendTo: function() {
27011 var element = this.options.appendTo;
27012
27013 if ( element ) {
27014 element = element.jquery || element.nodeType ?
27015 $( element ) :
27016 this.document.find( element ).eq( 0 );
27017 }
27018
27019 if ( !element || !element[ 0 ] ) {
27020 element = this.element.closest( ".ui-front, dialog" );
27021 }
27022
27023 if ( !element.length ) {
27024 element = this.document[ 0 ].body;
27025 }
27026
27027 return element;
27028 },
27029
27030 _toggleAttr: function() {
27031 this.button.attr( "aria-expanded", this.isOpen );
27032
27033 // We can't use two _toggleClass() calls here, because we need to make sure
27034 // we always remove classes first and add them second, otherwise if both classes have the
27035 // same theme class, it will be removed after we add it.
27036 this._removeClass( this.button, "ui-selectmenu-button-" +
27037 ( this.isOpen ? "closed" : "open" ) )
27038 ._addClass( this.button, "ui-selectmenu-button-" +
27039 ( this.isOpen ? "open" : "closed" ) )
27040 ._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen );
27041
27042 this.menu.attr( "aria-hidden", !this.isOpen );
27043 },
27044
27045 _resizeButton: function() {
27046 var width = this.options.width;
27047
27048 // For `width: false`, just remove inline style and stop
27049 if ( width === false ) {
27050 this.button.css( "width", "" );
27051 return;
27052 }
27053
27054 // For `width: null`, match the width of the original element
27055 if ( width === null ) {
27056 width = this.element.show().outerWidth();
27057 this.element.hide();
27058 }
27059
27060 this.button.outerWidth( width );
27061 },
27062
27063 _resizeMenu: function() {
27064 this.menu.outerWidth( Math.max(
27065 this.button.outerWidth(),
27066 this.menu.width( "" ).outerWidth()
27067 ) );
27068 },
27069
27070 _getCreateOptions: function() {
27071 var options = this._super();
27072
27073 options.disabled = this.element.prop( "disabled" );
27074
27075 return options;
27076 },
27077
27078 _parseOptions: function( options ) {
27079 var that = this,
27080 data = [];
27081 options.each( function( index, item ) {
27082 data.push( that._parseOption( $( item ), index ) );
27083 } );
27084 this.items = data;
27085 },
27086
27087 _parseOption: function( option, index ) {
27088 var optgroup = option.parent( "optgroup" );
27089
27090 return {
27091 element: option,
27092 index: index,
27093 value: option.val(),
27094 label: option.text(),
27095 hidden: optgroup.prop( "hidden" ) || option.prop( "hidden" ),
27096 optgroup: optgroup.attr( "label" ) || "",
27097 disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
27098 };
27099 },
27100
27101 _destroy: function() {
27102 this._unbindFormResetHandler();
27103 this.menuWrap.remove();
27104 this.button.remove();
27105 this.element.show();
27106 this.element.removeUniqueId();
27107 this.labels.attr( "for", this.ids.element );
27108 }
27109} ] );
27110
27111} );
27112
27113
27114
27115
27116
27117/*!
27118 * jQuery UI Slider 1.14.1
27119 * https://jqueryui.com
27120 *
27121 * Copyright OpenJS Foundation and other contributors
27122 * Released under the MIT license.
27123 * https://jquery.org/license
27124 */
27125
27126//>>label: Slider
27127//>>group: Widgets
27128//>>description: Displays a flexible slider with ranges and accessibility via keyboard.
27129//>>docs: https://api.jqueryui.com/slider/
27130//>>demos: https://jqueryui.com/slider/
27131//>>css.structure: ../../themes/base/core.css
27132//>>css.structure: ../../themes/base/slider.css
27133//>>css.theme: ../../themes/base/theme.css
27134
27135( function( factory ) {
27136 "use strict";
27137
27138 if ( typeof define === "function" && define.amd ) {
27139
27140 // AMD. Register as an anonymous module.
27141 define( [
27142 "jquery",
27143 "./mouse",
27144 "../keycode",
27145 "../version",
27146 "../widget"
27147 ], factory );
27148 } else {
27149
27150 // Browser globals
27151 factory( jQuery );
27152 }
27153} )( function( $ ) {
27154"use strict";
27155
27156return $.widget( "ui.slider", $.ui.mouse, {
27157 version: "1.14.1",
27158 widgetEventPrefix: "slide",
27159
27160 options: {
27161 animate: false,
27162 classes: {
27163 "ui-slider": "ui-corner-all",
27164 "ui-slider-handle": "ui-corner-all",
27165
27166 // Note: ui-widget-header isn't the most fittingly semantic framework class for this
27167 // element, but worked best visually with a variety of themes
27168 "ui-slider-range": "ui-corner-all ui-widget-header"
27169 },
27170 distance: 0,
27171 max: 100,
27172 min: 0,
27173 orientation: "horizontal",
27174 range: false,
27175 step: 1,
27176 value: 0,
27177 values: null,
27178
27179 // Callbacks
27180 change: null,
27181 slide: null,
27182 start: null,
27183 stop: null
27184 },
27185
27186 // Number of pages in a slider
27187 // (how many times can you page up/down to go through the whole range)
27188 numPages: 5,
27189
27190 _create: function() {
27191 this._keySliding = false;
27192 this._mouseSliding = false;
27193 this._animateOff = true;
27194 this._handleIndex = null;
27195 this._detectOrientation();
27196 this._mouseInit();
27197 this._calculateNewMax();
27198
27199 this._addClass( "ui-slider ui-slider-" + this.orientation,
27200 "ui-widget ui-widget-content" );
27201
27202 this._refresh();
27203
27204 this._animateOff = false;
27205 },
27206
27207 _refresh: function() {
27208 this._createRange();
27209 this._createHandles();
27210 this._setupEvents();
27211 this._refreshValue();
27212 },
27213
27214 _createHandles: function() {
27215 var i, handleCount,
27216 options = this.options,
27217 existingHandles = this.element.find( ".ui-slider-handle" ),
27218 handle = "<span tabindex='0'></span>",
27219 handles = [];
27220
27221 handleCount = ( options.values && options.values.length ) || 1;
27222
27223 if ( existingHandles.length > handleCount ) {
27224 existingHandles.slice( handleCount ).remove();
27225 existingHandles = existingHandles.slice( 0, handleCount );
27226 }
27227
27228 for ( i = existingHandles.length; i < handleCount; i++ ) {
27229 handles.push( handle );
27230 }
27231
27232 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
27233
27234 this._addClass( this.handles, "ui-slider-handle", "ui-state-default" );
27235
27236 this.handle = this.handles.eq( 0 );
27237
27238 this.handles.each( function( i ) {
27239 $( this )
27240 .data( "ui-slider-handle-index", i )
27241 .attr( "tabIndex", 0 );
27242 } );
27243 },
27244
27245 _createRange: function() {
27246 var options = this.options;
27247
27248 if ( options.range ) {
27249 if ( options.range === true ) {
27250 if ( !options.values ) {
27251 options.values = [ this._valueMin(), this._valueMin() ];
27252 } else if ( options.values.length && options.values.length !== 2 ) {
27253 options.values = [ options.values[ 0 ], options.values[ 0 ] ];
27254 } else if ( Array.isArray( options.values ) ) {
27255 options.values = options.values.slice( 0 );
27256 }
27257 }
27258
27259 if ( !this.range || !this.range.length ) {
27260 this.range = $( "<div>" )
27261 .appendTo( this.element );
27262
27263 this._addClass( this.range, "ui-slider-range" );
27264 } else {
27265 this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" );
27266
27267 // Handle range switching from true to min/max
27268 this.range.css( {
27269 "left": "",
27270 "bottom": ""
27271 } );
27272 }
27273 if ( options.range === "min" || options.range === "max" ) {
27274 this._addClass( this.range, "ui-slider-range-" + options.range );
27275 }
27276 } else {
27277 if ( this.range ) {
27278 this.range.remove();
27279 }
27280 this.range = null;
27281 }
27282 },
27283
27284 _setupEvents: function() {
27285 this._off( this.handles );
27286 this._on( this.handles, this._handleEvents );
27287 this._hoverable( this.handles );
27288 this._focusable( this.handles );
27289 },
27290
27291 _destroy: function() {
27292 this.handles.remove();
27293 if ( this.range ) {
27294 this.range.remove();
27295 }
27296
27297 this._mouseDestroy();
27298 },
27299
27300 _mouseCapture: function( event ) {
27301 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
27302 that = this,
27303 o = this.options;
27304
27305 if ( o.disabled ) {
27306 return false;
27307 }
27308
27309 this.elementSize = {
27310 width: this.element.outerWidth(),
27311 height: this.element.outerHeight()
27312 };
27313 this.elementOffset = this.element.offset();
27314
27315 position = { x: event.pageX, y: event.pageY };
27316 normValue = this._normValueFromMouse( position );
27317 distance = this._valueMax() - this._valueMin() + 1;
27318 this.handles.each( function( i ) {
27319 var thisDistance = Math.abs( normValue - that.values( i ) );
27320 if ( ( distance > thisDistance ) ||
27321 ( distance === thisDistance &&
27322 ( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {
27323 distance = thisDistance;
27324 closestHandle = $( this );
27325 index = i;
27326 }
27327 } );
27328
27329 allowed = this._start( event, index );
27330 if ( allowed === false ) {
27331 return false;
27332 }
27333 this._mouseSliding = true;
27334
27335 this._handleIndex = index;
27336
27337 this._addClass( closestHandle, null, "ui-state-active" );
27338 closestHandle.trigger( "focus" );
27339
27340 offset = closestHandle.offset();
27341 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
27342 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
27343 left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
27344 top: event.pageY - offset.top -
27345 ( closestHandle.height() / 2 ) -
27346 ( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) -
27347 ( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) +
27348 ( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 )
27349 };
27350
27351 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
27352 this._slide( event, index, normValue );
27353 }
27354 this._animateOff = true;
27355 return true;
27356 },
27357
27358 _mouseStart: function() {
27359 return true;
27360 },
27361
27362 _mouseDrag: function( event ) {
27363 var position = { x: event.pageX, y: event.pageY },
27364 normValue = this._normValueFromMouse( position );
27365
27366 this._slide( event, this._handleIndex, normValue );
27367
27368 return false;
27369 },
27370
27371 _mouseStop: function( event ) {
27372 this._removeClass( this.handles, null, "ui-state-active" );
27373 this._mouseSliding = false;
27374
27375 this._stop( event, this._handleIndex );
27376 this._change( event, this._handleIndex );
27377
27378 this._handleIndex = null;
27379 this._clickOffset = null;
27380 this._animateOff = false;
27381
27382 return false;
27383 },
27384
27385 _detectOrientation: function() {
27386 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
27387 },
27388
27389 _normValueFromMouse: function( position ) {
27390 var pixelTotal,
27391 pixelMouse,
27392 percentMouse,
27393 valueTotal,
27394 valueMouse;
27395
27396 if ( this.orientation === "horizontal" ) {
27397 pixelTotal = this.elementSize.width;
27398 pixelMouse = position.x - this.elementOffset.left -
27399 ( this._clickOffset ? this._clickOffset.left : 0 );
27400 } else {
27401 pixelTotal = this.elementSize.height;
27402 pixelMouse = position.y - this.elementOffset.top -
27403 ( this._clickOffset ? this._clickOffset.top : 0 );
27404 }
27405
27406 percentMouse = ( pixelMouse / pixelTotal );
27407 if ( percentMouse > 1 ) {
27408 percentMouse = 1;
27409 }
27410 if ( percentMouse < 0 ) {
27411 percentMouse = 0;
27412 }
27413 if ( this.orientation === "vertical" ) {
27414 percentMouse = 1 - percentMouse;
27415 }
27416
27417 valueTotal = this._valueMax() - this._valueMin();
27418 valueMouse = this._valueMin() + percentMouse * valueTotal;
27419
27420 return this._trimAlignValue( valueMouse );
27421 },
27422
27423 _uiHash: function( index, value, values ) {
27424 var uiHash = {
27425 handle: this.handles[ index ],
27426 handleIndex: index,
27427 value: value !== undefined ? value : this.value()
27428 };
27429
27430 if ( this._hasMultipleValues() ) {
27431 uiHash.value = value !== undefined ? value : this.values( index );
27432 uiHash.values = values || this.values();
27433 }
27434
27435 return uiHash;
27436 },
27437
27438 _hasMultipleValues: function() {
27439 return this.options.values && this.options.values.length;
27440 },
27441
27442 _start: function( event, index ) {
27443 return this._trigger( "start", event, this._uiHash( index ) );
27444 },
27445
27446 _slide: function( event, index, newVal ) {
27447 var allowed, otherVal,
27448 currentValue = this.value(),
27449 newValues = this.values();
27450
27451 if ( this._hasMultipleValues() ) {
27452 otherVal = this.values( index ? 0 : 1 );
27453 currentValue = this.values( index );
27454
27455 if ( this.options.values.length === 2 && this.options.range === true ) {
27456 newVal = index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );
27457 }
27458
27459 newValues[ index ] = newVal;
27460 }
27461
27462 if ( newVal === currentValue ) {
27463 return;
27464 }
27465
27466 allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) );
27467
27468 // A slide can be canceled by returning false from the slide callback
27469 if ( allowed === false ) {
27470 return;
27471 }
27472
27473 if ( this._hasMultipleValues() ) {
27474 this.values( index, newVal );
27475 } else {
27476 this.value( newVal );
27477 }
27478 },
27479
27480 _stop: function( event, index ) {
27481 this._trigger( "stop", event, this._uiHash( index ) );
27482 },
27483
27484 _change: function( event, index ) {
27485 if ( !this._keySliding && !this._mouseSliding ) {
27486
27487 //store the last changed value index for reference when handles overlap
27488 this._lastChangedValue = index;
27489 this._trigger( "change", event, this._uiHash( index ) );
27490 }
27491 },
27492
27493 value: function( newValue ) {
27494 if ( arguments.length ) {
27495 this.options.value = this._trimAlignValue( newValue );
27496 this._refreshValue();
27497 this._change( null, 0 );
27498 return;
27499 }
27500
27501 return this._value();
27502 },
27503
27504 values: function( index, newValue ) {
27505 var vals,
27506 newValues,
27507 i;
27508
27509 if ( arguments.length > 1 ) {
27510 this.options.values[ index ] = this._trimAlignValue( newValue );
27511 this._refreshValue();
27512 this._change( null, index );
27513 return;
27514 }
27515
27516 if ( arguments.length ) {
27517 if ( Array.isArray( arguments[ 0 ] ) ) {
27518 vals = this.options.values;
27519 newValues = arguments[ 0 ];
27520 for ( i = 0; i < vals.length; i += 1 ) {
27521 vals[ i ] = this._trimAlignValue( newValues[ i ] );
27522 this._change( null, i );
27523 }
27524 this._refreshValue();
27525 } else {
27526 if ( this._hasMultipleValues() ) {
27527 return this._values( index );
27528 } else {
27529 return this.value();
27530 }
27531 }
27532 } else {
27533 return this._values();
27534 }
27535 },
27536
27537 _setOption: function( key, value ) {
27538 var i,
27539 valsLength = 0;
27540
27541 if ( key === "range" && this.options.range === true ) {
27542 if ( value === "min" ) {
27543 this.options.value = this._values( 0 );
27544 this.options.values = null;
27545 } else if ( value === "max" ) {
27546 this.options.value = this._values( this.options.values.length - 1 );
27547 this.options.values = null;
27548 }
27549 }
27550
27551 if ( Array.isArray( this.options.values ) ) {
27552 valsLength = this.options.values.length;
27553 }
27554
27555 this._super( key, value );
27556
27557 switch ( key ) {
27558 case "orientation":
27559 this._detectOrientation();
27560 this._removeClass( "ui-slider-horizontal ui-slider-vertical" )
27561 ._addClass( "ui-slider-" + this.orientation );
27562 this._refreshValue();
27563 if ( this.options.range ) {
27564 this._refreshRange( value );
27565 }
27566
27567 // Reset positioning from previous orientation
27568 this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
27569 break;
27570 case "value":
27571 this._animateOff = true;
27572 this._refreshValue();
27573 this._change( null, 0 );
27574 this._animateOff = false;
27575 break;
27576 case "values":
27577 this._animateOff = true;
27578 this._refreshValue();
27579
27580 // Start from the last handle to prevent unreachable handles (#9046)
27581 for ( i = valsLength - 1; i >= 0; i-- ) {
27582 this._change( null, i );
27583 }
27584 this._animateOff = false;
27585 break;
27586 case "step":
27587 case "min":
27588 case "max":
27589 this._animateOff = true;
27590 this._calculateNewMax();
27591 this._refreshValue();
27592 this._animateOff = false;
27593 break;
27594 case "range":
27595 this._animateOff = true;
27596 this._refresh();
27597 this._animateOff = false;
27598 break;
27599 }
27600 },
27601
27602 _setOptionDisabled: function( value ) {
27603 this._super( value );
27604
27605 this._toggleClass( null, "ui-state-disabled", !!value );
27606 },
27607
27608 //internal value getter
27609 // _value() returns value trimmed by min and max, aligned by step
27610 _value: function() {
27611 var val = this.options.value;
27612 val = this._trimAlignValue( val );
27613
27614 return val;
27615 },
27616
27617 //internal values getter
27618 // _values() returns array of values trimmed by min and max, aligned by step
27619 // _values( index ) returns single value trimmed by min and max, aligned by step
27620 _values: function( index ) {
27621 var val,
27622 vals,
27623 i;
27624
27625 if ( arguments.length ) {
27626 val = this.options.values[ index ];
27627 val = this._trimAlignValue( val );
27628
27629 return val;
27630 } else if ( this._hasMultipleValues() ) {
27631
27632 // .slice() creates a copy of the array
27633 // this copy gets trimmed by min and max and then returned
27634 vals = this.options.values.slice();
27635 for ( i = 0; i < vals.length; i += 1 ) {
27636 vals[ i ] = this._trimAlignValue( vals[ i ] );
27637 }
27638
27639 return vals;
27640 } else {
27641 return [];
27642 }
27643 },
27644
27645 // Returns the step-aligned value that val is closest to, between (inclusive) min and max
27646 _trimAlignValue: function( val ) {
27647 if ( val <= this._valueMin() ) {
27648 return this._valueMin();
27649 }
27650 if ( val >= this._valueMax() ) {
27651 return this._valueMax();
27652 }
27653 var step = ( this.options.step > 0 ) ? this.options.step : 1,
27654 valModStep = ( val - this._valueMin() ) % step,
27655 alignValue = val - valModStep;
27656
27657 if ( Math.abs( valModStep ) * 2 >= step ) {
27658 alignValue += ( valModStep > 0 ) ? step : ( -step );
27659 }
27660
27661 // Since JavaScript has problems with large floats, round
27662 // the final value to 5 digits after the decimal point (see #4124)
27663 return parseFloat( alignValue.toFixed( 5 ) );
27664 },
27665
27666 _calculateNewMax: function() {
27667 var max = this.options.max,
27668 min = this._valueMin(),
27669 step = this.options.step,
27670 aboveMin = Math.round( ( max - min ) / step ) * step;
27671 max = aboveMin + min;
27672 if ( max > this.options.max ) {
27673
27674 //If max is not divisible by step, rounding off may increase its value
27675 max -= step;
27676 }
27677 this.max = parseFloat( max.toFixed( this._precision() ) );
27678 },
27679
27680 _precision: function() {
27681 var precision = this._precisionOf( this.options.step );
27682 if ( this.options.min !== null ) {
27683 precision = Math.max( precision, this._precisionOf( this.options.min ) );
27684 }
27685 return precision;
27686 },
27687
27688 _precisionOf: function( num ) {
27689 var str = num.toString(),
27690 decimal = str.indexOf( "." );
27691 return decimal === -1 ? 0 : str.length - decimal - 1;
27692 },
27693
27694 _valueMin: function() {
27695 return this.options.min;
27696 },
27697
27698 _valueMax: function() {
27699 return this.max;
27700 },
27701
27702 _refreshRange: function( orientation ) {
27703 if ( orientation === "vertical" ) {
27704 this.range.css( { "width": "", "left": "" } );
27705 }
27706 if ( orientation === "horizontal" ) {
27707 this.range.css( { "height": "", "bottom": "" } );
27708 }
27709 },
27710
27711 _refreshValue: function() {
27712 var lastValPercent, valPercent, value, valueMin, valueMax,
27713 oRange = this.options.range,
27714 o = this.options,
27715 that = this,
27716 animate = ( !this._animateOff ) ? o.animate : false,
27717 _set = {};
27718
27719 if ( this._hasMultipleValues() ) {
27720 this.handles.each( function( i ) {
27721 valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -
27722 that._valueMin() ) * 100;
27723 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
27724 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
27725 if ( that.options.range === true ) {
27726 if ( that.orientation === "horizontal" ) {
27727 if ( i === 0 ) {
27728 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
27729 left: valPercent + "%"
27730 }, o.animate );
27731 }
27732 if ( i === 1 ) {
27733 that.range[ animate ? "animate" : "css" ]( {
27734 width: ( valPercent - lastValPercent ) + "%"
27735 }, {
27736 queue: false,
27737 duration: o.animate
27738 } );
27739 }
27740 } else {
27741 if ( i === 0 ) {
27742 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
27743 bottom: ( valPercent ) + "%"
27744 }, o.animate );
27745 }
27746 if ( i === 1 ) {
27747 that.range[ animate ? "animate" : "css" ]( {
27748 height: ( valPercent - lastValPercent ) + "%"
27749 }, {
27750 queue: false,
27751 duration: o.animate
27752 } );
27753 }
27754 }
27755 }
27756 lastValPercent = valPercent;
27757 } );
27758 } else {
27759 value = this.value();
27760 valueMin = this._valueMin();
27761 valueMax = this._valueMax();
27762 valPercent = ( valueMax !== valueMin ) ?
27763 ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
27764 0;
27765 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
27766 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
27767
27768 if ( oRange === "min" && this.orientation === "horizontal" ) {
27769 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
27770 width: valPercent + "%"
27771 }, o.animate );
27772 }
27773 if ( oRange === "max" && this.orientation === "horizontal" ) {
27774 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
27775 width: ( 100 - valPercent ) + "%"
27776 }, o.animate );
27777 }
27778 if ( oRange === "min" && this.orientation === "vertical" ) {
27779 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
27780 height: valPercent + "%"
27781 }, o.animate );
27782 }
27783 if ( oRange === "max" && this.orientation === "vertical" ) {
27784 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
27785 height: ( 100 - valPercent ) + "%"
27786 }, o.animate );
27787 }
27788 }
27789 },
27790
27791 _handleEvents: {
27792 keydown: function( event ) {
27793 var allowed, curVal, newVal, step,
27794 index = $( event.target ).data( "ui-slider-handle-index" );
27795
27796 switch ( event.keyCode ) {
27797 case $.ui.keyCode.HOME:
27798 case $.ui.keyCode.END:
27799 case $.ui.keyCode.PAGE_UP:
27800 case $.ui.keyCode.PAGE_DOWN:
27801 case $.ui.keyCode.UP:
27802 case $.ui.keyCode.RIGHT:
27803 case $.ui.keyCode.DOWN:
27804 case $.ui.keyCode.LEFT:
27805 event.preventDefault();
27806 if ( !this._keySliding ) {
27807 this._keySliding = true;
27808 this._addClass( $( event.target ), null, "ui-state-active" );
27809 allowed = this._start( event, index );
27810 if ( allowed === false ) {
27811 return;
27812 }
27813 }
27814 break;
27815 }
27816
27817 step = this.options.step;
27818 if ( this._hasMultipleValues() ) {
27819 curVal = newVal = this.values( index );
27820 } else {
27821 curVal = newVal = this.value();
27822 }
27823
27824 switch ( event.keyCode ) {
27825 case $.ui.keyCode.HOME:
27826 newVal = this._valueMin();
27827 break;
27828 case $.ui.keyCode.END:
27829 newVal = this._valueMax();
27830 break;
27831 case $.ui.keyCode.PAGE_UP:
27832 newVal = this._trimAlignValue(
27833 curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
27834 );
27835 break;
27836 case $.ui.keyCode.PAGE_DOWN:
27837 newVal = this._trimAlignValue(
27838 curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );
27839 break;
27840 case $.ui.keyCode.UP:
27841 case $.ui.keyCode.RIGHT:
27842 if ( curVal === this._valueMax() ) {
27843 return;
27844 }
27845 newVal = this._trimAlignValue( curVal + step );
27846 break;
27847 case $.ui.keyCode.DOWN:
27848 case $.ui.keyCode.LEFT:
27849 if ( curVal === this._valueMin() ) {
27850 return;
27851 }
27852 newVal = this._trimAlignValue( curVal - step );
27853 break;
27854 }
27855
27856 this._slide( event, index, newVal );
27857 },
27858 keyup: function( event ) {
27859 var index = $( event.target ).data( "ui-slider-handle-index" );
27860
27861 if ( this._keySliding ) {
27862 this._keySliding = false;
27863 this._stop( event, index );
27864 this._change( event, index );
27865 this._removeClass( $( event.target ), null, "ui-state-active" );
27866 }
27867 }
27868 }
27869} );
27870
27871} );
27872
27873
27874
27875
27876
27877
27878/*!
27879 * jQuery UI Sortable 1.14.1
27880 * https://jqueryui.com
27881 *
27882 * Copyright OpenJS Foundation and other contributors
27883 * Released under the MIT license.
27884 * https://jquery.org/license
27885 */
27886
27887//>>label: Sortable
27888//>>group: Interactions
27889//>>description: Enables items in a list to be sorted using the mouse.
27890//>>docs: https://api.jqueryui.com/sortable/
27891//>>demos: https://jqueryui.com/sortable/
27892//>>css.structure: ../../themes/base/sortable.css
27893
27894( function( factory ) {
27895 "use strict";
27896
27897 if ( typeof define === "function" && define.amd ) {
27898
27899 // AMD. Register as an anonymous module.
27900 define( [
27901 "jquery",
27902 "./mouse",
27903 "../data",
27904 "../scroll-parent",
27905 "../version",
27906 "../widget"
27907 ], factory );
27908 } else {
27909
27910 // Browser globals
27911 factory( jQuery );
27912 }
27913} )( function( $ ) {
27914"use strict";
27915
27916return $.widget( "ui.sortable", $.ui.mouse, {
27917 version: "1.14.1",
27918 widgetEventPrefix: "sort",
27919 ready: false,
27920 options: {
27921 appendTo: "parent",
27922 axis: false,
27923 connectWith: false,
27924 containment: false,
27925 cursor: "auto",
27926 cursorAt: false,
27927 dropOnEmpty: true,
27928 forcePlaceholderSize: false,
27929 forceHelperSize: false,
27930 grid: false,
27931 handle: false,
27932 helper: "original",
27933 items: "> *",
27934 opacity: false,
27935 placeholder: false,
27936 revert: false,
27937 scroll: true,
27938 scrollSensitivity: 20,
27939 scrollSpeed: 20,
27940 scope: "default",
27941 tolerance: "intersect",
27942 zIndex: 1000,
27943
27944 // Callbacks
27945 activate: null,
27946 beforeStop: null,
27947 change: null,
27948 deactivate: null,
27949 out: null,
27950 over: null,
27951 receive: null,
27952 remove: null,
27953 sort: null,
27954 start: null,
27955 stop: null,
27956 update: null
27957 },
27958
27959 _isOverAxis: function( x, reference, size ) {
27960 return ( x >= reference ) && ( x < ( reference + size ) );
27961 },
27962
27963 _isFloating: function( item ) {
27964 return ( /left|right/ ).test( item.css( "float" ) ) ||
27965 ( /inline|table-cell/ ).test( item.css( "display" ) );
27966 },
27967
27968 _create: function() {
27969 this.containerCache = {};
27970 this._addClass( "ui-sortable" );
27971
27972 //Get the items
27973 this.refresh();
27974
27975 //Let's determine the parent's offset
27976 this.offset = this.element.offset();
27977
27978 //Initialize mouse events for interaction
27979 this._mouseInit();
27980
27981 this._setHandleClassName();
27982
27983 //We're ready to go
27984 this.ready = true;
27985
27986 },
27987
27988 _setOption: function( key, value ) {
27989 this._super( key, value );
27990
27991 if ( key === "handle" ) {
27992 this._setHandleClassName();
27993 }
27994 },
27995
27996 _setHandleClassName: function() {
27997 var that = this;
27998 this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" );
27999 $.each( this.items, function() {
28000 that._addClass(
28001 this.instance.options.handle ?
28002 this.item.find( this.instance.options.handle ) :
28003 this.item,
28004 "ui-sortable-handle"
28005 );
28006 } );
28007 },
28008
28009 _destroy: function() {
28010 this._mouseDestroy();
28011
28012 for ( var i = this.items.length - 1; i >= 0; i-- ) {
28013 this.items[ i ].item.removeData( this.widgetName + "-item" );
28014 }
28015
28016 return this;
28017 },
28018
28019 _mouseCapture: function( event, overrideHandle ) {
28020 var currentItem = null,
28021 validHandle = false,
28022 that = this;
28023
28024 if ( this.reverting ) {
28025 return false;
28026 }
28027
28028 if ( this.options.disabled || this.options.type === "static" ) {
28029 return false;
28030 }
28031
28032 //We have to refresh the items data once first
28033 this._refreshItems( event );
28034
28035 //Find out if the clicked node (or one of its parents) is a actual item in this.items
28036 $( event.target ).parents().each( function() {
28037 if ( $.data( this, that.widgetName + "-item" ) === that ) {
28038 currentItem = $( this );
28039 return false;
28040 }
28041 } );
28042 if ( $.data( event.target, that.widgetName + "-item" ) === that ) {
28043 currentItem = $( event.target );
28044 }
28045
28046 if ( !currentItem ) {
28047 return false;
28048 }
28049 if ( this.options.handle && !overrideHandle ) {
28050 $( this.options.handle, currentItem ).find( "*" ).addBack().each( function() {
28051 if ( this === event.target ) {
28052 validHandle = true;
28053 }
28054 } );
28055 if ( !validHandle ) {
28056 return false;
28057 }
28058 }
28059
28060 this.currentItem = currentItem;
28061 this._removeCurrentsFromItems();
28062 return true;
28063
28064 },
28065
28066 _mouseStart: function( event, overrideHandle, noActivation ) {
28067
28068 var i, body,
28069 o = this.options;
28070
28071 this.currentContainer = this;
28072
28073 //We only need to call refreshPositions, because the refreshItems call has been moved to
28074 // mouseCapture
28075 this.refreshPositions();
28076
28077 //Prepare the dragged items parent
28078 this.appendTo = $( o.appendTo !== "parent" ?
28079 o.appendTo :
28080 this.currentItem.parent() );
28081
28082 //Create and append the visible helper
28083 this.helper = this._createHelper( event );
28084
28085 //Cache the helper size
28086 this._cacheHelperProportions();
28087
28088 /*
28089 * - Position generation -
28090 * This block generates everything position related - it's the core of draggables.
28091 */
28092
28093 //Cache the margins of the original element
28094 this._cacheMargins();
28095
28096 //The element's absolute position on the page minus margins
28097 this.offset = this.currentItem.offset();
28098 this.offset = {
28099 top: this.offset.top - this.margins.top,
28100 left: this.offset.left - this.margins.left
28101 };
28102
28103 $.extend( this.offset, {
28104 click: { //Where the click happened, relative to the element
28105 left: event.pageX - this.offset.left,
28106 top: event.pageY - this.offset.top
28107 },
28108
28109 // This is a relative to absolute position minus the actual position calculation -
28110 // only used for relative positioned helper
28111 relative: this._getRelativeOffset()
28112 } );
28113
28114 // After we get the helper offset, but before we get the parent offset we can
28115 // change the helper's position to absolute
28116 // TODO: Still need to figure out a way to make relative sorting possible
28117 this.helper.css( "position", "absolute" );
28118 this.cssPosition = this.helper.css( "position" );
28119
28120 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
28121 if ( o.cursorAt ) {
28122 this._adjustOffsetFromHelper( o.cursorAt );
28123 }
28124
28125 //Cache the former DOM position
28126 this.domPosition = {
28127 prev: this.currentItem.prev()[ 0 ],
28128 parent: this.currentItem.parent()[ 0 ]
28129 };
28130
28131 // If the helper is not the original, hide the original so it's not playing any role during
28132 // the drag, won't cause anything bad this way
28133 if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
28134 this.currentItem.hide();
28135 }
28136
28137 //Create the placeholder
28138 this._createPlaceholder();
28139
28140 //Get the next scrolling parent
28141 this.scrollParent = this.placeholder.scrollParent();
28142
28143 $.extend( this.offset, {
28144 parent: this._getParentOffset()
28145 } );
28146
28147 //Set a containment if given in the options
28148 if ( o.containment ) {
28149 this._setContainment();
28150 }
28151
28152 if ( o.cursor && o.cursor !== "auto" ) { // cursor option
28153 body = this.document.find( "body" );
28154
28155 this._storedStylesheet =
28156 $( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body );
28157 }
28158
28159 // We need to make sure to grab the zIndex before setting the
28160 // opacity, because setting the opacity to anything lower than 1
28161 // causes the zIndex to change from "auto" to 0.
28162 if ( o.zIndex ) { // zIndex option
28163 if ( this.helper.css( "zIndex" ) ) {
28164 this._storedZIndex = this.helper.css( "zIndex" );
28165 }
28166 this.helper.css( "zIndex", o.zIndex );
28167 }
28168
28169 if ( o.opacity ) { // opacity option
28170 if ( this.helper.css( "opacity" ) ) {
28171 this._storedOpacity = this.helper.css( "opacity" );
28172 }
28173 this.helper.css( "opacity", o.opacity );
28174 }
28175
28176 //Prepare scrolling
28177 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
28178 this.scrollParent[ 0 ].tagName !== "HTML" ) {
28179 this.overflowOffset = this.scrollParent.offset();
28180 }
28181
28182 //Call callbacks
28183 this._trigger( "start", event, this._uiHash() );
28184
28185 //Recache the helper size
28186 if ( !this._preserveHelperProportions ) {
28187 this._cacheHelperProportions();
28188 }
28189
28190 //Post "activate" events to possible containers
28191 if ( !noActivation ) {
28192 for ( i = this.containers.length - 1; i >= 0; i-- ) {
28193 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
28194 }
28195 }
28196
28197 //Prepare possible droppables
28198 if ( $.ui.ddmanager ) {
28199 $.ui.ddmanager.current = this;
28200 }
28201
28202 if ( $.ui.ddmanager && !o.dropBehaviour ) {
28203 $.ui.ddmanager.prepareOffsets( this, event );
28204 }
28205
28206 this.dragging = true;
28207
28208 this._addClass( this.helper, "ui-sortable-helper" );
28209
28210 //Move the helper, if needed
28211 if ( !this.helper.parent().is( this.appendTo ) ) {
28212 this.helper.detach().appendTo( this.appendTo );
28213
28214 //Update position
28215 this.offset.parent = this._getParentOffset();
28216 }
28217
28218 //Generate the original position
28219 this.position = this.originalPosition = this._generatePosition( event );
28220 this.originalPageX = event.pageX;
28221 this.originalPageY = event.pageY;
28222 this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" );
28223
28224 this._mouseDrag( event );
28225
28226 return true;
28227
28228 },
28229
28230 _scroll: function( event ) {
28231 var o = this.options,
28232 scrolled = false;
28233
28234 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
28235 this.scrollParent[ 0 ].tagName !== "HTML" ) {
28236
28237 if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -
28238 event.pageY < o.scrollSensitivity ) {
28239 this.scrollParent[ 0 ].scrollTop =
28240 scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
28241 } else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {
28242 this.scrollParent[ 0 ].scrollTop =
28243 scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
28244 }
28245
28246 if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -
28247 event.pageX < o.scrollSensitivity ) {
28248 this.scrollParent[ 0 ].scrollLeft = scrolled =
28249 this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
28250 } else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {
28251 this.scrollParent[ 0 ].scrollLeft = scrolled =
28252 this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
28253 }
28254
28255 } else {
28256
28257 if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {
28258 scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );
28259 } else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <
28260 o.scrollSensitivity ) {
28261 scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );
28262 }
28263
28264 if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {
28265 scrolled = this.document.scrollLeft(
28266 this.document.scrollLeft() - o.scrollSpeed
28267 );
28268 } else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <
28269 o.scrollSensitivity ) {
28270 scrolled = this.document.scrollLeft(
28271 this.document.scrollLeft() + o.scrollSpeed
28272 );
28273 }
28274
28275 }
28276
28277 return scrolled;
28278 },
28279
28280 _mouseDrag: function( event ) {
28281 var i, item, itemElement, intersection,
28282 o = this.options;
28283
28284 //Compute the helpers position
28285 this.position = this._generatePosition( event );
28286 this.positionAbs = this._convertPositionTo( "absolute" );
28287
28288 //Set the helper position
28289 if ( !this.options.axis || this.options.axis !== "y" ) {
28290 this.helper[ 0 ].style.left = this.position.left + "px";
28291 }
28292 if ( !this.options.axis || this.options.axis !== "x" ) {
28293 this.helper[ 0 ].style.top = this.position.top + "px";
28294 }
28295
28296 //Do scrolling
28297 if ( o.scroll ) {
28298 if ( this._scroll( event ) !== false ) {
28299
28300 //Update item positions used in position checks
28301 this._refreshItemPositions( true );
28302
28303 if ( $.ui.ddmanager && !o.dropBehaviour ) {
28304 $.ui.ddmanager.prepareOffsets( this, event );
28305 }
28306 }
28307 }
28308
28309 this.dragDirection = {
28310 vertical: this._getDragVerticalDirection(),
28311 horizontal: this._getDragHorizontalDirection()
28312 };
28313
28314 //Rearrange
28315 for ( i = this.items.length - 1; i >= 0; i-- ) {
28316
28317 //Cache variables and intersection, continue if no intersection
28318 item = this.items[ i ];
28319 itemElement = item.item[ 0 ];
28320 intersection = this._intersectsWithPointer( item );
28321 if ( !intersection ) {
28322 continue;
28323 }
28324
28325 // Only put the placeholder inside the current Container, skip all
28326 // items from other containers. This works because when moving
28327 // an item from one container to another the
28328 // currentContainer is switched before the placeholder is moved.
28329 //
28330 // Without this, moving items in "sub-sortables" can cause
28331 // the placeholder to jitter between the outer and inner container.
28332 if ( item.instance !== this.currentContainer ) {
28333 continue;
28334 }
28335
28336 // Cannot intersect with itself
28337 // no useless actions that have been done before
28338 // no action if the item moved is the parent of the item checked
28339 if ( itemElement !== this.currentItem[ 0 ] &&
28340 this.placeholder[ intersection === 1 ?
28341 "next" : "prev" ]()[ 0 ] !== itemElement &&
28342 !$.contains( this.placeholder[ 0 ], itemElement ) &&
28343 ( this.options.type === "semi-dynamic" ?
28344 !$.contains( this.element[ 0 ], itemElement ) :
28345 true
28346 )
28347 ) {
28348
28349 this.direction = intersection === 1 ? "down" : "up";
28350
28351 if ( this.options.tolerance === "pointer" ||
28352 this._intersectsWithSides( item ) ) {
28353 this._rearrange( event, item );
28354 } else {
28355 break;
28356 }
28357
28358 this._trigger( "change", event, this._uiHash() );
28359 break;
28360 }
28361 }
28362
28363 //Post events to containers
28364 this._contactContainers( event );
28365
28366 //Interconnect with droppables
28367 if ( $.ui.ddmanager ) {
28368 $.ui.ddmanager.drag( this, event );
28369 }
28370
28371 //Call callbacks
28372 this._trigger( "sort", event, this._uiHash() );
28373
28374 this.lastPositionAbs = this.positionAbs;
28375 return false;
28376
28377 },
28378
28379 _mouseStop: function( event, noPropagation ) {
28380
28381 if ( !event ) {
28382 return;
28383 }
28384
28385 //If we are using droppables, inform the manager about the drop
28386 if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
28387 $.ui.ddmanager.drop( this, event );
28388 }
28389
28390 if ( this.options.revert ) {
28391 var that = this,
28392 cur = this.placeholder.offset(),
28393 axis = this.options.axis,
28394 animation = {};
28395
28396 if ( !axis || axis === "x" ) {
28397 animation.left = cur.left - this.offset.parent.left - this.margins.left +
28398 ( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
28399 0 :
28400 this.offsetParent[ 0 ].scrollLeft
28401 );
28402 }
28403 if ( !axis || axis === "y" ) {
28404 animation.top = cur.top - this.offset.parent.top - this.margins.top +
28405 ( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
28406 0 :
28407 this.offsetParent[ 0 ].scrollTop
28408 );
28409 }
28410 this.reverting = true;
28411 $( this.helper ).animate(
28412 animation,
28413 parseInt( this.options.revert, 10 ) || 500,
28414 function() {
28415 that._clear( event );
28416 }
28417 );
28418 } else {
28419 this._clear( event, noPropagation );
28420 }
28421
28422 return false;
28423
28424 },
28425
28426 cancel: function() {
28427
28428 if ( this.dragging ) {
28429
28430 this._mouseUp( new $.Event( "mouseup", { target: null } ) );
28431
28432 if ( this.options.helper === "original" ) {
28433 this.currentItem.css( this._storedCSS );
28434 this._removeClass( this.currentItem, "ui-sortable-helper" );
28435 } else {
28436 this.currentItem.show();
28437 }
28438
28439 //Post deactivating events to containers
28440 for ( var i = this.containers.length - 1; i >= 0; i-- ) {
28441 this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) );
28442 if ( this.containers[ i ].containerCache.over ) {
28443 this.containers[ i ]._trigger( "out", null, this._uiHash( this ) );
28444 this.containers[ i ].containerCache.over = 0;
28445 }
28446 }
28447
28448 }
28449
28450 if ( this.placeholder ) {
28451
28452 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
28453 // it unbinds ALL events from the original node!
28454 if ( this.placeholder[ 0 ].parentNode ) {
28455 this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
28456 }
28457 if ( this.options.helper !== "original" && this.helper &&
28458 this.helper[ 0 ].parentNode ) {
28459 this.helper.remove();
28460 }
28461
28462 $.extend( this, {
28463 helper: null,
28464 dragging: false,
28465 reverting: false,
28466 _noFinalSort: null
28467 } );
28468
28469 if ( this.domPosition.prev ) {
28470 $( this.domPosition.prev ).after( this.currentItem );
28471 } else {
28472 $( this.domPosition.parent ).prepend( this.currentItem );
28473 }
28474 }
28475
28476 return this;
28477
28478 },
28479
28480 serialize: function( o ) {
28481
28482 var items = this._getItemsAsjQuery( o && o.connected ),
28483 str = [];
28484 o = o || {};
28485
28486 $( items ).each( function() {
28487 var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" )
28488 .match( o.expression || ( /(.+)[\-=_](.+)/ ) );
28489 if ( res ) {
28490 str.push(
28491 ( o.key || res[ 1 ] + "[]" ) +
28492 "=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );
28493 }
28494 } );
28495
28496 if ( !str.length && o.key ) {
28497 str.push( o.key + "=" );
28498 }
28499
28500 return str.join( "&" );
28501
28502 },
28503
28504 toArray: function( o ) {
28505
28506 var items = this._getItemsAsjQuery( o && o.connected ),
28507 ret = [];
28508
28509 o = o || {};
28510
28511 items.each( function() {
28512 ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" );
28513 } );
28514 return ret;
28515
28516 },
28517
28518 /* Be careful with the following core functions */
28519 _intersectsWith: function( item ) {
28520
28521 var x1 = this.positionAbs.left,
28522 x2 = x1 + this.helperProportions.width,
28523 y1 = this.positionAbs.top,
28524 y2 = y1 + this.helperProportions.height,
28525 l = item.left,
28526 r = l + item.width,
28527 t = item.top,
28528 b = t + item.height,
28529 dyClick = this.offset.click.top,
28530 dxClick = this.offset.click.left,
28531 isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
28532 ( y1 + dyClick ) < b ),
28533 isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
28534 ( x1 + dxClick ) < r ),
28535 isOverElement = isOverElementHeight && isOverElementWidth;
28536
28537 if ( this.options.tolerance === "pointer" ||
28538 this.options.forcePointerForContainers ||
28539 ( this.options.tolerance !== "pointer" &&
28540 this.helperProportions[ this.floating ? "width" : "height" ] >
28541 item[ this.floating ? "width" : "height" ] )
28542 ) {
28543 return isOverElement;
28544 } else {
28545
28546 return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
28547 x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
28548 t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
28549 y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
28550
28551 }
28552 },
28553
28554 _intersectsWithPointer: function( item ) {
28555 var verticalDirection, horizontalDirection,
28556 isOverElementHeight = ( this.options.axis === "x" ) ||
28557 this._isOverAxis(
28558 this.positionAbs.top + this.offset.click.top, item.top, item.height ),
28559 isOverElementWidth = ( this.options.axis === "y" ) ||
28560 this._isOverAxis(
28561 this.positionAbs.left + this.offset.click.left, item.left, item.width ),
28562 isOverElement = isOverElementHeight && isOverElementWidth;
28563
28564 if ( !isOverElement ) {
28565 return false;
28566 }
28567
28568 verticalDirection = this.dragDirection.vertical;
28569 horizontalDirection = this.dragDirection.horizontal;
28570
28571 return this.floating ?
28572 ( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) :
28573 ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
28574
28575 },
28576
28577 _intersectsWithSides: function( item ) {
28578
28579 var isOverBottomHalf = this._isOverAxis( this.positionAbs.top +
28580 this.offset.click.top, item.top + ( item.height / 2 ), item.height ),
28581 isOverRightHalf = this._isOverAxis( this.positionAbs.left +
28582 this.offset.click.left, item.left + ( item.width / 2 ), item.width ),
28583 verticalDirection = this.dragDirection.vertical,
28584 horizontalDirection = this.dragDirection.horizontal;
28585
28586 if ( this.floating && horizontalDirection ) {
28587 return ( ( horizontalDirection === "right" && isOverRightHalf ) ||
28588 ( horizontalDirection === "left" && !isOverRightHalf ) );
28589 } else {
28590 return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) ||
28591 ( verticalDirection === "up" && !isOverBottomHalf ) );
28592 }
28593
28594 },
28595
28596 _getDragVerticalDirection: function() {
28597 var delta = this.positionAbs.top - this.lastPositionAbs.top;
28598 return delta !== 0 && ( delta > 0 ? "down" : "up" );
28599 },
28600
28601 _getDragHorizontalDirection: function() {
28602 var delta = this.positionAbs.left - this.lastPositionAbs.left;
28603 return delta !== 0 && ( delta > 0 ? "right" : "left" );
28604 },
28605
28606 refresh: function( event ) {
28607 this._refreshItems( event );
28608 this._setHandleClassName();
28609 this.refreshPositions();
28610 return this;
28611 },
28612
28613 _connectWith: function() {
28614 var options = this.options;
28615 return options.connectWith.constructor === String ?
28616 [ options.connectWith ] :
28617 options.connectWith;
28618 },
28619
28620 _getItemsAsjQuery: function( connected ) {
28621
28622 var i, j, cur, inst,
28623 items = [],
28624 queries = [],
28625 connectWith = this._connectWith();
28626
28627 if ( connectWith && connected ) {
28628 for ( i = connectWith.length - 1; i >= 0; i-- ) {
28629 cur = $( connectWith[ i ], this.document[ 0 ] );
28630 for ( j = cur.length - 1; j >= 0; j-- ) {
28631 inst = $.data( cur[ j ], this.widgetFullName );
28632 if ( inst && inst !== this && !inst.options.disabled ) {
28633 queries.push( [ typeof inst.options.items === "function" ?
28634 inst.options.items.call( inst.element ) :
28635 $( inst.options.items, inst.element )
28636 .not( ".ui-sortable-helper" )
28637 .not( ".ui-sortable-placeholder" ), inst ] );
28638 }
28639 }
28640 }
28641 }
28642
28643 queries.push( [ typeof this.options.items === "function" ?
28644 this.options.items
28645 .call( this.element, null, { options: this.options, item: this.currentItem } ) :
28646 $( this.options.items, this.element )
28647 .not( ".ui-sortable-helper" )
28648 .not( ".ui-sortable-placeholder" ), this ] );
28649
28650 function addItems() {
28651 items.push( this );
28652 }
28653 for ( i = queries.length - 1; i >= 0; i-- ) {
28654 queries[ i ][ 0 ].each( addItems );
28655 }
28656
28657 return $( items );
28658
28659 },
28660
28661 _removeCurrentsFromItems: function() {
28662
28663 var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" );
28664
28665 this.items = $.grep( this.items, function( item ) {
28666 for ( var j = 0; j < list.length; j++ ) {
28667 if ( list[ j ] === item.item[ 0 ] ) {
28668 return false;
28669 }
28670 }
28671 return true;
28672 } );
28673
28674 },
28675
28676 _refreshItems: function( event ) {
28677
28678 this.items = [];
28679 this.containers = [ this ];
28680
28681 var i, j, cur, inst, targetData, _queries, item, queriesLength,
28682 items = this.items,
28683 queries = [ [ typeof this.options.items === "function" ?
28684 this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :
28685 $( this.options.items, this.element ), this ] ],
28686 connectWith = this._connectWith();
28687
28688 //Shouldn't be run the first time through due to massive slow-down
28689 if ( connectWith && this.ready ) {
28690 for ( i = connectWith.length - 1; i >= 0; i-- ) {
28691 cur = $( connectWith[ i ], this.document[ 0 ] );
28692 for ( j = cur.length - 1; j >= 0; j-- ) {
28693 inst = $.data( cur[ j ], this.widgetFullName );
28694 if ( inst && inst !== this && !inst.options.disabled ) {
28695 queries.push( [ typeof inst.options.items === "function" ?
28696 inst.options.items
28697 .call( inst.element[ 0 ], event, { item: this.currentItem } ) :
28698 $( inst.options.items, inst.element ), inst ] );
28699 this.containers.push( inst );
28700 }
28701 }
28702 }
28703 }
28704
28705 for ( i = queries.length - 1; i >= 0; i-- ) {
28706 targetData = queries[ i ][ 1 ];
28707 _queries = queries[ i ][ 0 ];
28708
28709 for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {
28710 item = $( _queries[ j ] );
28711
28712 // Data for target checking (mouse manager)
28713 item.data( this.widgetName + "-item", targetData );
28714
28715 items.push( {
28716 item: item,
28717 instance: targetData,
28718 width: 0, height: 0,
28719 left: 0, top: 0
28720 } );
28721 }
28722 }
28723
28724 },
28725
28726 _refreshItemPositions: function( fast ) {
28727 var i, item, t, p;
28728
28729 for ( i = this.items.length - 1; i >= 0; i-- ) {
28730 item = this.items[ i ];
28731
28732 //We ignore calculating positions of all connected containers when we're not over them
28733 if ( this.currentContainer && item.instance !== this.currentContainer &&
28734 item.item[ 0 ] !== this.currentItem[ 0 ] ) {
28735 continue;
28736 }
28737
28738 t = this.options.toleranceElement ?
28739 $( this.options.toleranceElement, item.item ) :
28740 item.item;
28741
28742 if ( !fast ) {
28743 item.width = t.outerWidth();
28744 item.height = t.outerHeight();
28745 }
28746
28747 p = t.offset();
28748 item.left = p.left;
28749 item.top = p.top;
28750 }
28751 },
28752
28753 refreshPositions: function( fast ) {
28754
28755 // Determine whether items are being displayed horizontally
28756 this.floating = this.items.length ?
28757 this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
28758 false;
28759
28760 // This has to be redone because due to the item being moved out/into the offsetParent,
28761 // the offsetParent's position will change
28762 if ( this.offsetParent && this.helper ) {
28763 this.offset.parent = this._getParentOffset();
28764 }
28765
28766 this._refreshItemPositions( fast );
28767
28768 var i, p;
28769
28770 if ( this.options.custom && this.options.custom.refreshContainers ) {
28771 this.options.custom.refreshContainers.call( this );
28772 } else {
28773 for ( i = this.containers.length - 1; i >= 0; i-- ) {
28774 p = this.containers[ i ].element.offset();
28775 this.containers[ i ].containerCache.left = p.left;
28776 this.containers[ i ].containerCache.top = p.top;
28777 this.containers[ i ].containerCache.width =
28778 this.containers[ i ].element.outerWidth();
28779 this.containers[ i ].containerCache.height =
28780 this.containers[ i ].element.outerHeight();
28781 }
28782 }
28783
28784 return this;
28785 },
28786
28787 _createPlaceholder: function( that ) {
28788 that = that || this;
28789 var className, nodeName,
28790 o = that.options;
28791
28792 if ( !o.placeholder || o.placeholder.constructor === String ) {
28793 className = o.placeholder;
28794 nodeName = that.currentItem[ 0 ].nodeName.toLowerCase();
28795 o.placeholder = {
28796 element: function() {
28797
28798 var element = $( "<" + nodeName + ">", that.document[ 0 ] );
28799
28800 that._addClass( element, "ui-sortable-placeholder",
28801 className || that.currentItem[ 0 ].className )
28802 ._removeClass( element, "ui-sortable-helper" );
28803
28804 if ( nodeName === "tbody" ) {
28805 that._createTrPlaceholder(
28806 that.currentItem.find( "tr" ).eq( 0 ),
28807 $( "<tr>", that.document[ 0 ] ).appendTo( element )
28808 );
28809 } else if ( nodeName === "tr" ) {
28810 that._createTrPlaceholder( that.currentItem, element );
28811 } else if ( nodeName === "img" ) {
28812 element.attr( "src", that.currentItem.attr( "src" ) );
28813 }
28814
28815 if ( !className ) {
28816 element.css( "visibility", "hidden" );
28817 }
28818
28819 return element;
28820 },
28821 update: function( container, p ) {
28822
28823 // 1. If a className is set as 'placeholder option, we don't force sizes -
28824 // the class is responsible for that
28825 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a
28826 // class name is specified
28827 if ( className && !o.forcePlaceholderSize ) {
28828 return;
28829 }
28830
28831 // If the element doesn't have a actual height or width by itself (without
28832 // styles coming from a stylesheet), it receives the inline height and width
28833 // from the dragged item. Or, if it's a tbody or tr, it's going to have a height
28834 // anyway since we're populating them with <td>s above, but they're unlikely to
28835 // be the correct height on their own if the row heights are dynamic, so we'll
28836 // always assign the height of the dragged item given forcePlaceholderSize
28837 // is true.
28838 if ( !p.height() || ( o.forcePlaceholderSize &&
28839 ( nodeName === "tbody" || nodeName === "tr" ) ) ) {
28840 p.height(
28841 that.currentItem.innerHeight() -
28842 parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) -
28843 parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) );
28844 }
28845 if ( !p.width() ) {
28846 p.width(
28847 that.currentItem.innerWidth() -
28848 parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) -
28849 parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) );
28850 }
28851 }
28852 };
28853 }
28854
28855 //Create the placeholder
28856 that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );
28857
28858 //Append it after the actual current item
28859 that.currentItem.after( that.placeholder );
28860
28861 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
28862 o.placeholder.update( that, that.placeholder );
28863
28864 },
28865
28866 _createTrPlaceholder: function( sourceTr, targetTr ) {
28867 var that = this;
28868
28869 sourceTr.children().each( function() {
28870 $( "<td>&#160;</td>", that.document[ 0 ] )
28871 .attr( "colspan", $( this ).attr( "colspan" ) || 1 )
28872 .appendTo( targetTr );
28873 } );
28874 },
28875
28876 _contactContainers: function( event ) {
28877 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
28878 floating, axis,
28879 innermostContainer = null,
28880 innermostIndex = null;
28881
28882 // Get innermost container that intersects with item
28883 for ( i = this.containers.length - 1; i >= 0; i-- ) {
28884
28885 // Never consider a container that's located within the item itself
28886 if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {
28887 continue;
28888 }
28889
28890 if ( this._intersectsWith( this.containers[ i ].containerCache ) ) {
28891
28892 // If we've already found a container and it's more "inner" than this, then continue
28893 if ( innermostContainer &&
28894 $.contains(
28895 this.containers[ i ].element[ 0 ],
28896 innermostContainer.element[ 0 ] ) ) {
28897 continue;
28898 }
28899
28900 innermostContainer = this.containers[ i ];
28901 innermostIndex = i;
28902
28903 } else {
28904
28905 // container doesn't intersect. trigger "out" event if necessary
28906 if ( this.containers[ i ].containerCache.over ) {
28907 this.containers[ i ]._trigger( "out", event, this._uiHash( this ) );
28908 this.containers[ i ].containerCache.over = 0;
28909 }
28910 }
28911
28912 }
28913
28914 // If no intersecting containers found, return
28915 if ( !innermostContainer ) {
28916 return;
28917 }
28918
28919 // Move the item into the container if it's not there already
28920 if ( this.containers.length === 1 ) {
28921 if ( !this.containers[ innermostIndex ].containerCache.over ) {
28922 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
28923 this.containers[ innermostIndex ].containerCache.over = 1;
28924 }
28925 } else {
28926
28927 // When entering a new container, we will find the item with the least distance and
28928 // append our item near it
28929 dist = 10000;
28930 itemWithLeastDistance = null;
28931 floating = innermostContainer.floating || this._isFloating( this.currentItem );
28932 posProperty = floating ? "left" : "top";
28933 sizeProperty = floating ? "width" : "height";
28934 axis = floating ? "pageX" : "pageY";
28935
28936 for ( j = this.items.length - 1; j >= 0; j-- ) {
28937 if ( !$.contains(
28938 this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )
28939 ) {
28940 continue;
28941 }
28942 if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {
28943 continue;
28944 }
28945
28946 cur = this.items[ j ].item.offset()[ posProperty ];
28947 nearBottom = false;
28948 if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
28949 nearBottom = true;
28950 }
28951
28952 if ( Math.abs( event[ axis ] - cur ) < dist ) {
28953 dist = Math.abs( event[ axis ] - cur );
28954 itemWithLeastDistance = this.items[ j ];
28955 this.direction = nearBottom ? "up" : "down";
28956 }
28957 }
28958
28959 //Check if dropOnEmpty is enabled
28960 if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {
28961 return;
28962 }
28963
28964 if ( this.currentContainer === this.containers[ innermostIndex ] ) {
28965 if ( !this.currentContainer.containerCache.over ) {
28966 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
28967 this.currentContainer.containerCache.over = 1;
28968 }
28969 return;
28970 }
28971
28972 if ( itemWithLeastDistance ) {
28973 this._rearrange( event, itemWithLeastDistance, null, true );
28974 } else {
28975 this._rearrange( event, null, this.containers[ innermostIndex ].element, true );
28976 }
28977 this._trigger( "change", event, this._uiHash() );
28978 this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) );
28979 this.currentContainer = this.containers[ innermostIndex ];
28980
28981 //Update the placeholder
28982 this.options.placeholder.update( this.currentContainer, this.placeholder );
28983
28984 //Update scrollParent
28985 this.scrollParent = this.placeholder.scrollParent();
28986
28987 //Update overflowOffset
28988 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
28989 this.scrollParent[ 0 ].tagName !== "HTML" ) {
28990 this.overflowOffset = this.scrollParent.offset();
28991 }
28992
28993 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
28994 this.containers[ innermostIndex ].containerCache.over = 1;
28995 }
28996
28997 },
28998
28999 _createHelper: function( event ) {
29000
29001 var o = this.options,
29002 helper = typeof o.helper === "function" ?
29003 $( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :
29004 ( o.helper === "clone" ? this.currentItem.clone() : this.currentItem );
29005
29006 //Add the helper to the DOM if that didn't happen already
29007 if ( !helper.parents( "body" ).length ) {
29008 this.appendTo[ 0 ].appendChild( helper[ 0 ] );
29009 }
29010
29011 if ( helper[ 0 ] === this.currentItem[ 0 ] ) {
29012 this._storedCSS = {
29013 width: this.currentItem[ 0 ].style.width,
29014 height: this.currentItem[ 0 ].style.height,
29015 position: this.currentItem.css( "position" ),
29016 top: this.currentItem.css( "top" ),
29017 left: this.currentItem.css( "left" )
29018 };
29019 }
29020
29021 if ( !helper[ 0 ].style.width || o.forceHelperSize ) {
29022 helper.width( this.currentItem.width() );
29023 }
29024 if ( !helper[ 0 ].style.height || o.forceHelperSize ) {
29025 helper.height( this.currentItem.height() );
29026 }
29027
29028 return helper;
29029
29030 },
29031
29032 _adjustOffsetFromHelper: function( obj ) {
29033 if ( typeof obj === "string" ) {
29034 obj = obj.split( " " );
29035 }
29036 if ( Array.isArray( obj ) ) {
29037 obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
29038 }
29039 if ( "left" in obj ) {
29040 this.offset.click.left = obj.left + this.margins.left;
29041 }
29042 if ( "right" in obj ) {
29043 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
29044 }
29045 if ( "top" in obj ) {
29046 this.offset.click.top = obj.top + this.margins.top;
29047 }
29048 if ( "bottom" in obj ) {
29049 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
29050 }
29051 },
29052
29053 _getParentOffset: function() {
29054
29055 //Get the offsetParent and cache its position
29056 this.offsetParent = this.helper.offsetParent();
29057 var po = this.offsetParent.offset();
29058
29059 // This is a special case where we need to modify a offset calculated on start, since the
29060 // following happened:
29061 // 1. The position of the helper is absolute, so it's position is calculated based on the
29062 // next positioned parent
29063 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
29064 // the document, which means that the scroll is included in the initial calculation of the
29065 // offset of the parent, and never recalculated upon drag
29066 if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&
29067 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
29068 po.left += this.scrollParent.scrollLeft();
29069 po.top += this.scrollParent.scrollTop();
29070 }
29071
29072 // This needs to be actually done for all browsers, since pageX/pageY includes
29073 // this information.
29074 if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ) {
29075 po = { top: 0, left: 0 };
29076 }
29077
29078 return {
29079 top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
29080 left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
29081 };
29082
29083 },
29084
29085 _getRelativeOffset: function() {
29086
29087 if ( this.cssPosition === "relative" ) {
29088 var p = this.currentItem.position();
29089 return {
29090 top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
29091 this.scrollParent.scrollTop(),
29092 left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
29093 this.scrollParent.scrollLeft()
29094 };
29095 } else {
29096 return { top: 0, left: 0 };
29097 }
29098
29099 },
29100
29101 _cacheMargins: function() {
29102 this.margins = {
29103 left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ),
29104 top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 )
29105 };
29106 },
29107
29108 _cacheHelperProportions: function() {
29109 this.helperProportions = {
29110 width: this.helper.outerWidth(),
29111 height: this.helper.outerHeight()
29112 };
29113 },
29114
29115 _setContainment: function() {
29116
29117 var ce, co, over,
29118 o = this.options;
29119 if ( o.containment === "parent" ) {
29120 o.containment = this.helper[ 0 ].parentNode;
29121 }
29122 if ( o.containment === "document" || o.containment === "window" ) {
29123 this.containment = [
29124 0 - this.offset.relative.left - this.offset.parent.left,
29125 0 - this.offset.relative.top - this.offset.parent.top,
29126 o.containment === "document" ?
29127 this.document.width() :
29128 this.window.width() - this.helperProportions.width - this.margins.left,
29129 ( o.containment === "document" ?
29130 ( this.document.height() || document.body.parentNode.scrollHeight ) :
29131 this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight
29132 ) - this.helperProportions.height - this.margins.top
29133 ];
29134 }
29135
29136 if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {
29137 ce = $( o.containment )[ 0 ];
29138 co = $( o.containment ).offset();
29139 over = ( $( ce ).css( "overflow" ) !== "hidden" );
29140
29141 this.containment = [
29142 co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) +
29143 ( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left,
29144 co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) +
29145 ( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top,
29146 co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
29147 ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) -
29148 ( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) -
29149 this.helperProportions.width - this.margins.left,
29150 co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
29151 ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) -
29152 ( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) -
29153 this.helperProportions.height - this.margins.top
29154 ];
29155 }
29156
29157 },
29158
29159 _convertPositionTo: function( d, pos ) {
29160
29161 if ( !pos ) {
29162 pos = this.position;
29163 }
29164 var mod = d === "absolute" ? 1 : -1,
29165 scroll = this.cssPosition === "absolute" &&
29166 !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
29167 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
29168 this.offsetParent :
29169 this.scrollParent,
29170 scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
29171
29172 return {
29173 top: (
29174
29175 // The absolute mouse position
29176 pos.top +
29177
29178 // Only for relative positioned nodes: Relative offset from element to offset parent
29179 this.offset.relative.top * mod +
29180
29181 // The offsetParent's offset without borders (offset + border)
29182 this.offset.parent.top * mod -
29183 ( ( this.cssPosition === "fixed" ?
29184 -this.scrollParent.scrollTop() :
29185 ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
29186 ),
29187 left: (
29188
29189 // The absolute mouse position
29190 pos.left +
29191
29192 // Only for relative positioned nodes: Relative offset from element to offset parent
29193 this.offset.relative.left * mod +
29194
29195 // The offsetParent's offset without borders (offset + border)
29196 this.offset.parent.left * mod -
29197 ( ( this.cssPosition === "fixed" ?
29198 -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
29199 scroll.scrollLeft() ) * mod )
29200 )
29201 };
29202
29203 },
29204
29205 _generatePosition: function( event ) {
29206
29207 var top, left,
29208 o = this.options,
29209 pageX = event.pageX,
29210 pageY = event.pageY,
29211 scroll = this.cssPosition === "absolute" &&
29212 !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
29213 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
29214 this.offsetParent :
29215 this.scrollParent,
29216 scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
29217
29218 // This is another very weird special case that only happens for relative elements:
29219 // 1. If the css position is relative
29220 // 2. and the scroll parent is the document or similar to the offset parent
29221 // we have to refresh the relative offset during the scroll so there are no jumps
29222 if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
29223 this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
29224 this.offset.relative = this._getRelativeOffset();
29225 }
29226
29227 /*
29228 * - Position constraining -
29229 * Constrain the position to a mix of grid, containment.
29230 */
29231
29232 if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
29233
29234 if ( this.containment ) {
29235 if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
29236 pageX = this.containment[ 0 ] + this.offset.click.left;
29237 }
29238 if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
29239 pageY = this.containment[ 1 ] + this.offset.click.top;
29240 }
29241 if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
29242 pageX = this.containment[ 2 ] + this.offset.click.left;
29243 }
29244 if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
29245 pageY = this.containment[ 3 ] + this.offset.click.top;
29246 }
29247 }
29248
29249 if ( o.grid ) {
29250 top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
29251 o.grid[ 1 ] ) * o.grid[ 1 ];
29252 pageY = this.containment ?
29253 ( ( top - this.offset.click.top >= this.containment[ 1 ] &&
29254 top - this.offset.click.top <= this.containment[ 3 ] ) ?
29255 top :
29256 ( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
29257 top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
29258 top;
29259
29260 left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
29261 o.grid[ 0 ] ) * o.grid[ 0 ];
29262 pageX = this.containment ?
29263 ( ( left - this.offset.click.left >= this.containment[ 0 ] &&
29264 left - this.offset.click.left <= this.containment[ 2 ] ) ?
29265 left :
29266 ( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
29267 left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
29268 left;
29269 }
29270
29271 }
29272
29273 return {
29274 top: (
29275
29276 // The absolute mouse position
29277 pageY -
29278
29279 // Click offset (relative to the element)
29280 this.offset.click.top -
29281
29282 // Only for relative positioned nodes: Relative offset from element to offset parent
29283 this.offset.relative.top -
29284
29285 // The offsetParent's offset without borders (offset + border)
29286 this.offset.parent.top +
29287 ( ( this.cssPosition === "fixed" ?
29288 -this.scrollParent.scrollTop() :
29289 ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
29290 ),
29291 left: (
29292
29293 // The absolute mouse position
29294 pageX -
29295
29296 // Click offset (relative to the element)
29297 this.offset.click.left -
29298
29299 // Only for relative positioned nodes: Relative offset from element to offset parent
29300 this.offset.relative.left -
29301
29302 // The offsetParent's offset without borders (offset + border)
29303 this.offset.parent.left +
29304 ( ( this.cssPosition === "fixed" ?
29305 -this.scrollParent.scrollLeft() :
29306 scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
29307 )
29308 };
29309
29310 },
29311
29312 _rearrange: function( event, i, a, hardRefresh ) {
29313
29314 if ( a ) {
29315 a[ 0 ].appendChild( this.placeholder[ 0 ] );
29316 } else {
29317 i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],
29318 ( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );
29319 }
29320
29321 //Various things done here to improve the performance:
29322 // 1. we create a setTimeout, that calls refreshPositions
29323 // 2. on the instance, we have a counter variable, that get's higher after every append
29324 // 3. on the local scope, we copy the counter variable, and check in the timeout,
29325 // if it's still the same
29326 // 4. this lets only the last addition to the timeout stack through
29327 this.counter = this.counter ? ++this.counter : 1;
29328 var counter = this.counter;
29329
29330 this._delay( function() {
29331 if ( counter === this.counter ) {
29332
29333 //Precompute after each DOM insertion, NOT on mousemove
29334 this.refreshPositions( !hardRefresh );
29335 }
29336 } );
29337
29338 },
29339
29340 _clear: function( event, noPropagation ) {
29341
29342 this.reverting = false;
29343
29344 // We delay all events that have to be triggered to after the point where the placeholder
29345 // has been removed and everything else normalized again
29346 var i,
29347 delayedTriggers = [];
29348
29349 // We first have to update the dom position of the actual currentItem
29350 // Note: don't do it if the current item is already removed (by a user), or it gets
29351 // reappended (see #4088)
29352 if ( !this._noFinalSort && this.currentItem.parent().length ) {
29353 this.placeholder.before( this.currentItem );
29354 }
29355 this._noFinalSort = null;
29356
29357 if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {
29358 for ( i in this._storedCSS ) {
29359 if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) {
29360 this._storedCSS[ i ] = "";
29361 }
29362 }
29363 this.currentItem.css( this._storedCSS );
29364 this._removeClass( this.currentItem, "ui-sortable-helper" );
29365 } else {
29366 this.currentItem.show();
29367 }
29368
29369 if ( this.fromOutside && !noPropagation ) {
29370 delayedTriggers.push( function( event ) {
29371 this._trigger( "receive", event, this._uiHash( this.fromOutside ) );
29372 } );
29373 }
29374 if ( ( this.fromOutside ||
29375 this.domPosition.prev !==
29376 this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] ||
29377 this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {
29378
29379 // Trigger update callback if the DOM position has changed
29380 delayedTriggers.push( function( event ) {
29381 this._trigger( "update", event, this._uiHash() );
29382 } );
29383 }
29384
29385 // Check if the items Container has Changed and trigger appropriate
29386 // events.
29387 if ( this !== this.currentContainer ) {
29388 if ( !noPropagation ) {
29389 delayedTriggers.push( function( event ) {
29390 this._trigger( "remove", event, this._uiHash() );
29391 } );
29392 delayedTriggers.push( ( function( c ) {
29393 return function( event ) {
29394 c._trigger( "receive", event, this._uiHash( this ) );
29395 };
29396 } ).call( this, this.currentContainer ) );
29397 delayedTriggers.push( ( function( c ) {
29398 return function( event ) {
29399 c._trigger( "update", event, this._uiHash( this ) );
29400 };
29401 } ).call( this, this.currentContainer ) );
29402 }
29403 }
29404
29405 //Post events to containers
29406 function delayEvent( type, instance, container ) {
29407 return function( event ) {
29408 container._trigger( type, event, instance._uiHash( instance ) );
29409 };
29410 }
29411 for ( i = this.containers.length - 1; i >= 0; i-- ) {
29412 if ( !noPropagation ) {
29413 delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
29414 }
29415 if ( this.containers[ i ].containerCache.over ) {
29416 delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
29417 this.containers[ i ].containerCache.over = 0;
29418 }
29419 }
29420
29421 //Do what was originally in plugins
29422 if ( this._storedStylesheet ) {
29423 this._storedStylesheet.remove();
29424 this._storedStylesheet = null;
29425 }
29426 if ( this._storedOpacity ) {
29427 this.helper.css( "opacity", this._storedOpacity );
29428 }
29429 if ( this._storedZIndex ) {
29430 this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex );
29431 }
29432
29433 this.dragging = false;
29434
29435 if ( !noPropagation ) {
29436 this._trigger( "beforeStop", event, this._uiHash() );
29437 }
29438
29439 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
29440 // it unbinds ALL events from the original node!
29441 this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
29442
29443 if ( !this.cancelHelperRemoval ) {
29444 if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
29445 this.helper.remove();
29446 }
29447 this.helper = null;
29448 }
29449
29450 if ( !noPropagation ) {
29451 for ( i = 0; i < delayedTriggers.length; i++ ) {
29452
29453 // Trigger all delayed events
29454 delayedTriggers[ i ].call( this, event );
29455 }
29456 this._trigger( "stop", event, this._uiHash() );
29457 }
29458
29459 this.fromOutside = false;
29460 return !this.cancelHelperRemoval;
29461
29462 },
29463
29464 _trigger: function() {
29465 if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {
29466 this.cancel();
29467 }
29468 },
29469
29470 _uiHash: function( _inst ) {
29471 var inst = _inst || this;
29472 return {
29473 helper: inst.helper,
29474 placeholder: inst.placeholder || $( [] ),
29475 position: inst.position,
29476 originalPosition: inst.originalPosition,
29477 offset: inst.positionAbs,
29478 item: inst.currentItem,
29479 sender: _inst ? _inst.element : null
29480 };
29481 }
29482
29483} );
29484
29485} );
29486
29487
29488
29489
29490
29491/*!
29492 * jQuery UI Spinner 1.14.1
29493 * https://jqueryui.com
29494 *
29495 * Copyright OpenJS Foundation and other contributors
29496 * Released under the MIT license.
29497 * https://jquery.org/license
29498 */
29499
29500//>>label: Spinner
29501//>>group: Widgets
29502//>>description: Displays buttons to easily input numbers via the keyboard or mouse.
29503//>>docs: https://api.jqueryui.com/spinner/
29504//>>demos: https://jqueryui.com/spinner/
29505//>>css.structure: ../../themes/base/core.css
29506//>>css.structure: ../../themes/base/spinner.css
29507//>>css.theme: ../../themes/base/theme.css
29508
29509( function( factory ) {
29510 "use strict";
29511
29512 if ( typeof define === "function" && define.amd ) {
29513
29514 // AMD. Register as an anonymous module.
29515 define( [
29516 "jquery",
29517 "./button",
29518 "../version",
29519 "../keycode",
29520 "../widget"
29521 ], factory );
29522 } else {
29523
29524 // Browser globals
29525 factory( jQuery );
29526 }
29527} )( function( $ ) {
29528"use strict";
29529
29530function spinnerModifier( fn ) {
29531 return function() {
29532 var previous = this.element.val();
29533 fn.apply( this, arguments );
29534 this._refresh();
29535 if ( previous !== this.element.val() ) {
29536 this._trigger( "change" );
29537 }
29538 };
29539}
29540
29541$.widget( "ui.spinner", {
29542 version: "1.14.1",
29543 defaultElement: "<input>",
29544 widgetEventPrefix: "spin",
29545 options: {
29546 classes: {
29547 "ui-spinner": "ui-corner-all",
29548 "ui-spinner-down": "ui-corner-br",
29549 "ui-spinner-up": "ui-corner-tr"
29550 },
29551 culture: null,
29552 icons: {
29553 down: "ui-icon-triangle-1-s",
29554 up: "ui-icon-triangle-1-n"
29555 },
29556 incremental: true,
29557 max: null,
29558 min: null,
29559 numberFormat: null,
29560 page: 10,
29561 step: 1,
29562
29563 change: null,
29564 spin: null,
29565 start: null,
29566 stop: null
29567 },
29568
29569 _create: function() {
29570
29571 // handle string values that need to be parsed
29572 this._setOption( "max", this.options.max );
29573 this._setOption( "min", this.options.min );
29574 this._setOption( "step", this.options.step );
29575
29576 // Only format if there is a value, prevents the field from being marked
29577 // as invalid in Firefox, see #9573.
29578 if ( this.value() !== "" ) {
29579
29580 // Format the value, but don't constrain.
29581 this._value( this.element.val(), true );
29582 }
29583
29584 this._draw();
29585 this._on( this._events );
29586 this._refresh();
29587
29588 // Turning off autocomplete prevents the browser from remembering the
29589 // value when navigating through history, so we re-enable autocomplete
29590 // if the page is unloaded before the widget is destroyed. #7790
29591 this._on( this.window, {
29592 beforeunload: function() {
29593 this.element.removeAttr( "autocomplete" );
29594 }
29595 } );
29596 },
29597
29598 _getCreateOptions: function() {
29599 var options = this._super();
29600 var element = this.element;
29601
29602 $.each( [ "min", "max", "step" ], function( i, option ) {
29603 var value = element.attr( option );
29604 if ( value != null && value.length ) {
29605 options[ option ] = value;
29606 }
29607 } );
29608
29609 return options;
29610 },
29611
29612 _events: {
29613 keydown: function( event ) {
29614 if ( this._start( event ) && this._keydown( event ) ) {
29615 event.preventDefault();
29616 }
29617 },
29618 keyup: "_stop",
29619 focus: function() {
29620 this.previous = this.element.val();
29621 },
29622 blur: function( event ) {
29623 this._stop();
29624 this._refresh();
29625 if ( this.previous !== this.element.val() ) {
29626 this._trigger( "change", event );
29627 }
29628 },
29629 mousewheel: function( event, delta ) {
29630 var activeElement = this.document[ 0 ].activeElement;
29631 var isActive = this.element[ 0 ] === activeElement;
29632
29633 if ( !isActive || !delta ) {
29634 return;
29635 }
29636
29637 if ( !this.spinning && !this._start( event ) ) {
29638 return false;
29639 }
29640
29641 this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );
29642 clearTimeout( this.mousewheelTimer );
29643 this.mousewheelTimer = this._delay( function() {
29644 if ( this.spinning ) {
29645 this._stop( event );
29646 }
29647 }, 100 );
29648 event.preventDefault();
29649 },
29650 "mousedown .ui-spinner-button": function( event ) {
29651 var previous;
29652
29653 // We never want the buttons to have focus; whenever the user is
29654 // interacting with the spinner, the focus should be on the input.
29655 // If the input is focused then this.previous is properly set from
29656 // when the input first received focus. If the input is not focused
29657 // then we need to set this.previous based on the value before spinning.
29658 previous = this.element[ 0 ] === this.document[ 0 ].activeElement ?
29659 this.previous : this.element.val();
29660 function checkFocus() {
29661 var isActive = this.element[ 0 ] === this.document[ 0 ].activeElement;
29662 if ( !isActive ) {
29663 this.element.trigger( "focus" );
29664 this.previous = previous;
29665 }
29666 }
29667
29668 // Ensure focus is on (or stays on) the text field
29669 event.preventDefault();
29670 checkFocus.call( this );
29671
29672 if ( this._start( event ) === false ) {
29673 return;
29674 }
29675
29676 this._repeat( null, $( event.currentTarget )
29677 .hasClass( "ui-spinner-up" ) ? 1 : -1, event );
29678 },
29679 "mouseup .ui-spinner-button": "_stop",
29680 "mouseenter .ui-spinner-button": function( event ) {
29681
29682 // button will add ui-state-active if mouse was down while mouseleave and kept down
29683 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
29684 return;
29685 }
29686
29687 if ( this._start( event ) === false ) {
29688 return false;
29689 }
29690 this._repeat( null, $( event.currentTarget )
29691 .hasClass( "ui-spinner-up" ) ? 1 : -1, event );
29692 },
29693
29694 // TODO: do we really want to consider this a stop?
29695 // shouldn't we just stop the repeater and wait until mouseup before
29696 // we trigger the stop event?
29697 "mouseleave .ui-spinner-button": "_stop"
29698 },
29699
29700 // Support mobile enhanced option and make backcompat more sane
29701 _enhance: function() {
29702 this.uiSpinner = this.element
29703 .attr( "autocomplete", "off" )
29704 .wrap( "<span>" )
29705 .parent()
29706
29707 // Add buttons
29708 .append(
29709 "<a></a><a></a>"
29710 );
29711 },
29712
29713 _draw: function() {
29714 this._enhance();
29715
29716 this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" );
29717 this._addClass( "ui-spinner-input" );
29718
29719 this.element.attr( "role", "spinbutton" );
29720
29721 // Button bindings
29722 this.buttons = this.uiSpinner.children( "a" )
29723 .attr( "tabIndex", -1 )
29724 .attr( "aria-hidden", true )
29725 .button( {
29726 classes: {
29727 "ui-button": ""
29728 }
29729 } );
29730
29731 // TODO: Right now button does not support classes this is already updated in button PR
29732 this._removeClass( this.buttons, "ui-corner-all" );
29733
29734 this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" );
29735 this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" );
29736 this.buttons.first().button( {
29737 "icon": this.options.icons.up,
29738 "showLabel": false
29739 } );
29740 this.buttons.last().button( {
29741 "icon": this.options.icons.down,
29742 "showLabel": false
29743 } );
29744
29745 // IE 6 doesn't understand height: 50% for the buttons
29746 // unless the wrapper has an explicit height
29747 if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&
29748 this.uiSpinner.height() > 0 ) {
29749 this.uiSpinner.height( this.uiSpinner.height() );
29750 }
29751 },
29752
29753 _keydown: function( event ) {
29754 var options = this.options,
29755 keyCode = $.ui.keyCode;
29756
29757 switch ( event.keyCode ) {
29758 case keyCode.UP:
29759 this._repeat( null, 1, event );
29760 return true;
29761 case keyCode.DOWN:
29762 this._repeat( null, -1, event );
29763 return true;
29764 case keyCode.PAGE_UP:
29765 this._repeat( null, options.page, event );
29766 return true;
29767 case keyCode.PAGE_DOWN:
29768 this._repeat( null, -options.page, event );
29769 return true;
29770 }
29771
29772 return false;
29773 },
29774
29775 _start: function( event ) {
29776 if ( !this.spinning && this._trigger( "start", event ) === false ) {
29777 return false;
29778 }
29779
29780 if ( !this.counter ) {
29781 this.counter = 1;
29782 }
29783 this.spinning = true;
29784 return true;
29785 },
29786
29787 _repeat: function( i, steps, event ) {
29788 i = i || 500;
29789
29790 clearTimeout( this.timer );
29791 this.timer = this._delay( function() {
29792 this._repeat( 40, steps, event );
29793 }, i );
29794
29795 this._spin( steps * this.options.step, event );
29796 },
29797
29798 _spin: function( step, event ) {
29799 var value = this.value() || 0;
29800
29801 if ( !this.counter ) {
29802 this.counter = 1;
29803 }
29804
29805 value = this._adjustValue( value + step * this._increment( this.counter ) );
29806
29807 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) {
29808 this._value( value );
29809 this.counter++;
29810 }
29811 },
29812
29813 _increment: function( i ) {
29814 var incremental = this.options.incremental;
29815
29816 if ( incremental ) {
29817 return typeof incremental === "function" ?
29818 incremental( i ) :
29819 Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
29820 }
29821
29822 return 1;
29823 },
29824
29825 _precision: function() {
29826 var precision = this._precisionOf( this.options.step );
29827 if ( this.options.min !== null ) {
29828 precision = Math.max( precision, this._precisionOf( this.options.min ) );
29829 }
29830 return precision;
29831 },
29832
29833 _precisionOf: function( num ) {
29834 var str = num.toString(),
29835 decimal = str.indexOf( "." );
29836 return decimal === -1 ? 0 : str.length - decimal - 1;
29837 },
29838
29839 _adjustValue: function( value ) {
29840 var base, aboveMin,
29841 options = this.options;
29842
29843 // Make sure we're at a valid step
29844 // - find out where we are relative to the base (min or 0)
29845 base = options.min !== null ? options.min : 0;
29846 aboveMin = value - base;
29847
29848 // - round to the nearest step
29849 aboveMin = Math.round( aboveMin / options.step ) * options.step;
29850
29851 // - rounding is based on 0, so adjust back to our base
29852 value = base + aboveMin;
29853
29854 // Fix precision from bad JS floating point math
29855 value = parseFloat( value.toFixed( this._precision() ) );
29856
29857 // Clamp the value
29858 if ( options.max !== null && value > options.max ) {
29859 return options.max;
29860 }
29861 if ( options.min !== null && value < options.min ) {
29862 return options.min;
29863 }
29864
29865 return value;
29866 },
29867
29868 _stop: function( event ) {
29869 if ( !this.spinning ) {
29870 return;
29871 }
29872
29873 clearTimeout( this.timer );
29874 clearTimeout( this.mousewheelTimer );
29875 this.counter = 0;
29876 this.spinning = false;
29877 this._trigger( "stop", event );
29878 },
29879
29880 _setOption: function( key, value ) {
29881 var prevValue, first, last;
29882
29883 if ( key === "culture" || key === "numberFormat" ) {
29884 prevValue = this._parse( this.element.val() );
29885 this.options[ key ] = value;
29886 this.element.val( this._format( prevValue ) );
29887 return;
29888 }
29889
29890 if ( key === "max" || key === "min" || key === "step" ) {
29891 if ( typeof value === "string" ) {
29892 value = this._parse( value );
29893 }
29894 }
29895 if ( key === "icons" ) {
29896 first = this.buttons.first().find( ".ui-icon" );
29897 this._removeClass( first, null, this.options.icons.up );
29898 this._addClass( first, null, value.up );
29899 last = this.buttons.last().find( ".ui-icon" );
29900 this._removeClass( last, null, this.options.icons.down );
29901 this._addClass( last, null, value.down );
29902 }
29903
29904 this._super( key, value );
29905 },
29906
29907 _setOptionDisabled: function( value ) {
29908 this._super( value );
29909
29910 this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value );
29911 this.element.prop( "disabled", !!value );
29912 this.buttons.button( value ? "disable" : "enable" );
29913 },
29914
29915 _setOptions: spinnerModifier( function( options ) {
29916 this._super( options );
29917 } ),
29918
29919 _parse: function( val ) {
29920 if ( typeof val === "string" && val !== "" ) {
29921 val = window.Globalize && this.options.numberFormat ?
29922 Globalize.parseFloat( val, 10, this.options.culture ) : +val;
29923 }
29924 return val === "" || isNaN( val ) ? null : val;
29925 },
29926
29927 _format: function( value ) {
29928 if ( value === "" ) {
29929 return "";
29930 }
29931 return window.Globalize && this.options.numberFormat ?
29932 Globalize.format( value, this.options.numberFormat, this.options.culture ) :
29933 value;
29934 },
29935
29936 _refresh: function() {
29937 this.element.attr( {
29938 "aria-valuemin": this.options.min,
29939 "aria-valuemax": this.options.max,
29940
29941 // TODO: what should we do with values that can't be parsed?
29942 "aria-valuenow": this._parse( this.element.val() )
29943 } );
29944 },
29945
29946 isValid: function() {
29947 var value = this.value();
29948
29949 // Null is invalid
29950 if ( value === null ) {
29951 return false;
29952 }
29953
29954 // If value gets adjusted, it's invalid
29955 return value === this._adjustValue( value );
29956 },
29957
29958 // Update the value without triggering change
29959 _value: function( value, allowAny ) {
29960 var parsed;
29961 if ( value !== "" ) {
29962 parsed = this._parse( value );
29963 if ( parsed !== null ) {
29964 if ( !allowAny ) {
29965 parsed = this._adjustValue( parsed );
29966 }
29967 value = this._format( parsed );
29968 }
29969 }
29970 this.element.val( value );
29971 this._refresh();
29972 },
29973
29974 _destroy: function() {
29975 this.element
29976 .prop( "disabled", false )
29977 .removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" );
29978
29979 this.uiSpinner.replaceWith( this.element );
29980 },
29981
29982 stepUp: spinnerModifier( function( steps ) {
29983 this._stepUp( steps );
29984 } ),
29985 _stepUp: function( steps ) {
29986 if ( this._start() ) {
29987 this._spin( ( steps || 1 ) * this.options.step );
29988 this._stop();
29989 }
29990 },
29991
29992 stepDown: spinnerModifier( function( steps ) {
29993 this._stepDown( steps );
29994 } ),
29995 _stepDown: function( steps ) {
29996 if ( this._start() ) {
29997 this._spin( ( steps || 1 ) * -this.options.step );
29998 this._stop();
29999 }
30000 },
30001
30002 pageUp: spinnerModifier( function( pages ) {
30003 this._stepUp( ( pages || 1 ) * this.options.page );
30004 } ),
30005
30006 pageDown: spinnerModifier( function( pages ) {
30007 this._stepDown( ( pages || 1 ) * this.options.page );
30008 } ),
30009
30010 value: function( newVal ) {
30011 if ( !arguments.length ) {
30012 return this._parse( this.element.val() );
30013 }
30014 spinnerModifier( this._value ).call( this, newVal );
30015 },
30016
30017 widget: function() {
30018 return this.uiSpinner;
30019 }
30020} );
30021
30022// DEPRECATED
30023// TODO: switch return back to widget declaration at top of file when this is removed
30024if ( $.uiBackCompat === true ) {
30025
30026 // Backcompat for spinner html extension points
30027 $.widget( "ui.spinner", $.ui.spinner, {
30028 _enhance: function() {
30029 this.uiSpinner = this.element
30030 .attr( "autocomplete", "off" )
30031 .wrap( this._uiSpinnerHtml() )
30032 .parent()
30033
30034 // Add buttons
30035 .append( this._buttonHtml() );
30036 },
30037 _uiSpinnerHtml: function() {
30038 return "<span>";
30039 },
30040
30041 _buttonHtml: function() {
30042 return "<a></a><a></a>";
30043 }
30044 } );
30045}
30046
30047return $.ui.spinner;
30048
30049} );
30050
30051
30052
30053
30054
30055/*!
30056 * jQuery UI Tabs 1.14.1
30057 * https://jqueryui.com
30058 *
30059 * Copyright OpenJS Foundation and other contributors
30060 * Released under the MIT license.
30061 * https://jquery.org/license
30062 */
30063
30064//>>label: Tabs
30065//>>group: Widgets
30066//>>description: Transforms a set of container elements into a tab structure.
30067//>>docs: https://api.jqueryui.com/tabs/
30068//>>demos: https://jqueryui.com/tabs/
30069//>>css.structure: ../../themes/base/core.css
30070//>>css.structure: ../../themes/base/tabs.css
30071//>>css.theme: ../../themes/base/theme.css
30072
30073( function( factory ) {
30074 "use strict";
30075
30076 if ( typeof define === "function" && define.amd ) {
30077
30078 // AMD. Register as an anonymous module.
30079 define( [
30080 "jquery",
30081 "../keycode",
30082 "../unique-id",
30083 "../version",
30084 "../widget"
30085 ], factory );
30086 } else {
30087
30088 // Browser globals
30089 factory( jQuery );
30090 }
30091} )( function( $ ) {
30092"use strict";
30093
30094$.widget( "ui.tabs", {
30095 version: "1.14.1",
30096 delay: 300,
30097 options: {
30098 active: null,
30099 classes: {
30100 "ui-tabs": "ui-corner-all",
30101 "ui-tabs-nav": "ui-corner-all",
30102 "ui-tabs-panel": "ui-corner-bottom",
30103 "ui-tabs-tab": "ui-corner-top"
30104 },
30105 collapsible: false,
30106 event: "click",
30107 heightStyle: "content",
30108 hide: null,
30109 show: null,
30110
30111 // Callbacks
30112 activate: null,
30113 beforeActivate: null,
30114 beforeLoad: null,
30115 load: null
30116 },
30117
30118 _isLocal: ( function() {
30119 var rhash = /#.*$/;
30120
30121 return function( anchor ) {
30122 var anchorUrl, locationUrl;
30123
30124 anchorUrl = anchor.href.replace( rhash, "" );
30125 locationUrl = location.href.replace( rhash, "" );
30126
30127 // Decoding may throw an error if the URL isn't UTF-8 (#9518)
30128 try {
30129 anchorUrl = decodeURIComponent( anchorUrl );
30130 } catch ( error ) {}
30131 try {
30132 locationUrl = decodeURIComponent( locationUrl );
30133 } catch ( error ) {}
30134
30135 return anchor.hash.length > 1 && anchorUrl === locationUrl;
30136 };
30137 } )(),
30138
30139 _create: function() {
30140 var that = this,
30141 options = this.options;
30142
30143 this.running = false;
30144
30145 this._addClass( "ui-tabs", "ui-widget ui-widget-content" );
30146 this._toggleClass( "ui-tabs-collapsible", null, options.collapsible );
30147
30148 this._processTabs();
30149 options.active = this._initialActive();
30150
30151 // Take disabling tabs via class attribute from HTML
30152 // into account and update option properly.
30153 if ( Array.isArray( options.disabled ) ) {
30154 options.disabled = $.uniqueSort( options.disabled.concat(
30155 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
30156 return that.tabs.index( li );
30157 } )
30158 ) ).sort();
30159 }
30160
30161 // Check for length avoids error when initializing empty list
30162 if ( this.options.active !== false && this.anchors.length ) {
30163 this.active = this._findActive( options.active );
30164 } else {
30165 this.active = $();
30166 }
30167
30168 this._refresh();
30169
30170 if ( this.active.length ) {
30171 this.load( options.active );
30172 }
30173 },
30174
30175 _initialActive: function() {
30176 var active = this.options.active,
30177 collapsible = this.options.collapsible,
30178 locationHashDecoded = decodeURIComponent( location.hash.substring( 1 ) );
30179
30180 if ( active === null ) {
30181
30182 // check the fragment identifier in the URL
30183 if ( locationHashDecoded ) {
30184 this.tabs.each( function( i, tab ) {
30185 if ( $( tab ).attr( "aria-controls" ) === locationHashDecoded ) {
30186 active = i;
30187 return false;
30188 }
30189 } );
30190 }
30191
30192 // Check for a tab marked active via a class
30193 if ( active === null ) {
30194 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
30195 }
30196
30197 // No active tab, set to false
30198 if ( active === null || active === -1 ) {
30199 active = this.tabs.length ? 0 : false;
30200 }
30201 }
30202
30203 // Handle numbers: negative, out of range
30204 if ( active !== false ) {
30205 active = this.tabs.index( this.tabs.eq( active ) );
30206 if ( active === -1 ) {
30207 active = collapsible ? false : 0;
30208 }
30209 }
30210
30211 // Don't allow collapsible: false and active: false
30212 if ( !collapsible && active === false && this.anchors.length ) {
30213 active = 0;
30214 }
30215
30216 return active;
30217 },
30218
30219 _getCreateEventData: function() {
30220 return {
30221 tab: this.active,
30222 panel: !this.active.length ? $() : this._getPanelForTab( this.active )
30223 };
30224 },
30225
30226 _tabKeydown: function( event ) {
30227 var focusedTab = $( this.document[ 0 ].activeElement ).closest( "li" ),
30228 selectedIndex = this.tabs.index( focusedTab ),
30229 goingForward = true;
30230
30231 if ( this._handlePageNav( event ) ) {
30232 return;
30233 }
30234
30235 switch ( event.keyCode ) {
30236 case $.ui.keyCode.RIGHT:
30237 case $.ui.keyCode.DOWN:
30238 selectedIndex++;
30239 break;
30240 case $.ui.keyCode.UP:
30241 case $.ui.keyCode.LEFT:
30242 goingForward = false;
30243 selectedIndex--;
30244 break;
30245 case $.ui.keyCode.END:
30246 selectedIndex = this.anchors.length - 1;
30247 break;
30248 case $.ui.keyCode.HOME:
30249 selectedIndex = 0;
30250 break;
30251 case $.ui.keyCode.SPACE:
30252
30253 // Activate only, no collapsing
30254 event.preventDefault();
30255 clearTimeout( this.activating );
30256 this._activate( selectedIndex );
30257 return;
30258 case $.ui.keyCode.ENTER:
30259
30260 // Toggle (cancel delayed activation, allow collapsing)
30261 event.preventDefault();
30262 clearTimeout( this.activating );
30263
30264 // Determine if we should collapse or activate
30265 this._activate( selectedIndex === this.options.active ? false : selectedIndex );
30266 return;
30267 default:
30268 return;
30269 }
30270
30271 // Focus the appropriate tab, based on which key was pressed
30272 event.preventDefault();
30273 clearTimeout( this.activating );
30274 selectedIndex = this._focusNextTab( selectedIndex, goingForward );
30275
30276 // Navigating with control/command key will prevent automatic activation
30277 if ( !event.ctrlKey && !event.metaKey ) {
30278
30279 // Update aria-selected immediately so that AT think the tab is already selected.
30280 // Otherwise AT may confuse the user by stating that they need to activate the tab,
30281 // but the tab will already be activated by the time the announcement finishes.
30282 focusedTab.attr( "aria-selected", "false" );
30283 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
30284
30285 this.activating = this._delay( function() {
30286 this.option( "active", selectedIndex );
30287 }, this.delay );
30288 }
30289 },
30290
30291 _panelKeydown: function( event ) {
30292 if ( this._handlePageNav( event ) ) {
30293 return;
30294 }
30295
30296 // Ctrl+up moves focus to the current tab
30297 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
30298 event.preventDefault();
30299 this.active.trigger( "focus" );
30300 }
30301 },
30302
30303 // Alt+page up/down moves focus to the previous/next tab (and activates)
30304 _handlePageNav: function( event ) {
30305 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
30306 this._activate( this._focusNextTab( this.options.active - 1, false ) );
30307 return true;
30308 }
30309 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
30310 this._activate( this._focusNextTab( this.options.active + 1, true ) );
30311 return true;
30312 }
30313 },
30314
30315 _findNextTab: function( index, goingForward ) {
30316 var lastTabIndex = this.tabs.length - 1;
30317
30318 function constrain() {
30319 if ( index > lastTabIndex ) {
30320 index = 0;
30321 }
30322 if ( index < 0 ) {
30323 index = lastTabIndex;
30324 }
30325 return index;
30326 }
30327
30328 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
30329 index = goingForward ? index + 1 : index - 1;
30330 }
30331
30332 return index;
30333 },
30334
30335 _focusNextTab: function( index, goingForward ) {
30336 index = this._findNextTab( index, goingForward );
30337 this.tabs.eq( index ).trigger( "focus" );
30338 return index;
30339 },
30340
30341 _setOption: function( key, value ) {
30342 if ( key === "active" ) {
30343
30344 // _activate() will handle invalid values and update this.options
30345 this._activate( value );
30346 return;
30347 }
30348
30349 this._super( key, value );
30350
30351 if ( key === "collapsible" ) {
30352 this._toggleClass( "ui-tabs-collapsible", null, value );
30353
30354 // Setting collapsible: false while collapsed; open first panel
30355 if ( !value && this.options.active === false ) {
30356 this._activate( 0 );
30357 }
30358 }
30359
30360 if ( key === "event" ) {
30361 this._setupEvents( value );
30362 }
30363
30364 if ( key === "heightStyle" ) {
30365 this._setupHeightStyle( value );
30366 }
30367 },
30368
30369 refresh: function() {
30370 var options = this.options,
30371 lis = this.tablist.children( ":has(a[href])" );
30372
30373 // Get disabled tabs from class attribute from HTML
30374 // this will get converted to a boolean if needed in _refresh()
30375 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
30376 return lis.index( tab );
30377 } );
30378
30379 this._processTabs();
30380
30381 // Was collapsed or no tabs
30382 if ( options.active === false || !this.anchors.length ) {
30383 options.active = false;
30384 this.active = $();
30385
30386 // was active, but active tab is gone
30387 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
30388
30389 // all remaining tabs are disabled
30390 if ( this.tabs.length === options.disabled.length ) {
30391 options.active = false;
30392 this.active = $();
30393
30394 // activate previous tab
30395 } else {
30396 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
30397 }
30398
30399 // was active, active tab still exists
30400 } else {
30401
30402 // make sure active index is correct
30403 options.active = this.tabs.index( this.active );
30404 }
30405
30406 this._refresh();
30407 },
30408
30409 _refresh: function() {
30410 this._setOptionDisabled( this.options.disabled );
30411 this._setupEvents( this.options.event );
30412 this._setupHeightStyle( this.options.heightStyle );
30413
30414 this.tabs.not( this.active ).attr( {
30415 "aria-selected": "false",
30416 "aria-expanded": "false",
30417 tabIndex: -1
30418 } );
30419 this.panels.not( this._getPanelForTab( this.active ) )
30420 .hide()
30421 .attr( {
30422 "aria-hidden": "true"
30423 } );
30424
30425 // Make sure one tab is in the tab order
30426 if ( !this.active.length ) {
30427 this.tabs.eq( 0 ).attr( "tabIndex", 0 );
30428 } else {
30429 this.active
30430 .attr( {
30431 "aria-selected": "true",
30432 "aria-expanded": "true",
30433 tabIndex: 0
30434 } );
30435 this._addClass( this.active, "ui-tabs-active", "ui-state-active" );
30436 this._getPanelForTab( this.active )
30437 .show()
30438 .attr( {
30439 "aria-hidden": "false"
30440 } );
30441 }
30442 },
30443
30444 _processTabs: function() {
30445 var that = this,
30446 prevTabs = this.tabs,
30447 prevAnchors = this.anchors,
30448 prevPanels = this.panels;
30449
30450 this.tablist = this._getList().attr( "role", "tablist" );
30451 this._addClass( this.tablist, "ui-tabs-nav",
30452 "ui-helper-reset ui-helper-clearfix ui-widget-header" );
30453
30454 // Prevent users from focusing disabled tabs via click
30455 this.tablist
30456 .on( "mousedown" + this.eventNamespace, "> li", function( event ) {
30457 if ( $( this ).is( ".ui-state-disabled" ) ) {
30458 event.preventDefault();
30459 }
30460 } );
30461
30462 this.tabs = this.tablist.find( "> li:has(a[href])" )
30463 .attr( {
30464 role: "tab",
30465 tabIndex: -1
30466 } );
30467 this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" );
30468
30469 this.anchors = this.tabs.map( function() {
30470 return $( "a", this )[ 0 ];
30471 } )
30472 .attr( {
30473 tabIndex: -1
30474 } );
30475 this._addClass( this.anchors, "ui-tabs-anchor" );
30476
30477 this.panels = $();
30478
30479 this.anchors.each( function( i, anchor ) {
30480 var selector, panel, panelId,
30481 anchorId = $( anchor ).uniqueId().attr( "id" ),
30482 tab = $( anchor ).closest( "li" ),
30483 originalAriaControls = tab.attr( "aria-controls" );
30484
30485 // Inline tab
30486 if ( that._isLocal( anchor ) ) {
30487 selector = decodeURIComponent( anchor.hash );
30488 panelId = selector.substring( 1 );
30489 panel = that.element.find( "#" + CSS.escape( panelId ) );
30490
30491 // remote tab
30492 } else {
30493
30494 // If the tab doesn't already have aria-controls,
30495 // generate an id by using a throw-away element
30496 panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
30497 selector = "#" + panelId;
30498 panel = that.element.find( selector );
30499 if ( !panel.length ) {
30500 panel = that._createPanel( panelId );
30501 panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
30502 }
30503 panel.attr( "aria-live", "polite" );
30504 }
30505
30506 if ( panel.length ) {
30507 that.panels = that.panels.add( panel );
30508 }
30509 if ( originalAriaControls ) {
30510 tab.data( "ui-tabs-aria-controls", originalAriaControls );
30511 }
30512 tab.attr( {
30513 "aria-controls": panelId,
30514 "aria-labelledby": anchorId
30515 } );
30516 panel.attr( "aria-labelledby", anchorId );
30517 } );
30518
30519 this.panels.attr( "role", "tabpanel" );
30520 this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" );
30521
30522 // Avoid memory leaks (#10056)
30523 if ( prevTabs ) {
30524 this._off( prevTabs.not( this.tabs ) );
30525 this._off( prevAnchors.not( this.anchors ) );
30526 this._off( prevPanels.not( this.panels ) );
30527 }
30528 },
30529
30530 // Allow overriding how to find the list for rare usage scenarios (#7715)
30531 _getList: function() {
30532 return this.tablist || this.element.find( "ol, ul" ).eq( 0 );
30533 },
30534
30535 _createPanel: function( id ) {
30536 return $( "<div>" )
30537 .attr( "id", id )
30538 .data( "ui-tabs-destroy", true );
30539 },
30540
30541 _setOptionDisabled: function( disabled ) {
30542 var currentItem, li, i;
30543
30544 if ( Array.isArray( disabled ) ) {
30545 if ( !disabled.length ) {
30546 disabled = false;
30547 } else if ( disabled.length === this.anchors.length ) {
30548 disabled = true;
30549 }
30550 }
30551
30552 // Disable tabs
30553 for ( i = 0; ( li = this.tabs[ i ] ); i++ ) {
30554 currentItem = $( li );
30555 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
30556 currentItem.attr( "aria-disabled", "true" );
30557 this._addClass( currentItem, null, "ui-state-disabled" );
30558 } else {
30559 currentItem.removeAttr( "aria-disabled" );
30560 this._removeClass( currentItem, null, "ui-state-disabled" );
30561 }
30562 }
30563
30564 this.options.disabled = disabled;
30565
30566 this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null,
30567 disabled === true );
30568 },
30569
30570 _setupEvents: function( event ) {
30571 var events = {};
30572 if ( event ) {
30573 $.each( event.split( " " ), function( index, eventName ) {
30574 events[ eventName ] = "_eventHandler";
30575 } );
30576 }
30577
30578 this._off( this.anchors.add( this.tabs ).add( this.panels ) );
30579
30580 // Always prevent the default action, even when disabled
30581 this._on( true, this.anchors, {
30582 click: function( event ) {
30583 event.preventDefault();
30584 }
30585 } );
30586 this._on( this.anchors, events );
30587 this._on( this.tabs, { keydown: "_tabKeydown" } );
30588 this._on( this.panels, { keydown: "_panelKeydown" } );
30589
30590 this._focusable( this.tabs );
30591 this._hoverable( this.tabs );
30592 },
30593
30594 _setupHeightStyle: function( heightStyle ) {
30595 var maxHeight,
30596 parent = this.element.parent();
30597
30598 if ( heightStyle === "fill" ) {
30599 maxHeight = parent.height();
30600 maxHeight -= this.element.outerHeight() - this.element.height();
30601
30602 this.element.siblings( ":visible" ).each( function() {
30603 var elem = $( this ),
30604 position = elem.css( "position" );
30605
30606 if ( position === "absolute" || position === "fixed" ) {
30607 return;
30608 }
30609 maxHeight -= elem.outerHeight( true );
30610 } );
30611
30612 this.element.children().not( this.panels ).each( function() {
30613 maxHeight -= $( this ).outerHeight( true );
30614 } );
30615
30616 this.panels.each( function() {
30617 $( this ).height( Math.max( 0, maxHeight -
30618 $( this ).innerHeight() + $( this ).height() ) );
30619 } )
30620 .css( "overflow", "auto" );
30621 } else if ( heightStyle === "auto" ) {
30622 maxHeight = 0;
30623 this.panels.each( function() {
30624 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
30625 } ).height( maxHeight );
30626 }
30627 },
30628
30629 _eventHandler: function( event ) {
30630 var options = this.options,
30631 active = this.active,
30632 anchor = $( event.currentTarget ),
30633 tab = anchor.closest( "li" ),
30634 clickedIsActive = tab[ 0 ] === active[ 0 ],
30635 collapsing = clickedIsActive && options.collapsible,
30636 toShow = collapsing ? $() : this._getPanelForTab( tab ),
30637 toHide = !active.length ? $() : this._getPanelForTab( active ),
30638 eventData = {
30639 oldTab: active,
30640 oldPanel: toHide,
30641 newTab: collapsing ? $() : tab,
30642 newPanel: toShow
30643 };
30644
30645 event.preventDefault();
30646
30647 if ( tab.hasClass( "ui-state-disabled" ) ||
30648
30649 // tab is already loading
30650 tab.hasClass( "ui-tabs-loading" ) ||
30651
30652 // can't switch durning an animation
30653 this.running ||
30654
30655 // click on active header, but not collapsible
30656 ( clickedIsActive && !options.collapsible ) ||
30657
30658 // allow canceling activation
30659 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
30660 return;
30661 }
30662
30663 options.active = collapsing ? false : this.tabs.index( tab );
30664
30665 this.active = clickedIsActive ? $() : tab;
30666 if ( this.xhr ) {
30667 this.xhr.abort();
30668 }
30669
30670 if ( !toHide.length && !toShow.length ) {
30671 $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
30672 }
30673
30674 if ( toShow.length ) {
30675 this.load( this.tabs.index( tab ), event );
30676 }
30677 this._toggle( event, eventData );
30678 },
30679
30680 // Handles show/hide for selecting tabs
30681 _toggle: function( event, eventData ) {
30682 var that = this,
30683 toShow = eventData.newPanel,
30684 toHide = eventData.oldPanel;
30685
30686 this.running = true;
30687
30688 function complete() {
30689 that.running = false;
30690 that._trigger( "activate", event, eventData );
30691 }
30692
30693 function show() {
30694 that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" );
30695
30696 if ( toShow.length && that.options.show ) {
30697 that._show( toShow, that.options.show, complete );
30698 } else {
30699 toShow.show();
30700 complete();
30701 }
30702 }
30703
30704 // Start out by hiding, then showing, then completing
30705 if ( toHide.length && this.options.hide ) {
30706 this._hide( toHide, this.options.hide, function() {
30707 that._removeClass( eventData.oldTab.closest( "li" ),
30708 "ui-tabs-active", "ui-state-active" );
30709 show();
30710 } );
30711 } else {
30712 this._removeClass( eventData.oldTab.closest( "li" ),
30713 "ui-tabs-active", "ui-state-active" );
30714 toHide.hide();
30715 show();
30716 }
30717
30718 toHide.attr( "aria-hidden", "true" );
30719 eventData.oldTab.attr( {
30720 "aria-selected": "false",
30721 "aria-expanded": "false"
30722 } );
30723
30724 // If we're switching tabs, remove the old tab from the tab order.
30725 // If we're opening from collapsed state, remove the previous tab from the tab order.
30726 // If we're collapsing, then keep the collapsing tab in the tab order.
30727 if ( toShow.length && toHide.length ) {
30728 eventData.oldTab.attr( "tabIndex", -1 );
30729 } else if ( toShow.length ) {
30730 this.tabs.filter( function() {
30731 return $( this ).attr( "tabIndex" ) === 0;
30732 } )
30733 .attr( "tabIndex", -1 );
30734 }
30735
30736 toShow.attr( "aria-hidden", "false" );
30737 eventData.newTab.attr( {
30738 "aria-selected": "true",
30739 "aria-expanded": "true",
30740 tabIndex: 0
30741 } );
30742 },
30743
30744 _activate: function( index ) {
30745 var anchor,
30746 active = this._findActive( index );
30747
30748 // Trying to activate the already active panel
30749 if ( active[ 0 ] === this.active[ 0 ] ) {
30750 return;
30751 }
30752
30753 // Trying to collapse, simulate a click on the current active header
30754 if ( !active.length ) {
30755 active = this.active;
30756 }
30757
30758 anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
30759 this._eventHandler( {
30760 target: anchor,
30761 currentTarget: anchor,
30762 preventDefault: $.noop
30763 } );
30764 },
30765
30766 _findActive: function( index ) {
30767 return index === false ? $() : this.tabs.eq( index );
30768 },
30769
30770 _getIndex: function( index ) {
30771
30772 // meta-function to give users option to provide a href string instead of a numerical index.
30773 if ( typeof index === "string" ) {
30774 index = this.anchors.index( this.anchors.filter( "[href$='" +
30775 CSS.escape( index ) + "']" ) );
30776 }
30777
30778 return index;
30779 },
30780
30781 _destroy: function() {
30782 if ( this.xhr ) {
30783 this.xhr.abort();
30784 }
30785
30786 this.tablist
30787 .removeAttr( "role" )
30788 .off( this.eventNamespace );
30789
30790 this.anchors
30791 .removeAttr( "role tabIndex" )
30792 .removeUniqueId();
30793
30794 this.tabs.add( this.panels ).each( function() {
30795 if ( $.data( this, "ui-tabs-destroy" ) ) {
30796 $( this ).remove();
30797 } else {
30798 $( this ).removeAttr( "role tabIndex " +
30799 "aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" );
30800 }
30801 } );
30802
30803 this.tabs.each( function() {
30804 var li = $( this ),
30805 prev = li.data( "ui-tabs-aria-controls" );
30806 if ( prev ) {
30807 li
30808 .attr( "aria-controls", prev )
30809 .removeData( "ui-tabs-aria-controls" );
30810 } else {
30811 li.removeAttr( "aria-controls" );
30812 }
30813 } );
30814
30815 this.panels.show();
30816
30817 if ( this.options.heightStyle !== "content" ) {
30818 this.panels.css( "height", "" );
30819 }
30820 },
30821
30822 enable: function( index ) {
30823 var disabled = this.options.disabled;
30824 if ( disabled === false ) {
30825 return;
30826 }
30827
30828 if ( index === undefined ) {
30829 disabled = false;
30830 } else {
30831 index = this._getIndex( index );
30832 if ( Array.isArray( disabled ) ) {
30833 disabled = $.map( disabled, function( num ) {
30834 return num !== index ? num : null;
30835 } );
30836 } else {
30837 disabled = $.map( this.tabs, function( li, num ) {
30838 return num !== index ? num : null;
30839 } );
30840 }
30841 }
30842 this._setOptionDisabled( disabled );
30843 },
30844
30845 disable: function( index ) {
30846 var disabled = this.options.disabled;
30847 if ( disabled === true ) {
30848 return;
30849 }
30850
30851 if ( index === undefined ) {
30852 disabled = true;
30853 } else {
30854 index = this._getIndex( index );
30855 if ( $.inArray( index, disabled ) !== -1 ) {
30856 return;
30857 }
30858 if ( Array.isArray( disabled ) ) {
30859 disabled = $.merge( [ index ], disabled ).sort();
30860 } else {
30861 disabled = [ index ];
30862 }
30863 }
30864 this._setOptionDisabled( disabled );
30865 },
30866
30867 load: function( index, event ) {
30868 index = this._getIndex( index );
30869 var that = this,
30870 tab = this.tabs.eq( index ),
30871 anchor = tab.find( ".ui-tabs-anchor" ),
30872 panel = this._getPanelForTab( tab ),
30873 eventData = {
30874 tab: tab,
30875 panel: panel
30876 },
30877 complete = function( jqXHR, status ) {
30878 if ( status === "abort" ) {
30879 that.panels.stop( false, true );
30880 }
30881
30882 that._removeClass( tab, "ui-tabs-loading" );
30883 panel.removeAttr( "aria-busy" );
30884
30885 if ( jqXHR === that.xhr ) {
30886 delete that.xhr;
30887 }
30888 };
30889
30890 // Not remote
30891 if ( this._isLocal( anchor[ 0 ] ) ) {
30892 return;
30893 }
30894
30895 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
30896
30897 if ( this.xhr.statusText !== "canceled" ) {
30898 this._addClass( tab, "ui-tabs-loading" );
30899 panel.attr( "aria-busy", "true" );
30900
30901 this.xhr
30902 .done( function( response, status, jqXHR ) {
30903 panel.html( response );
30904 that._trigger( "load", event, eventData );
30905
30906 complete( jqXHR, status );
30907 } )
30908 .fail( function( jqXHR, status ) {
30909 complete( jqXHR, status );
30910 } );
30911 }
30912 },
30913
30914 _ajaxSettings: function( anchor, event, eventData ) {
30915 var that = this;
30916 return {
30917 url: anchor.attr( "href" ),
30918 beforeSend: function( jqXHR, settings ) {
30919 return that._trigger( "beforeLoad", event,
30920 $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
30921 }
30922 };
30923 },
30924
30925 _getPanelForTab: function( tab ) {
30926 var id = $( tab ).attr( "aria-controls" );
30927 return this.element.find( "#" + CSS.escape( id ) );
30928 }
30929} );
30930
30931// DEPRECATED
30932// TODO: Switch return back to widget declaration at top of file when this is removed
30933if ( $.uiBackCompat === true ) {
30934
30935 // Backcompat for ui-tab class (now ui-tabs-tab)
30936 $.widget( "ui.tabs", $.ui.tabs, {
30937 _processTabs: function() {
30938 this._superApply( arguments );
30939 this._addClass( this.tabs, "ui-tab" );
30940 }
30941 } );
30942}
30943
30944return $.ui.tabs;
30945
30946} );
30947
30948
30949
30950
30951
30952
30953/*!
30954 * jQuery UI Tooltip 1.14.1
30955 * https://jqueryui.com
30956 *
30957 * Copyright OpenJS Foundation and other contributors
30958 * Released under the MIT license.
30959 * https://jquery.org/license
30960 */
30961
30962//>>label: Tooltip
30963//>>group: Widgets
30964//>>description: Shows additional information for any element on hover or focus.
30965//>>docs: https://api.jqueryui.com/tooltip/
30966//>>demos: https://jqueryui.com/tooltip/
30967//>>css.structure: ../../themes/base/core.css
30968//>>css.structure: ../../themes/base/tooltip.css
30969//>>css.theme: ../../themes/base/theme.css
30970
30971( function( factory ) {
30972 "use strict";
30973
30974 if ( typeof define === "function" && define.amd ) {
30975
30976 // AMD. Register as an anonymous module.
30977 define( [
30978 "jquery",
30979 "../keycode",
30980 "../position",
30981 "../unique-id",
30982 "../version",
30983 "../widget"
30984 ], factory );
30985 } else {
30986
30987 // Browser globals
30988 factory( jQuery );
30989 }
30990} )( function( $ ) {
30991"use strict";
30992
30993$.widget( "ui.tooltip", {
30994 version: "1.14.1",
30995 options: {
30996 classes: {
30997 "ui-tooltip": "ui-corner-all ui-widget-shadow"
30998 },
30999 content: function() {
31000 var title = $( this ).attr( "title" );
31001
31002 // Escape title, since we're going from an attribute to raw HTML
31003 return $( "<a>" ).text( title ).html();
31004 },
31005 hide: true,
31006
31007 // Disabled elements have inconsistent behavior across browsers (#8661)
31008 items: "[title]:not([disabled])",
31009 position: {
31010 my: "left top+15",
31011 at: "left bottom",
31012 collision: "flipfit flip"
31013 },
31014 show: true,
31015 track: false,
31016
31017 // Callbacks
31018 close: null,
31019 open: null
31020 },
31021
31022 _addDescribedBy: function( elem, id ) {
31023 var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ );
31024 describedby.push( id );
31025 elem
31026 .data( "ui-tooltip-id", id )
31027 .attr( "aria-describedby", String.prototype.trim.call( describedby.join( " " ) ) );
31028 },
31029
31030 _removeDescribedBy: function( elem ) {
31031 var id = elem.data( "ui-tooltip-id" ),
31032 describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ),
31033 index = $.inArray( id, describedby );
31034
31035 if ( index !== -1 ) {
31036 describedby.splice( index, 1 );
31037 }
31038
31039 elem.removeData( "ui-tooltip-id" );
31040 describedby = String.prototype.trim.call( describedby.join( " " ) );
31041 if ( describedby ) {
31042 elem.attr( "aria-describedby", describedby );
31043 } else {
31044 elem.removeAttr( "aria-describedby" );
31045 }
31046 },
31047
31048 _create: function() {
31049 this._on( {
31050 mouseover: "open",
31051 focusin: "open"
31052 } );
31053
31054 // IDs of generated tooltips, needed for destroy
31055 this.tooltips = {};
31056
31057 // IDs of parent tooltips where we removed the title attribute
31058 this.parents = {};
31059
31060 // Append the aria-live region so tooltips announce correctly
31061 this.liveRegion = $( "<div>" )
31062 .attr( {
31063 role: "log",
31064 "aria-live": "assertive",
31065 "aria-relevant": "additions"
31066 } )
31067 .appendTo( this.document[ 0 ].body );
31068 this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
31069
31070 this.disabledTitles = $( [] );
31071 },
31072
31073 _setOption: function( key, value ) {
31074 var that = this;
31075
31076 this._super( key, value );
31077
31078 if ( key === "content" ) {
31079 $.each( this.tooltips, function( id, tooltipData ) {
31080 that._updateContent( tooltipData.element );
31081 } );
31082 }
31083 },
31084
31085 _setOptionDisabled: function( value ) {
31086 this[ value ? "_disable" : "_enable" ]();
31087 },
31088
31089 _disable: function() {
31090 var that = this;
31091
31092 // Close open tooltips
31093 $.each( this.tooltips, function( id, tooltipData ) {
31094 var event = $.Event( "blur" );
31095 event.target = event.currentTarget = tooltipData.element[ 0 ];
31096 that.close( event, true );
31097 } );
31098
31099 // Remove title attributes to prevent native tooltips
31100 this.disabledTitles = this.disabledTitles.add(
31101 this.element.find( this.options.items ).addBack()
31102 .filter( function() {
31103 var element = $( this );
31104 if ( element.is( "[title]" ) ) {
31105 return element
31106 .data( "ui-tooltip-title", element.attr( "title" ) )
31107 .removeAttr( "title" );
31108 }
31109 } )
31110 );
31111 },
31112
31113 _enable: function() {
31114
31115 // restore title attributes
31116 this.disabledTitles.each( function() {
31117 var element = $( this );
31118 if ( element.data( "ui-tooltip-title" ) ) {
31119 element.attr( "title", element.data( "ui-tooltip-title" ) );
31120 }
31121 } );
31122 this.disabledTitles = $( [] );
31123 },
31124
31125 open: function( event ) {
31126 var that = this,
31127 target = $( event ? event.target : this.element )
31128
31129 // we need closest here due to mouseover bubbling,
31130 // but always pointing at the same event target
31131 .closest( this.options.items );
31132
31133 // No element to show a tooltip for or the tooltip is already open
31134 if ( !target.length || target.data( "ui-tooltip-id" ) ) {
31135 return;
31136 }
31137
31138 if ( target.attr( "title" ) ) {
31139 target.data( "ui-tooltip-title", target.attr( "title" ) );
31140 }
31141
31142 target.data( "ui-tooltip-open", true );
31143
31144 // Kill parent tooltips, custom or native, for hover
31145 if ( event && event.type === "mouseover" ) {
31146 target.parents().each( function() {
31147 var parent = $( this ),
31148 blurEvent;
31149 if ( parent.data( "ui-tooltip-open" ) ) {
31150 blurEvent = $.Event( "blur" );
31151 blurEvent.target = blurEvent.currentTarget = this;
31152 that.close( blurEvent, true );
31153 }
31154 if ( parent.attr( "title" ) ) {
31155 parent.uniqueId();
31156 that.parents[ this.id ] = {
31157 element: this,
31158 title: parent.attr( "title" )
31159 };
31160 parent.attr( "title", "" );
31161 }
31162 } );
31163 }
31164
31165 this._registerCloseHandlers( event, target );
31166 this._updateContent( target, event );
31167 },
31168
31169 _updateContent: function( target, event ) {
31170 var content,
31171 contentOption = this.options.content,
31172 that = this,
31173 eventType = event ? event.type : null;
31174
31175 if ( typeof contentOption === "string" || contentOption.nodeType ||
31176 contentOption.jquery ) {
31177 return this._open( event, target, contentOption );
31178 }
31179
31180 content = contentOption.call( target[ 0 ], function( response ) {
31181
31182 // Ignore async response if tooltip was closed already
31183 if ( !target.data( "ui-tooltip-open" ) ) {
31184 return;
31185 }
31186
31187 // JQuery creates a special event for focusin when it doesn't
31188 // exist natively. To improve performance, the native event
31189 // object is reused and the type is changed. Therefore, we can't
31190 // rely on the type being correct after the event finished
31191 // bubbling, so we set it back to the previous value. (#8740)
31192 if ( event ) {
31193 event.type = eventType;
31194 }
31195 that._open( event, target, response );
31196 } );
31197 if ( content ) {
31198 this._open( event, target, content );
31199 }
31200 },
31201
31202 _open: function( event, target, content ) {
31203 var tooltipData, tooltip, delayedShow, a11yContent,
31204 positionOption = $.extend( {}, this.options.position );
31205
31206 if ( !content ) {
31207 return;
31208 }
31209
31210 // Content can be updated multiple times. If the tooltip already
31211 // exists, then just update the content and bail.
31212 tooltipData = this._find( target );
31213 if ( tooltipData ) {
31214 tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
31215 return;
31216 }
31217
31218 // If we have a title, clear it to prevent the native tooltip
31219 // we have to check first to avoid defining a title if none exists
31220 // (we don't want to cause an element to start matching [title])
31221 //
31222 // We use removeAttr only for key events, to allow IE to export the correct
31223 // accessible attributes. For mouse events, set to empty string to avoid
31224 // native tooltip showing up (happens only when removing inside mouseover).
31225 if ( target.is( "[title]" ) ) {
31226 if ( event && event.type === "mouseover" ) {
31227 target.attr( "title", "" );
31228 } else {
31229 target.removeAttr( "title" );
31230 }
31231 }
31232
31233 tooltipData = this._tooltip( target );
31234 tooltip = tooltipData.tooltip;
31235 this._addDescribedBy( target, tooltip.attr( "id" ) );
31236 tooltip.find( ".ui-tooltip-content" ).html( content );
31237
31238 // Support: Voiceover on OS X, JAWS on IE <= 9
31239 // JAWS announces deletions even when aria-relevant="additions"
31240 // Voiceover will sometimes re-read the entire log region's contents from the beginning
31241 this.liveRegion.children().hide();
31242 a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() );
31243 a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" );
31244 a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
31245 a11yContent.appendTo( this.liveRegion );
31246
31247 function position( event ) {
31248 positionOption.of = event;
31249 if ( tooltip.is( ":hidden" ) ) {
31250 return;
31251 }
31252 tooltip.position( positionOption );
31253 }
31254 if ( this.options.track && event && /^mouse/.test( event.type ) ) {
31255 this._on( this.document, {
31256 mousemove: position
31257 } );
31258
31259 // trigger once to override element-relative positioning
31260 position( event );
31261 } else {
31262 tooltip.position( $.extend( {
31263 of: target
31264 }, this.options.position ) );
31265 }
31266
31267 tooltip.hide();
31268
31269 this._show( tooltip, this.options.show );
31270
31271 // Handle tracking tooltips that are shown with a delay (#8644). As soon
31272 // as the tooltip is visible, position the tooltip using the most recent
31273 // event.
31274 // Adds the check to add the timers only when both delay and track options are set (#14682)
31275 if ( this.options.track && this.options.show && this.options.show.delay ) {
31276 delayedShow = this.delayedShow = setInterval( function() {
31277 if ( tooltip.is( ":visible" ) ) {
31278 position( positionOption.of );
31279 clearInterval( delayedShow );
31280 }
31281 }, 13 );
31282 }
31283
31284 this._trigger( "open", event, { tooltip: tooltip } );
31285 },
31286
31287 _registerCloseHandlers: function( event, target ) {
31288 var events = {
31289 keyup: function( event ) {
31290 if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
31291 var fakeEvent = $.Event( event );
31292 fakeEvent.currentTarget = target[ 0 ];
31293 this.close( fakeEvent, true );
31294 }
31295 }
31296 };
31297
31298 // Only bind remove handler for delegated targets. Non-delegated
31299 // tooltips will handle this in destroy.
31300 if ( target[ 0 ] !== this.element[ 0 ] ) {
31301 events.remove = function() {
31302 var targetElement = this._find( target );
31303 if ( targetElement ) {
31304 this._removeTooltip( targetElement.tooltip );
31305 }
31306 };
31307 }
31308
31309 if ( !event || event.type === "mouseover" ) {
31310 events.mouseleave = "close";
31311 }
31312 if ( !event || event.type === "focusin" ) {
31313 events.focusout = "close";
31314 }
31315 this._on( true, target, events );
31316 },
31317
31318 close: function( event ) {
31319 var tooltip,
31320 that = this,
31321 target = $( event ? event.currentTarget : this.element ),
31322 tooltipData = this._find( target );
31323
31324 // The tooltip may already be closed
31325 if ( !tooltipData ) {
31326
31327 // We set ui-tooltip-open immediately upon open (in open()), but only set the
31328 // additional data once there's actually content to show (in _open()). So even if the
31329 // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
31330 // the period between open() and _open().
31331 target.removeData( "ui-tooltip-open" );
31332 return;
31333 }
31334
31335 tooltip = tooltipData.tooltip;
31336
31337 // Disabling closes the tooltip, so we need to track when we're closing
31338 // to avoid an infinite loop in case the tooltip becomes disabled on close
31339 if ( tooltipData.closing ) {
31340 return;
31341 }
31342
31343 // Clear the interval for delayed tracking tooltips
31344 clearInterval( this.delayedShow );
31345
31346 // Only set title if we had one before (see comment in _open())
31347 // If the title attribute has changed since open(), don't restore
31348 if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
31349 target.attr( "title", target.data( "ui-tooltip-title" ) );
31350 }
31351
31352 this._removeDescribedBy( target );
31353
31354 tooltipData.hiding = true;
31355 tooltip.stop( true );
31356 this._hide( tooltip, this.options.hide, function() {
31357 that._removeTooltip( $( this ) );
31358 } );
31359
31360 target.removeData( "ui-tooltip-open" );
31361 this._off( target, "mouseleave focusout keyup" );
31362
31363 // Remove 'remove' binding only on delegated targets
31364 if ( target[ 0 ] !== this.element[ 0 ] ) {
31365 this._off( target, "remove" );
31366 }
31367 this._off( this.document, "mousemove" );
31368
31369 if ( event && event.type === "mouseleave" ) {
31370 $.each( this.parents, function( id, parent ) {
31371 $( parent.element ).attr( "title", parent.title );
31372 delete that.parents[ id ];
31373 } );
31374 }
31375
31376 tooltipData.closing = true;
31377 this._trigger( "close", event, { tooltip: tooltip } );
31378 if ( !tooltipData.hiding ) {
31379 tooltipData.closing = false;
31380 }
31381 },
31382
31383 _tooltip: function( element ) {
31384 var tooltip = $( "<div>" ).attr( "role", "tooltip" ),
31385 content = $( "<div>" ).appendTo( tooltip ),
31386 id = tooltip.uniqueId().attr( "id" );
31387
31388 this._addClass( content, "ui-tooltip-content" );
31389 this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" );
31390
31391 tooltip.appendTo( this._appendTo( element ) );
31392
31393 return this.tooltips[ id ] = {
31394 element: element,
31395 tooltip: tooltip
31396 };
31397 },
31398
31399 _find: function( target ) {
31400 var id = target.data( "ui-tooltip-id" );
31401 return id ? this.tooltips[ id ] : null;
31402 },
31403
31404 _removeTooltip: function( tooltip ) {
31405
31406 // Clear the interval for delayed tracking tooltips
31407 clearInterval( this.delayedShow );
31408
31409 tooltip.remove();
31410 delete this.tooltips[ tooltip.attr( "id" ) ];
31411 },
31412
31413 _appendTo: function( target ) {
31414 var element = target.closest( ".ui-front, dialog" );
31415
31416 if ( !element.length ) {
31417 element = this.document[ 0 ].body;
31418 }
31419
31420 return element;
31421 },
31422
31423 _destroy: function() {
31424 var that = this;
31425
31426 // Close open tooltips
31427 $.each( this.tooltips, function( id, tooltipData ) {
31428
31429 // Delegate to close method to handle common cleanup
31430 var event = $.Event( "blur" ),
31431 element = tooltipData.element;
31432 event.target = event.currentTarget = element[ 0 ];
31433 that.close( event, true );
31434
31435 // Remove immediately; destroying an open tooltip doesn't use the
31436 // hide animation
31437 $( "#" + id ).remove();
31438
31439 // Restore the title
31440 if ( element.data( "ui-tooltip-title" ) ) {
31441
31442 // If the title attribute has changed since open(), don't restore
31443 if ( !element.attr( "title" ) ) {
31444 element.attr( "title", element.data( "ui-tooltip-title" ) );
31445 }
31446 element.removeData( "ui-tooltip-title" );
31447 }
31448 } );
31449 this.liveRegion.remove();
31450 }
31451} );
31452
31453// DEPRECATED
31454// TODO: Switch return back to widget declaration at top of file when this is removed
31455if ( $.uiBackCompat === true ) {
31456
31457 // Backcompat for tooltipClass option
31458 $.widget( "ui.tooltip", $.ui.tooltip, {
31459 options: {
31460 tooltipClass: null
31461 },
31462 _tooltip: function() {
31463 var tooltipData = this._superApply( arguments );
31464 if ( this.options.tooltipClass ) {
31465 tooltipData.tooltip.addClass( this.options.tooltipClass );
31466 }
31467 return tooltipData;
31468 }
31469 } );
31470}
31471
31472return $.ui.tooltip;
31473
31474} );
31475
31476
31477
31478
31479
31480
31481
31482
31483
31484
31485
31486
31487
31488
31489
31490
31491
31492
31493
31494
31495
31496
31497
31498
31499
31500
31501
31502
31503
31504
31505
31506
31507
31508
31509
31510
31511
31512
31513
31514
31515
31516
31517
31518
31519
31520
31521
31522
31523
31524
31525
31526
31527/*
31528(c) Copyrights 2007 - 2008
31529
31530Original idea by by Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
31531
31532jQuery Plugin by Tzury Bar Yochay
31533tzury.by@gmail.com
31534http://evalinux.wordpress.com
31535http://facebook.com/profile.php?id=513676303
31536
31537Project's sites:
31538http://code.google.com/p/js-hotkeys/
31539http://github.com/tzuryby/hotkeys/tree/master
31540
31541License: same as jQuery license.
31542
31543USAGE:
31544 // simple usage
31545 $(document).bind('keydown', 'Ctrl+c', function(){ alert('copy anyone?');});
31546
31547 // special options such as disableInIput
31548 $(document).bind('keydown', {combi:'Ctrl+x', disableInInput: true} , function() {});
31549
31550Note:
31551 This plugin wraps the following jQuery methods: $.fn.find, $.fn.bind and $.fn.unbind
31552*/
31553
31554(function (jQuery){
31555 // keep reference to the original $.fn.bind, $.fn.unbind and $.fn.find
31556 jQuery.fn.__bind__ = jQuery.fn.bind;
31557 jQuery.fn.__unbind__ = jQuery.fn.unbind;
31558 jQuery.fn.__find__ = jQuery.fn.find;
31559
31560 var hotkeys = {
31561 version: '0.7.9',
31562 override: /keypress|keydown|keyup/g,
31563 triggersMap: {},
31564
31565 specialKeys: { 27: 'esc', 9: 'tab', 32:'space', 13: 'return', 8:'backspace', 145: 'scroll',
31566 20: 'capslock', 144: 'numlock', 19:'pause', 45:'insert', 36:'home', 46:'del',
31567 35:'end', 33: 'pageup', 34:'pagedown', 37:'left', 38:'up', 39:'right',40:'down',
31568 109: '-',
31569 112:'f1',113:'f2', 114:'f3', 115:'f4', 116:'f5', 117:'f6', 118:'f7', 119:'f8',
31570 120:'f9', 121:'f10', 122:'f11', 123:'f12', 191: '/'},
31571
31572 shiftNums: { "`":"~", "1":"!", "2":"@", "3":"#", "4":"$", "5":"%", "6":"^", "7":"&",
31573 "8":"*", "9":"(", "0":")", "-":"_", "=":"+", ";":":", "'":"\"", ",":"<",
31574 ".":">", "/":"?", "\\":"|" },
31575
31576 newTrigger: function (type, combi, callback) {
31577 // i.e. {'keyup': {'ctrl': {cb: callback, disableInInput: false}}}
31578 var result = {};
31579 result[type] = {};
31580 result[type][combi] = {cb: callback, disableInInput: false};
31581 return result;
31582 }
31583 };
31584 // add firefox num pad char codes
31585 //if (jQuery.browser.mozilla){
31586 // add num pad char codes
31587 hotkeys.specialKeys = jQuery.extend(hotkeys.specialKeys, { 96: '0', 97:'1', 98: '2', 99:
31588 '3', 100: '4', 101: '5', 102: '6', 103: '7', 104: '8', 105: '9', 106: '*',
31589 107: '+', 109: '-', 110: '.', 111 : '/'
31590 });
31591 //}
31592
31593 // a wrapper around of $.fn.find
31594 // see more at: http://groups.google.com/group/jquery-en/browse_thread/thread/18f9825e8d22f18d
31595 jQuery.fn.find = function( selector ) {
31596 this.query = selector;
31597 return jQuery.fn.__find__.apply(this, arguments);
31598 };
31599
31600 jQuery.fn.unbind = function (type, combi, fn){
31601 if (jQuery.isFunction(combi)){
31602 fn = combi;
31603 combi = null;
31604 }
31605 if (combi && typeof combi === 'string'){
31606 var selectorId = ((this.prevObject && this.prevObject.query) || (this[0].id && this[0].id) || this[0]).toString();
31607 var hkTypes = type.split(' ');
31608 for (var x=0; x<hkTypes.length; x++){
31609 delete hotkeys.triggersMap[selectorId][hkTypes[x]][combi];
31610 }
31611 }
31612 // call jQuery original unbind
31613 return this.__unbind__(type, fn);
31614 };
31615
31616 jQuery.fn.bind = function(type, data, fn){
31617 // grab keyup,keydown,keypress
31618 var handle = type.match(hotkeys.override);
31619
31620 if (jQuery.isFunction(data) || !handle){
31621 // call jQuery.bind only
31622 return this.__bind__(type, data, fn);
31623 }
31624 else{
31625 // split the job
31626 var result = null,
31627 // pass the rest to the original $.fn.bind
31628 pass2jq = jQuery.trim(type.replace(hotkeys.override, ''));
31629
31630 // see if there are other types, pass them to the original $.fn.bind
31631 if (pass2jq){
31632 result = this.__bind__(pass2jq, data, fn);
31633 }
31634
31635 if (typeof data === "string"){
31636 data = {'combi': data};
31637 }
31638 if(data.combi){
31639 for (var x=0; x < handle.length; x++){
31640 var eventType = handle[x];
31641 var combi = data.combi.toLowerCase(),
31642 trigger = hotkeys.newTrigger(eventType, combi, fn),
31643 selectorId = ((this.prevObject && this.prevObject.query) || (this[0].id && this[0].id) || this[0]).toString();
31644
31645 //trigger[eventType][combi].propagate = data.propagate;
31646 trigger[eventType][combi].disableInInput = data.disableInInput;
31647
31648 // first time selector is bounded
31649 if (!hotkeys.triggersMap[selectorId]) {
31650 hotkeys.triggersMap[selectorId] = trigger;
31651 }
31652 // first time selector is bounded with this type
31653 else if (!hotkeys.triggersMap[selectorId][eventType]) {
31654 hotkeys.triggersMap[selectorId][eventType] = trigger[eventType];
31655 }
31656 // make trigger point as array so more than one handler can be bound
31657 var mapPoint = hotkeys.triggersMap[selectorId][eventType][combi];
31658 if (!mapPoint){
31659 hotkeys.triggersMap[selectorId][eventType][combi] = [trigger[eventType][combi]];
31660 }
31661 else if (mapPoint.constructor !== Array){
31662 hotkeys.triggersMap[selectorId][eventType][combi] = [mapPoint];
31663 }
31664 else {
31665 hotkeys.triggersMap[selectorId][eventType][combi][mapPoint.length] = trigger[eventType][combi];
31666 }
31667
31668 // add attribute and call $.event.add per matched element
31669 this.each(function(){
31670 // jQuery wrapper for the current element
31671 var jqElem = jQuery(this);
31672
31673 // element already associated with another collection
31674 if (jqElem.attr('hkId') && jqElem.attr('hkId') !== selectorId){
31675 selectorId = jqElem.attr('hkId') + ";" + selectorId;
31676 }
31677 jqElem.attr('hkId', selectorId);
31678 });
31679 result = this.__bind__(handle.join(' '), data, hotkeys.handler)
31680 }
31681 }
31682 return result;
31683 }
31684 };
31685 // work-around for opera and safari where (sometimes) the target is the element which was last
31686 // clicked with the mouse and not the document event it would make sense to get the document
31687 hotkeys.findElement = function (elem){
31688 if (!jQuery(elem).attr('hkId')){
31689 if (jQuery.browser.opera || jQuery.browser.safari){
31690 while (!jQuery(elem).attr('hkId') && elem.parentNode){
31691 elem = elem.parentNode;
31692 }
31693 }
31694 }
31695 return elem;
31696 };
31697 // the event handler
31698 hotkeys.handler = function(event) {
31699 var target = hotkeys.findElement(event.currentTarget),
31700 jTarget = jQuery(target),
31701 ids = jTarget.attr('hkId');
31702
31703 if(ids){
31704 ids = ids.split(';');
31705 var code = event.which,
31706 type = event.type,
31707 special = hotkeys.specialKeys[code],
31708 // prevent f5 overlapping with 't' (or f4 with 's', etc.)
31709 character = !special && String.fromCharCode(code).toLowerCase(),
31710 shift = event.shiftKey,
31711 ctrl = event.ctrlKey,
31712 // patch for jquery 1.2.5 && 1.2.6 see more at:
31713 // http://groups.google.com/group/jquery-en/browse_thread/thread/83e10b3bb1f1c32b
31714 alt = event.altKey || event.originalEvent.altKey,
31715 mapPoint = null;
31716
31717 for (var x=0; x < ids.length; x++){
31718 if (hotkeys.triggersMap[ids[x]][type]){
31719 mapPoint = hotkeys.triggersMap[ids[x]][type];
31720 break;
31721 }
31722 }
31723
31724 //find by: id.type.combi.options
31725 if (mapPoint){
31726 var trigger;
31727 // event type is associated with the hkId
31728 if(!shift && !ctrl && !alt) { // No Modifiers
31729 trigger = mapPoint[special] || (character && mapPoint[character]);
31730 }
31731 else{
31732 // check combinations (alt|ctrl|shift+anything)
31733 var modif = '';
31734 if(alt) modif +='alt+';
31735 if(ctrl) modif+= 'ctrl+';
31736 if(shift) modif += 'shift+';
31737 // modifiers + special keys or modifiers + character or modifiers + shift character or just shift character
31738 trigger = mapPoint[modif+special];
31739 if (!trigger){
31740 if (character){
31741 trigger = mapPoint[modif+character]
31742 || mapPoint[modif+hotkeys.shiftNums[character]]
31743 // '$' can be triggered as 'Shift+4' or 'Shift+$' or just '$'
31744 || (modif === 'shift+' && mapPoint[hotkeys.shiftNums[character]]);
31745 }
31746 }
31747 }
31748 if (trigger){
31749 var result = false;
31750 for (var x=0; x < trigger.length; x++){
31751 if(trigger[x].disableInInput){
31752 // double check event.currentTarget and event.target
31753 var elem = jQuery(event.target);
31754 if (jTarget.is("input") || jTarget.is("textarea") || jTarget.is("select")
31755 || elem.is("input") || elem.is("textarea") || elem.is("select")) {
31756 return true;
31757 }
31758 }
31759 // call the registered callback function
31760 result = result || trigger[x].cb.apply(this, [event]);
31761 }
31762 return result;
31763 }
31764 }
31765 }
31766 };
31767 // place it under window so it can be extended and overridden by others
31768 window.hotkeys = hotkeys;
31769 return jQuery;
31770})(jQuery);
31771
31772
31773
31774
31775
diff --git a/public/assets/admin_bundle-e15d8265faa7d827f0b57416f9aeec7a730d7f47ede994b76014444669fb2081.js.gz b/public/assets/admin_bundle-e15d8265faa7d827f0b57416f9aeec7a730d7f47ede994b76014444669fb2081.js.gz
new file mode 100644
index 0000000..e848b84
--- /dev/null
+++ b/public/assets/admin_bundle-e15d8265faa7d827f0b57416f9aeec7a730d7f47ede994b76014444669fb2081.js.gz
Binary files differ
diff --git a/public/assets/manifest-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.js b/public/assets/manifest-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/public/assets/manifest-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.js
diff --git a/public/assets/manifest-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.js.gz b/public/assets/manifest-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.js.gz
new file mode 100644
index 0000000..cad7e60
--- /dev/null
+++ b/public/assets/manifest-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.js.gz
Binary files differ
diff --git a/public/assets/trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js b/public/assets/trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js
new file mode 100644
index 0000000..1cd185f
--- /dev/null
+++ b/public/assets/trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js
@@ -0,0 +1,13720 @@
1/*
2Trix 2.1.10
3Copyright © 2024 37signals, LLC
4 */
5(function (global, factory) {
6 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
7 typeof define === 'function' && define.amd ? define(factory) :
8 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Trix = factory());
9})(this, (function () { 'use strict';
10
11 var name = "trix";
12 var version = "2.1.10";
13 var description = "A rich text editor for everyday writing";
14 var main = "dist/trix.umd.min.js";
15 var module = "dist/trix.esm.min.js";
16 var style = "dist/trix.css";
17 var files = [
18 "dist/*.css",
19 "dist/*.js",
20 "dist/*.map",
21 "src/{inspector,trix}/*.js"
22 ];
23 var repository = {
24 type: "git",
25 url: "git+https://github.com/basecamp/trix.git"
26 };
27 var keywords = [
28 "rich text",
29 "wysiwyg",
30 "editor"
31 ];
32 var author = "37signals, LLC";
33 var license = "MIT";
34 var bugs = {
35 url: "https://github.com/basecamp/trix/issues"
36 };
37 var homepage = "https://trix-editor.org/";
38 var devDependencies = {
39 "@babel/core": "^7.16.0",
40 "@babel/preset-env": "^7.16.4",
41 "@rollup/plugin-babel": "^5.3.0",
42 "@rollup/plugin-commonjs": "^22.0.2",
43 "@rollup/plugin-json": "^4.1.0",
44 "@rollup/plugin-node-resolve": "^13.3.0",
45 "@web/dev-server": "^0.1.34",
46 "babel-eslint": "^10.1.0",
47 concurrently: "^7.4.0",
48 eslint: "^7.32.0",
49 esm: "^3.2.25",
50 karma: "6.4.1",
51 "karma-chrome-launcher": "3.2.0",
52 "karma-qunit": "^4.1.2",
53 "karma-sauce-launcher": "^4.3.6",
54 "node-sass": "^7.0.1",
55 qunit: "2.19.1",
56 rangy: "^1.3.0",
57 rollup: "^2.56.3",
58 "rollup-plugin-includepaths": "^0.2.4",
59 "rollup-plugin-terser": "^7.0.2",
60 svgo: "^2.8.0",
61 webdriverio: "^7.19.5"
62 };
63 var resolutions = {
64 webdriverio: "^7.19.5"
65 };
66 var scripts = {
67 "build-css": "node-sass --functions=./assets/trix/stylesheets/functions assets/trix.scss dist/trix.css",
68 "build-js": "rollup -c",
69 "build-assets": "cp -f assets/*.html dist/",
70 build: "yarn run build-js && yarn run build-css && yarn run build-assets",
71 watch: "rollup -c -w",
72 lint: "eslint .",
73 pretest: "yarn run lint && yarn run build",
74 test: "karma start",
75 prerelease: "yarn version && yarn test",
76 release: "npm adduser && npm publish",
77 postrelease: "git push && git push --tags",
78 dev: "web-dev-server --app-index index.html --root-dir dist --node-resolve --open",
79 start: "yarn build-assets && concurrently --kill-others --names js,css,dev-server 'yarn watch' 'yarn build-css --watch' 'yarn dev'"
80 };
81 var dependencies = {
82 dompurify: "^3.2.3"
83 };
84 var _package = {
85 name: name,
86 version: version,
87 description: description,
88 main: main,
89 module: module,
90 style: style,
91 files: files,
92 repository: repository,
93 keywords: keywords,
94 author: author,
95 license: license,
96 bugs: bugs,
97 homepage: homepage,
98 devDependencies: devDependencies,
99 resolutions: resolutions,
100 scripts: scripts,
101 dependencies: dependencies
102 };
103
104 const attachmentSelector = "[data-trix-attachment]";
105 const attachments = {
106 preview: {
107 presentation: "gallery",
108 caption: {
109 name: true,
110 size: true
111 }
112 },
113 file: {
114 caption: {
115 size: true
116 }
117 }
118 };
119
120 const attributes = {
121 default: {
122 tagName: "div",
123 parse: false
124 },
125 quote: {
126 tagName: "blockquote",
127 nestable: true
128 },
129 heading1: {
130 tagName: "h1",
131 terminal: true,
132 breakOnReturn: true,
133 group: false
134 },
135 code: {
136 tagName: "pre",
137 terminal: true,
138 htmlAttributes: ["language"],
139 text: {
140 plaintext: true
141 }
142 },
143 bulletList: {
144 tagName: "ul",
145 parse: false
146 },
147 bullet: {
148 tagName: "li",
149 listAttribute: "bulletList",
150 group: false,
151 nestable: true,
152 test(element) {
153 return tagName$1(element.parentNode) === attributes[this.listAttribute].tagName;
154 }
155 },
156 numberList: {
157 tagName: "ol",
158 parse: false
159 },
160 number: {
161 tagName: "li",
162 listAttribute: "numberList",
163 group: false,
164 nestable: true,
165 test(element) {
166 return tagName$1(element.parentNode) === attributes[this.listAttribute].tagName;
167 }
168 },
169 attachmentGallery: {
170 tagName: "div",
171 exclusive: true,
172 terminal: true,
173 parse: false,
174 group: false
175 }
176 };
177 const tagName$1 = element => {
178 var _element$tagName;
179 return element === null || element === void 0 || (_element$tagName = element.tagName) === null || _element$tagName === void 0 ? void 0 : _element$tagName.toLowerCase();
180 };
181
182 const androidVersionMatch = navigator.userAgent.match(/android\s([0-9]+.*Chrome)/i);
183 const androidVersion = androidVersionMatch && parseInt(androidVersionMatch[1]);
184 var browser$1 = {
185 // Android emits composition events when moving the cursor through existing text
186 // Introduced in Chrome 65: https://bugs.chromium.org/p/chromium/issues/detail?id=764439#c9
187 composesExistingText: /Android.*Chrome/.test(navigator.userAgent),
188 // Android 13, especially on Samsung keyboards, emits extra compositionend and beforeinput events
189 // that can make the input handler lose the current selection or enter an infinite input -> render -> input
190 // loop.
191 recentAndroid: androidVersion && androidVersion > 12,
192 samsungAndroid: androidVersion && navigator.userAgent.match(/Android.*SM-/),
193 // IE 11 activates resizing handles on editable elements that have "layout"
194 forcesObjectResizing: /Trident.*rv:11/.test(navigator.userAgent),
195 // https://www.w3.org/TR/input-events-1/ + https://www.w3.org/TR/input-events-2/
196 supportsInputEvents: typeof InputEvent !== "undefined" && ["data", "getTargetRanges", "inputType"].every(prop => prop in InputEvent.prototype)
197 };
198
199 var css$3 = {
200 attachment: "attachment",
201 attachmentCaption: "attachment__caption",
202 attachmentCaptionEditor: "attachment__caption-editor",
203 attachmentMetadata: "attachment__metadata",
204 attachmentMetadataContainer: "attachment__metadata-container",
205 attachmentName: "attachment__name",
206 attachmentProgress: "attachment__progress",
207 attachmentSize: "attachment__size",
208 attachmentToolbar: "attachment__toolbar",
209 attachmentGallery: "attachment-gallery"
210 };
211
212 var lang$1 = {
213 attachFiles: "Attach Files",
214 bold: "Bold",
215 bullets: "Bullets",
216 byte: "Byte",
217 bytes: "Bytes",
218 captionPlaceholder: "Add a caption…",
219 code: "Code",
220 heading1: "Heading",
221 indent: "Increase Level",
222 italic: "Italic",
223 link: "Link",
224 numbers: "Numbers",
225 outdent: "Decrease Level",
226 quote: "Quote",
227 redo: "Redo",
228 remove: "Remove",
229 strike: "Strikethrough",
230 undo: "Undo",
231 unlink: "Unlink",
232 url: "URL",
233 urlPlaceholder: "Enter a URL…",
234 GB: "GB",
235 KB: "KB",
236 MB: "MB",
237 PB: "PB",
238 TB: "TB"
239 };
240
241 /* eslint-disable
242 no-case-declarations,
243 */
244 const sizes = [lang$1.bytes, lang$1.KB, lang$1.MB, lang$1.GB, lang$1.TB, lang$1.PB];
245 var file_size_formatting = {
246 prefix: "IEC",
247 precision: 2,
248 formatter(number) {
249 switch (number) {
250 case 0:
251 return "0 ".concat(lang$1.bytes);
252 case 1:
253 return "1 ".concat(lang$1.byte);
254 default:
255 let base;
256 if (this.prefix === "SI") {
257 base = 1000;
258 } else if (this.prefix === "IEC") {
259 base = 1024;
260 }
261 const exp = Math.floor(Math.log(number) / Math.log(base));
262 const humanSize = number / Math.pow(base, exp);
263 const string = humanSize.toFixed(this.precision);
264 const withoutInsignificantZeros = string.replace(/0*$/, "").replace(/\.$/, "");
265 return "".concat(withoutInsignificantZeros, " ").concat(sizes[exp]);
266 }
267 }
268 };
269
270 const ZERO_WIDTH_SPACE = "\uFEFF";
271 const NON_BREAKING_SPACE = "\u00A0";
272 const OBJECT_REPLACEMENT_CHARACTER = "\uFFFC";
273
274 const extend = function (properties) {
275 for (const key in properties) {
276 const value = properties[key];
277 this[key] = value;
278 }
279 return this;
280 };
281
282 const html$2 = document.documentElement;
283 const match = html$2.matches;
284 const handleEvent = function (eventName) {
285 let {
286 onElement,
287 matchingSelector,
288 withCallback,
289 inPhase,
290 preventDefault,
291 times
292 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
293 const element = onElement ? onElement : html$2;
294 const selector = matchingSelector;
295 const useCapture = inPhase === "capturing";
296 const handler = function (event) {
297 if (times != null && --times === 0) {
298 handler.destroy();
299 }
300 const target = findClosestElementFromNode(event.target, {
301 matchingSelector: selector
302 });
303 if (target != null) {
304 withCallback === null || withCallback === void 0 || withCallback.call(target, event, target);
305 if (preventDefault) {
306 event.preventDefault();
307 }
308 }
309 };
310 handler.destroy = () => element.removeEventListener(eventName, handler, useCapture);
311 element.addEventListener(eventName, handler, useCapture);
312 return handler;
313 };
314 const handleEventOnce = function (eventName) {
315 let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
316 options.times = 1;
317 return handleEvent(eventName, options);
318 };
319 const triggerEvent = function (eventName) {
320 let {
321 onElement,
322 bubbles,
323 cancelable,
324 attributes
325 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
326 const element = onElement != null ? onElement : html$2;
327 bubbles = bubbles !== false;
328 cancelable = cancelable !== false;
329 const event = document.createEvent("Events");
330 event.initEvent(eventName, bubbles, cancelable);
331 if (attributes != null) {
332 extend.call(event, attributes);
333 }
334 return element.dispatchEvent(event);
335 };
336 const elementMatchesSelector = function (element, selector) {
337 if ((element === null || element === void 0 ? void 0 : element.nodeType) === 1) {
338 return match.call(element, selector);
339 }
340 };
341 const findClosestElementFromNode = function (node) {
342 let {
343 matchingSelector,
344 untilNode
345 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
346 while (node && node.nodeType !== Node.ELEMENT_NODE) {
347 node = node.parentNode;
348 }
349 if (node == null) {
350 return;
351 }
352 if (matchingSelector != null) {
353 if (node.closest && untilNode == null) {
354 return node.closest(matchingSelector);
355 } else {
356 while (node && node !== untilNode) {
357 if (elementMatchesSelector(node, matchingSelector)) {
358 return node;
359 }
360 node = node.parentNode;
361 }
362 }
363 } else {
364 return node;
365 }
366 };
367 const findInnerElement = function (element) {
368 while ((_element = element) !== null && _element !== void 0 && _element.firstElementChild) {
369 var _element;
370 element = element.firstElementChild;
371 }
372 return element;
373 };
374 const innerElementIsActive = element => document.activeElement !== element && elementContainsNode(element, document.activeElement);
375 const elementContainsNode = function (element, node) {
376 if (!element || !node) {
377 return;
378 }
379 while (node) {
380 if (node === element) {
381 return true;
382 }
383 node = node.parentNode;
384 }
385 };
386 const findNodeFromContainerAndOffset = function (container, offset) {
387 if (!container) {
388 return;
389 }
390 if (container.nodeType === Node.TEXT_NODE) {
391 return container;
392 } else if (offset === 0) {
393 return container.firstChild != null ? container.firstChild : container;
394 } else {
395 return container.childNodes.item(offset - 1);
396 }
397 };
398 const findElementFromContainerAndOffset = function (container, offset) {
399 const node = findNodeFromContainerAndOffset(container, offset);
400 return findClosestElementFromNode(node);
401 };
402 const findChildIndexOfNode = function (node) {
403 var _node;
404 if (!((_node = node) !== null && _node !== void 0 && _node.parentNode)) {
405 return;
406 }
407 let childIndex = 0;
408 node = node.previousSibling;
409 while (node) {
410 childIndex++;
411 node = node.previousSibling;
412 }
413 return childIndex;
414 };
415 const removeNode = node => {
416 var _node$parentNode;
417 return node === null || node === void 0 || (_node$parentNode = node.parentNode) === null || _node$parentNode === void 0 ? void 0 : _node$parentNode.removeChild(node);
418 };
419 const walkTree = function (tree) {
420 let {
421 onlyNodesOfType,
422 usingFilter,
423 expandEntityReferences
424 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
425 const whatToShow = (() => {
426 switch (onlyNodesOfType) {
427 case "element":
428 return NodeFilter.SHOW_ELEMENT;
429 case "text":
430 return NodeFilter.SHOW_TEXT;
431 case "comment":
432 return NodeFilter.SHOW_COMMENT;
433 default:
434 return NodeFilter.SHOW_ALL;
435 }
436 })();
437 return document.createTreeWalker(tree, whatToShow, usingFilter != null ? usingFilter : null, expandEntityReferences === true);
438 };
439 const tagName = element => {
440 var _element$tagName;
441 return element === null || element === void 0 || (_element$tagName = element.tagName) === null || _element$tagName === void 0 ? void 0 : _element$tagName.toLowerCase();
442 };
443 const makeElement = function (tag) {
444 let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
445 let key, value;
446 if (typeof tag === "object") {
447 options = tag;
448 tag = options.tagName;
449 } else {
450 options = {
451 attributes: options
452 };
453 }
454 const element = document.createElement(tag);
455 if (options.editable != null) {
456 if (options.attributes == null) {
457 options.attributes = {};
458 }
459 options.attributes.contenteditable = options.editable;
460 }
461 if (options.attributes) {
462 for (key in options.attributes) {
463 value = options.attributes[key];
464 element.setAttribute(key, value);
465 }
466 }
467 if (options.style) {
468 for (key in options.style) {
469 value = options.style[key];
470 element.style[key] = value;
471 }
472 }
473 if (options.data) {
474 for (key in options.data) {
475 value = options.data[key];
476 element.dataset[key] = value;
477 }
478 }
479 if (options.className) {
480 options.className.split(" ").forEach(className => {
481 element.classList.add(className);
482 });
483 }
484 if (options.textContent) {
485 element.textContent = options.textContent;
486 }
487 if (options.childNodes) {
488 [].concat(options.childNodes).forEach(childNode => {
489 element.appendChild(childNode);
490 });
491 }
492 return element;
493 };
494 let blockTagNames = undefined;
495 const getBlockTagNames = function () {
496 if (blockTagNames != null) {
497 return blockTagNames;
498 }
499 blockTagNames = [];
500 for (const key in attributes) {
501 const attributes$1 = attributes[key];
502 if (attributes$1.tagName) {
503 blockTagNames.push(attributes$1.tagName);
504 }
505 }
506 return blockTagNames;
507 };
508 const nodeIsBlockContainer = node => nodeIsBlockStartComment(node === null || node === void 0 ? void 0 : node.firstChild);
509 const nodeProbablyIsBlockContainer = function (node) {
510 return getBlockTagNames().includes(tagName(node)) && !getBlockTagNames().includes(tagName(node.firstChild));
511 };
512 const nodeIsBlockStart = function (node) {
513 let {
514 strict
515 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
516 strict: true
517 };
518 if (strict) {
519 return nodeIsBlockStartComment(node);
520 } else {
521 return nodeIsBlockStartComment(node) || !nodeIsBlockStartComment(node.firstChild) && nodeProbablyIsBlockContainer(node);
522 }
523 };
524 const nodeIsBlockStartComment = node => nodeIsCommentNode(node) && (node === null || node === void 0 ? void 0 : node.data) === "block";
525 const nodeIsCommentNode = node => (node === null || node === void 0 ? void 0 : node.nodeType) === Node.COMMENT_NODE;
526 const nodeIsCursorTarget = function (node) {
527 let {
528 name
529 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
530 if (!node) {
531 return;
532 }
533 if (nodeIsTextNode(node)) {
534 if (node.data === ZERO_WIDTH_SPACE) {
535 if (name) {
536 return node.parentNode.dataset.trixCursorTarget === name;
537 } else {
538 return true;
539 }
540 }
541 } else {
542 return nodeIsCursorTarget(node.firstChild);
543 }
544 };
545 const nodeIsAttachmentElement = node => elementMatchesSelector(node, attachmentSelector);
546 const nodeIsEmptyTextNode = node => nodeIsTextNode(node) && (node === null || node === void 0 ? void 0 : node.data) === "";
547 const nodeIsTextNode = node => (node === null || node === void 0 ? void 0 : node.nodeType) === Node.TEXT_NODE;
548
549 const input = {
550 level2Enabled: true,
551 getLevel() {
552 if (this.level2Enabled && browser$1.supportsInputEvents) {
553 return 2;
554 } else {
555 return 0;
556 }
557 },
558 pickFiles(callback) {
559 const input = makeElement("input", {
560 type: "file",
561 multiple: true,
562 hidden: true,
563 id: this.fileInputId
564 });
565 input.addEventListener("change", () => {
566 callback(input.files);
567 removeNode(input);
568 });
569 removeNode(document.getElementById(this.fileInputId));
570 document.body.appendChild(input);
571 input.click();
572 }
573 };
574
575 var key_names = {
576 8: "backspace",
577 9: "tab",
578 13: "return",
579 27: "escape",
580 37: "left",
581 39: "right",
582 46: "delete",
583 68: "d",
584 72: "h",
585 79: "o"
586 };
587
588 var parser = {
589 removeBlankTableCells: false,
590 tableCellSeparator: " | ",
591 tableRowSeparator: "\n"
592 };
593
594 var text_attributes = {
595 bold: {
596 tagName: "strong",
597 inheritable: true,
598 parser(element) {
599 const style = window.getComputedStyle(element);
600 return style.fontWeight === "bold" || style.fontWeight >= 600;
601 }
602 },
603 italic: {
604 tagName: "em",
605 inheritable: true,
606 parser(element) {
607 const style = window.getComputedStyle(element);
608 return style.fontStyle === "italic";
609 }
610 },
611 href: {
612 groupTagName: "a",
613 parser(element) {
614 const matchingSelector = "a:not(".concat(attachmentSelector, ")");
615 const link = element.closest(matchingSelector);
616 if (link) {
617 return link.getAttribute("href");
618 }
619 }
620 },
621 strike: {
622 tagName: "del",
623 inheritable: true
624 },
625 frozen: {
626 style: {
627 backgroundColor: "highlight"
628 }
629 }
630 };
631
632 var toolbar = {
633 getDefaultHTML() {
634 return "<div class=\"trix-button-row\">\n <span class=\"trix-button-group trix-button-group--text-tools\" data-trix-button-group=\"text-tools\">\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-bold\" data-trix-attribute=\"bold\" data-trix-key=\"b\" title=\"".concat(lang$1.bold, "\" tabindex=\"-1\">").concat(lang$1.bold, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-italic\" data-trix-attribute=\"italic\" data-trix-key=\"i\" title=\"").concat(lang$1.italic, "\" tabindex=\"-1\">").concat(lang$1.italic, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-strike\" data-trix-attribute=\"strike\" title=\"").concat(lang$1.strike, "\" tabindex=\"-1\">").concat(lang$1.strike, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-link\" data-trix-attribute=\"href\" data-trix-action=\"link\" data-trix-key=\"k\" title=\"").concat(lang$1.link, "\" tabindex=\"-1\">").concat(lang$1.link, "</button>\n </span>\n\n <span class=\"trix-button-group trix-button-group--block-tools\" data-trix-button-group=\"block-tools\">\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-heading-1\" data-trix-attribute=\"heading1\" title=\"").concat(lang$1.heading1, "\" tabindex=\"-1\">").concat(lang$1.heading1, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-quote\" data-trix-attribute=\"quote\" title=\"").concat(lang$1.quote, "\" tabindex=\"-1\">").concat(lang$1.quote, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-code\" data-trix-attribute=\"code\" title=\"").concat(lang$1.code, "\" tabindex=\"-1\">").concat(lang$1.code, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-bullet-list\" data-trix-attribute=\"bullet\" title=\"").concat(lang$1.bullets, "\" tabindex=\"-1\">").concat(lang$1.bullets, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-number-list\" data-trix-attribute=\"number\" title=\"").concat(lang$1.numbers, "\" tabindex=\"-1\">").concat(lang$1.numbers, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-decrease-nesting-level\" data-trix-action=\"decreaseNestingLevel\" title=\"").concat(lang$1.outdent, "\" tabindex=\"-1\">").concat(lang$1.outdent, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-increase-nesting-level\" data-trix-action=\"increaseNestingLevel\" title=\"").concat(lang$1.indent, "\" tabindex=\"-1\">").concat(lang$1.indent, "</button>\n </span>\n\n <span class=\"trix-button-group trix-button-group--file-tools\" data-trix-button-group=\"file-tools\">\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-attach\" data-trix-action=\"attachFiles\" title=\"").concat(lang$1.attachFiles, "\" tabindex=\"-1\">").concat(lang$1.attachFiles, "</button>\n </span>\n\n <span class=\"trix-button-group-spacer\"></span>\n\n <span class=\"trix-button-group trix-button-group--history-tools\" data-trix-button-group=\"history-tools\">\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-undo\" data-trix-action=\"undo\" data-trix-key=\"z\" title=\"").concat(lang$1.undo, "\" tabindex=\"-1\">").concat(lang$1.undo, "</button>\n <button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-redo\" data-trix-action=\"redo\" data-trix-key=\"shift+z\" title=\"").concat(lang$1.redo, "\" tabindex=\"-1\">").concat(lang$1.redo, "</button>\n </span>\n </div>\n\n <div class=\"trix-dialogs\" data-trix-dialogs>\n <div class=\"trix-dialog trix-dialog--link\" data-trix-dialog=\"href\" data-trix-dialog-attribute=\"href\">\n <div class=\"trix-dialog__link-fields\">\n <input type=\"url\" name=\"href\" class=\"trix-input trix-input--dialog\" placeholder=\"").concat(lang$1.urlPlaceholder, "\" aria-label=\"").concat(lang$1.url, "\" required data-trix-input>\n <div class=\"trix-button-group\">\n <input type=\"button\" class=\"trix-button trix-button--dialog\" value=\"").concat(lang$1.link, "\" data-trix-method=\"setAttribute\">\n <input type=\"button\" class=\"trix-button trix-button--dialog\" value=\"").concat(lang$1.unlink, "\" data-trix-method=\"removeAttribute\">\n </div>\n </div>\n </div>\n </div>");
635 }
636 };
637
638 const undo = {
639 interval: 5000
640 };
641
642 var config = /*#__PURE__*/Object.freeze({
643 __proto__: null,
644 attachments: attachments,
645 blockAttributes: attributes,
646 browser: browser$1,
647 css: css$3,
648 fileSize: file_size_formatting,
649 input: input,
650 keyNames: key_names,
651 lang: lang$1,
652 parser: parser,
653 textAttributes: text_attributes,
654 toolbar: toolbar,
655 undo: undo
656 });
657
658 class BasicObject {
659 static proxyMethod(expression) {
660 const {
661 name,
662 toMethod,
663 toProperty,
664 optional
665 } = parseProxyMethodExpression(expression);
666 this.prototype[name] = function () {
667 let subject;
668 let object;
669 if (toMethod) {
670 if (optional) {
671 var _this$toMethod;
672 object = (_this$toMethod = this[toMethod]) === null || _this$toMethod === void 0 ? void 0 : _this$toMethod.call(this);
673 } else {
674 object = this[toMethod]();
675 }
676 } else if (toProperty) {
677 object = this[toProperty];
678 }
679 if (optional) {
680 var _object;
681 subject = (_object = object) === null || _object === void 0 ? void 0 : _object[name];
682 if (subject) {
683 return apply$1.call(subject, object, arguments);
684 }
685 } else {
686 subject = object[name];
687 return apply$1.call(subject, object, arguments);
688 }
689 };
690 }
691 }
692 const parseProxyMethodExpression = function (expression) {
693 const match = expression.match(proxyMethodExpressionPattern);
694 if (!match) {
695 throw new Error("can't parse @proxyMethod expression: ".concat(expression));
696 }
697 const args = {
698 name: match[4]
699 };
700 if (match[2] != null) {
701 args.toMethod = match[1];
702 } else {
703 args.toProperty = match[1];
704 }
705 if (match[3] != null) {
706 args.optional = true;
707 }
708 return args;
709 };
710 const {
711 apply: apply$1
712 } = Function.prototype;
713 const proxyMethodExpressionPattern = new RegExp("\
714^\
715(.+?)\
716(\\(\\))?\
717(\\?)?\
718\\.\
719(.+?)\
720$\
721");
722
723 var _Array$from, _$codePointAt$1, _$1, _String$fromCodePoint;
724 class UTF16String extends BasicObject {
725 static box() {
726 let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
727 if (value instanceof this) {
728 return value;
729 } else {
730 return this.fromUCS2String(value === null || value === void 0 ? void 0 : value.toString());
731 }
732 }
733 static fromUCS2String(ucs2String) {
734 return new this(ucs2String, ucs2decode(ucs2String));
735 }
736 static fromCodepoints(codepoints) {
737 return new this(ucs2encode(codepoints), codepoints);
738 }
739 constructor(ucs2String, codepoints) {
740 super(...arguments);
741 this.ucs2String = ucs2String;
742 this.codepoints = codepoints;
743 this.length = this.codepoints.length;
744 this.ucs2Length = this.ucs2String.length;
745 }
746 offsetToUCS2Offset(offset) {
747 return ucs2encode(this.codepoints.slice(0, Math.max(0, offset))).length;
748 }
749 offsetFromUCS2Offset(ucs2Offset) {
750 return ucs2decode(this.ucs2String.slice(0, Math.max(0, ucs2Offset))).length;
751 }
752 slice() {
753 return this.constructor.fromCodepoints(this.codepoints.slice(...arguments));
754 }
755 charAt(offset) {
756 return this.slice(offset, offset + 1);
757 }
758 isEqualTo(value) {
759 return this.constructor.box(value).ucs2String === this.ucs2String;
760 }
761 toJSON() {
762 return this.ucs2String;
763 }
764 getCacheKey() {
765 return this.ucs2String;
766 }
767 toString() {
768 return this.ucs2String;
769 }
770 }
771 const hasArrayFrom = ((_Array$from = Array.from) === null || _Array$from === void 0 ? void 0 : _Array$from.call(Array, "\ud83d\udc7c").length) === 1;
772 const hasStringCodePointAt$1 = ((_$codePointAt$1 = (_$1 = " ").codePointAt) === null || _$codePointAt$1 === void 0 ? void 0 : _$codePointAt$1.call(_$1, 0)) != null;
773 const hasStringFromCodePoint = ((_String$fromCodePoint = String.fromCodePoint) === null || _String$fromCodePoint === void 0 ? void 0 : _String$fromCodePoint.call(String, 32, 128124)) === " \ud83d\udc7c";
774
775 // UCS-2 conversion helpers ported from Mathias Bynens' Punycode.js:
776 // https://github.com/bestiejs/punycode.js#punycodeucs2
777
778 let ucs2decode, ucs2encode;
779
780 // Creates an array containing the numeric code points of each Unicode
781 // character in the string. While JavaScript uses UCS-2 internally,
782 // this function will convert a pair of surrogate halves (each of which
783 // UCS-2 exposes as separate characters) into a single code point,
784 // matching UTF-16.
785 if (hasArrayFrom && hasStringCodePointAt$1) {
786 ucs2decode = string => Array.from(string).map(char => char.codePointAt(0));
787 } else {
788 ucs2decode = function (string) {
789 const output = [];
790 let counter = 0;
791 const {
792 length
793 } = string;
794 while (counter < length) {
795 let value = string.charCodeAt(counter++);
796 if (0xd800 <= value && value <= 0xdbff && counter < length) {
797 // high surrogate, and there is a next character
798 const extra = string.charCodeAt(counter++);
799 if ((extra & 0xfc00) === 0xdc00) {
800 // low surrogate
801 value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000;
802 } else {
803 // unmatched surrogate; only append this code unit, in case the
804 // next code unit is the high surrogate of a surrogate pair
805 counter--;
806 }
807 }
808 output.push(value);
809 }
810 return output;
811 };
812 }
813
814 // Creates a string based on an array of numeric code points.
815 if (hasStringFromCodePoint) {
816 ucs2encode = array => String.fromCodePoint(...Array.from(array || []));
817 } else {
818 ucs2encode = function (array) {
819 const characters = (() => {
820 const result = [];
821 Array.from(array).forEach(value => {
822 let output = "";
823 if (value > 0xffff) {
824 value -= 0x10000;
825 output += String.fromCharCode(value >>> 10 & 0x3ff | 0xd800);
826 value = 0xdc00 | value & 0x3ff;
827 }
828 result.push(output + String.fromCharCode(value));
829 });
830 return result;
831 })();
832 return characters.join("");
833 };
834 }
835
836 let id$2 = 0;
837 class TrixObject extends BasicObject {
838 static fromJSONString(jsonString) {
839 return this.fromJSON(JSON.parse(jsonString));
840 }
841 constructor() {
842 super(...arguments);
843 this.id = ++id$2;
844 }
845 hasSameConstructorAs(object) {
846 return this.constructor === (object === null || object === void 0 ? void 0 : object.constructor);
847 }
848 isEqualTo(object) {
849 return this === object;
850 }
851 inspect() {
852 const parts = [];
853 const contents = this.contentsForInspection() || {};
854 for (const key in contents) {
855 const value = contents[key];
856 parts.push("".concat(key, "=").concat(value));
857 }
858 return "#<".concat(this.constructor.name, ":").concat(this.id).concat(parts.length ? " ".concat(parts.join(", ")) : "", ">");
859 }
860 contentsForInspection() {}
861 toJSONString() {
862 return JSON.stringify(this);
863 }
864 toUTF16String() {
865 return UTF16String.box(this);
866 }
867 getCacheKey() {
868 return this.id.toString();
869 }
870 }
871
872 /* eslint-disable
873 id-length,
874 */
875 const arraysAreEqual = function () {
876 let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
877 let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
878 if (a.length !== b.length) {
879 return false;
880 }
881 for (let index = 0; index < a.length; index++) {
882 const value = a[index];
883 if (value !== b[index]) {
884 return false;
885 }
886 }
887 return true;
888 };
889 const arrayStartsWith = function () {
890 let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
891 let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
892 return arraysAreEqual(a.slice(0, b.length), b);
893 };
894 const spliceArray = function (array) {
895 const result = array.slice(0);
896 for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
897 args[_key - 1] = arguments[_key];
898 }
899 result.splice(...args);
900 return result;
901 };
902 const summarizeArrayChange = function () {
903 let oldArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
904 let newArray = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
905 const added = [];
906 const removed = [];
907 const existingValues = new Set();
908 oldArray.forEach(value => {
909 existingValues.add(value);
910 });
911 const currentValues = new Set();
912 newArray.forEach(value => {
913 currentValues.add(value);
914 if (!existingValues.has(value)) {
915 added.push(value);
916 }
917 });
918 oldArray.forEach(value => {
919 if (!currentValues.has(value)) {
920 removed.push(value);
921 }
922 });
923 return {
924 added,
925 removed
926 };
927 };
928
929 // https://github.com/mathiasbynens/unicode-2.1.8/blob/master/Bidi_Class/Right_To_Left/regex.js
930 const RTL_PATTERN = /[\u05BE\u05C0\u05C3\u05D0-\u05EA\u05F0-\u05F4\u061B\u061F\u0621-\u063A\u0640-\u064A\u066D\u0671-\u06B7\u06BA-\u06BE\u06C0-\u06CE\u06D0-\u06D5\u06E5\u06E6\u200F\u202B\u202E\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE72\uFE74\uFE76-\uFEFC]/;
931 const getDirection = function () {
932 const input = makeElement("input", {
933 dir: "auto",
934 name: "x",
935 dirName: "x.dir"
936 });
937 const textArea = makeElement("textarea", {
938 dir: "auto",
939 name: "y",
940 dirName: "y.dir"
941 });
942 const form = makeElement("form");
943 form.appendChild(input);
944 form.appendChild(textArea);
945 const supportsDirName = function () {
946 try {
947 return new FormData(form).has(textArea.dirName);
948 } catch (error) {
949 return false;
950 }
951 }();
952 const supportsDirSelector = function () {
953 try {
954 return input.matches(":dir(ltr),:dir(rtl)");
955 } catch (error) {
956 return false;
957 }
958 }();
959 if (supportsDirName) {
960 return function (string) {
961 textArea.value = string;
962 return new FormData(form).get(textArea.dirName);
963 };
964 } else if (supportsDirSelector) {
965 return function (string) {
966 input.value = string;
967 if (input.matches(":dir(rtl)")) {
968 return "rtl";
969 } else {
970 return "ltr";
971 }
972 };
973 } else {
974 return function (string) {
975 const char = string.trim().charAt(0);
976 if (RTL_PATTERN.test(char)) {
977 return "rtl";
978 } else {
979 return "ltr";
980 }
981 };
982 }
983 }();
984
985 let allAttributeNames = null;
986 let blockAttributeNames = null;
987 let textAttributeNames = null;
988 let listAttributeNames = null;
989 const getAllAttributeNames = () => {
990 if (!allAttributeNames) {
991 allAttributeNames = getTextAttributeNames().concat(getBlockAttributeNames());
992 }
993 return allAttributeNames;
994 };
995 const getBlockConfig = attributeName => attributes[attributeName];
996 const getBlockAttributeNames = () => {
997 if (!blockAttributeNames) {
998 blockAttributeNames = Object.keys(attributes);
999 }
1000 return blockAttributeNames;
1001 };
1002 const getTextConfig = attributeName => text_attributes[attributeName];
1003 const getTextAttributeNames = () => {
1004 if (!textAttributeNames) {
1005 textAttributeNames = Object.keys(text_attributes);
1006 }
1007 return textAttributeNames;
1008 };
1009 const getListAttributeNames = () => {
1010 if (!listAttributeNames) {
1011 listAttributeNames = [];
1012 for (const key in attributes) {
1013 const {
1014 listAttribute
1015 } = attributes[key];
1016 if (listAttribute != null) {
1017 listAttributeNames.push(listAttribute);
1018 }
1019 }
1020 }
1021 return listAttributeNames;
1022 };
1023
1024 /* eslint-disable
1025 */
1026 const installDefaultCSSForTagName = function (tagName, defaultCSS) {
1027 const styleElement = insertStyleElementForTagName(tagName);
1028 styleElement.textContent = defaultCSS.replace(/%t/g, tagName);
1029 };
1030 const insertStyleElementForTagName = function (tagName) {
1031 const element = document.createElement("style");
1032 element.setAttribute("type", "text/css");
1033 element.setAttribute("data-tag-name", tagName.toLowerCase());
1034 const nonce = getCSPNonce();
1035 if (nonce) {
1036 element.setAttribute("nonce", nonce);
1037 }
1038 document.head.insertBefore(element, document.head.firstChild);
1039 return element;
1040 };
1041 const getCSPNonce = function () {
1042 const element = getMetaElement("trix-csp-nonce") || getMetaElement("csp-nonce");
1043 if (element) {
1044 const {
1045 nonce,
1046 content
1047 } = element;
1048 return nonce == "" ? content : nonce;
1049 }
1050 };
1051 const getMetaElement = name => document.head.querySelector("meta[name=".concat(name, "]"));
1052
1053 const testTransferData = {
1054 "application/x-trix-feature-detection": "test"
1055 };
1056 const dataTransferIsPlainText = function (dataTransfer) {
1057 const text = dataTransfer.getData("text/plain");
1058 const html = dataTransfer.getData("text/html");
1059 if (text && html) {
1060 const {
1061 body
1062 } = new DOMParser().parseFromString(html, "text/html");
1063 if (body.textContent === text) {
1064 return !body.querySelector("*");
1065 }
1066 } else {
1067 return text === null || text === void 0 ? void 0 : text.length;
1068 }
1069 };
1070 const dataTransferIsMsOfficePaste = _ref => {
1071 let {
1072 dataTransfer
1073 } = _ref;
1074 return dataTransfer.types.includes("Files") && dataTransfer.types.includes("text/html") && dataTransfer.getData("text/html").includes("urn:schemas-microsoft-com:office:office");
1075 };
1076 const dataTransferIsWritable = function (dataTransfer) {
1077 if (!(dataTransfer !== null && dataTransfer !== void 0 && dataTransfer.setData)) return false;
1078 for (const key in testTransferData) {
1079 const value = testTransferData[key];
1080 try {
1081 dataTransfer.setData(key, value);
1082 if (!dataTransfer.getData(key) === value) return false;
1083 } catch (error) {
1084 return false;
1085 }
1086 }
1087 return true;
1088 };
1089 const keyEventIsKeyboardCommand = function () {
1090 if (/Mac|^iP/.test(navigator.platform)) {
1091 return event => event.metaKey;
1092 } else {
1093 return event => event.ctrlKey;
1094 }
1095 }();
1096 function shouldRenderInmmediatelyToDealWithIOSDictation(inputEvent) {
1097 if (/iPhone|iPad/.test(navigator.userAgent)) {
1098 // Handle garbled content and duplicated newlines when using dictation on iOS 18+. Upon dictation completion, iOS sends
1099 // the list of insertText / insertParagraph events in a quick sequence. If we don't render
1100 // the editor synchronously, the internal range fails to update and results in garbled content or duplicated newlines.
1101 //
1102 // This workaround is necessary because iOS doesn't send composing events as expected while dictating:
1103 // https://bugs.webkit.org/show_bug.cgi?id=261764
1104 return !inputEvent.inputType || inputEvent.inputType === "insertParagraph";
1105 } else {
1106 return false;
1107 }
1108 }
1109
1110 const defer = fn => setTimeout(fn, 1);
1111
1112 /* eslint-disable
1113 id-length,
1114 */
1115 const copyObject = function () {
1116 let object = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1117 const result = {};
1118 for (const key in object) {
1119 const value = object[key];
1120 result[key] = value;
1121 }
1122 return result;
1123 };
1124 const objectsAreEqual = function () {
1125 let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1126 let b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1127 if (Object.keys(a).length !== Object.keys(b).length) {
1128 return false;
1129 }
1130 for (const key in a) {
1131 const value = a[key];
1132 if (value !== b[key]) {
1133 return false;
1134 }
1135 }
1136 return true;
1137 };
1138
1139 const normalizeRange = function (range) {
1140 if (range == null) return;
1141 if (!Array.isArray(range)) {
1142 range = [range, range];
1143 }
1144 return [copyValue(range[0]), copyValue(range[1] != null ? range[1] : range[0])];
1145 };
1146 const rangeIsCollapsed = function (range) {
1147 if (range == null) return;
1148 const [start, end] = normalizeRange(range);
1149 return rangeValuesAreEqual(start, end);
1150 };
1151 const rangesAreEqual = function (leftRange, rightRange) {
1152 if (leftRange == null || rightRange == null) return;
1153 const [leftStart, leftEnd] = normalizeRange(leftRange);
1154 const [rightStart, rightEnd] = normalizeRange(rightRange);
1155 return rangeValuesAreEqual(leftStart, rightStart) && rangeValuesAreEqual(leftEnd, rightEnd);
1156 };
1157 const copyValue = function (value) {
1158 if (typeof value === "number") {
1159 return value;
1160 } else {
1161 return copyObject(value);
1162 }
1163 };
1164 const rangeValuesAreEqual = function (left, right) {
1165 if (typeof left === "number") {
1166 return left === right;
1167 } else {
1168 return objectsAreEqual(left, right);
1169 }
1170 };
1171
1172 class SelectionChangeObserver extends BasicObject {
1173 constructor() {
1174 super(...arguments);
1175 this.update = this.update.bind(this);
1176 this.selectionManagers = [];
1177 }
1178 start() {
1179 if (!this.started) {
1180 this.started = true;
1181 document.addEventListener("selectionchange", this.update, true);
1182 }
1183 }
1184 stop() {
1185 if (this.started) {
1186 this.started = false;
1187 return document.removeEventListener("selectionchange", this.update, true);
1188 }
1189 }
1190 registerSelectionManager(selectionManager) {
1191 if (!this.selectionManagers.includes(selectionManager)) {
1192 this.selectionManagers.push(selectionManager);
1193 return this.start();
1194 }
1195 }
1196 unregisterSelectionManager(selectionManager) {
1197 this.selectionManagers = this.selectionManagers.filter(sm => sm !== selectionManager);
1198 if (this.selectionManagers.length === 0) {
1199 return this.stop();
1200 }
1201 }
1202 notifySelectionManagersOfSelectionChange() {
1203 return this.selectionManagers.map(selectionManager => selectionManager.selectionDidChange());
1204 }
1205 update() {
1206 this.notifySelectionManagersOfSelectionChange();
1207 }
1208 reset() {
1209 this.update();
1210 }
1211 }
1212 const selectionChangeObserver = new SelectionChangeObserver();
1213 const getDOMSelection = function () {
1214 const selection = window.getSelection();
1215 if (selection.rangeCount > 0) {
1216 return selection;
1217 }
1218 };
1219 const getDOMRange = function () {
1220 var _getDOMSelection;
1221 const domRange = (_getDOMSelection = getDOMSelection()) === null || _getDOMSelection === void 0 ? void 0 : _getDOMSelection.getRangeAt(0);
1222 if (domRange) {
1223 if (!domRangeIsPrivate(domRange)) {
1224 return domRange;
1225 }
1226 }
1227 };
1228 const setDOMRange = function (domRange) {
1229 const selection = window.getSelection();
1230 selection.removeAllRanges();
1231 selection.addRange(domRange);
1232 return selectionChangeObserver.update();
1233 };
1234
1235 // In Firefox, clicking certain <input> elements changes the selection to a
1236 // private element used to draw its UI. Attempting to access properties of those
1237 // elements throws an error.
1238 // https://bugzilla.mozilla.org/show_bug.cgi?id=208427
1239 const domRangeIsPrivate = domRange => nodeIsPrivate(domRange.startContainer) || nodeIsPrivate(domRange.endContainer);
1240 const nodeIsPrivate = node => !Object.getPrototypeOf(node);
1241
1242 /* eslint-disable
1243 id-length,
1244 no-useless-escape,
1245 */
1246 const normalizeSpaces = string => string.replace(new RegExp("".concat(ZERO_WIDTH_SPACE), "g"), "").replace(new RegExp("".concat(NON_BREAKING_SPACE), "g"), " ");
1247 const normalizeNewlines = string => string.replace(/\r\n?/g, "\n");
1248 const breakableWhitespacePattern = new RegExp("[^\\S".concat(NON_BREAKING_SPACE, "]"));
1249 const squishBreakableWhitespace = string => string
1250 // Replace all breakable whitespace characters with a space
1251 .replace(new RegExp("".concat(breakableWhitespacePattern.source), "g"), " ")
1252 // Replace two or more spaces with a single space
1253 .replace(/\ {2,}/g, " ");
1254 const summarizeStringChange = function (oldString, newString) {
1255 let added, removed;
1256 oldString = UTF16String.box(oldString);
1257 newString = UTF16String.box(newString);
1258 if (newString.length < oldString.length) {
1259 [removed, added] = utf16StringDifferences(oldString, newString);
1260 } else {
1261 [added, removed] = utf16StringDifferences(newString, oldString);
1262 }
1263 return {
1264 added,
1265 removed
1266 };
1267 };
1268 const utf16StringDifferences = function (a, b) {
1269 if (a.isEqualTo(b)) {
1270 return ["", ""];
1271 }
1272 const diffA = utf16StringDifference(a, b);
1273 const {
1274 length
1275 } = diffA.utf16String;
1276 let diffB;
1277 if (length) {
1278 const {
1279 offset
1280 } = diffA;
1281 const codepoints = a.codepoints.slice(0, offset).concat(a.codepoints.slice(offset + length));
1282 diffB = utf16StringDifference(b, UTF16String.fromCodepoints(codepoints));
1283 } else {
1284 diffB = utf16StringDifference(b, a);
1285 }
1286 return [diffA.utf16String.toString(), diffB.utf16String.toString()];
1287 };
1288 const utf16StringDifference = function (a, b) {
1289 let leftIndex = 0;
1290 let rightIndexA = a.length;
1291 let rightIndexB = b.length;
1292 while (leftIndex < rightIndexA && a.charAt(leftIndex).isEqualTo(b.charAt(leftIndex))) {
1293 leftIndex++;
1294 }
1295 while (rightIndexA > leftIndex + 1 && a.charAt(rightIndexA - 1).isEqualTo(b.charAt(rightIndexB - 1))) {
1296 rightIndexA--;
1297 rightIndexB--;
1298 }
1299 return {
1300 utf16String: a.slice(leftIndex, rightIndexA),
1301 offset: leftIndex
1302 };
1303 };
1304
1305 class Hash extends TrixObject {
1306 static fromCommonAttributesOfObjects() {
1307 let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
1308 if (!objects.length) {
1309 return new this();
1310 }
1311 let hash = box(objects[0]);
1312 let keys = hash.getKeys();
1313 objects.slice(1).forEach(object => {
1314 keys = hash.getKeysCommonToHash(box(object));
1315 hash = hash.slice(keys);
1316 });
1317 return hash;
1318 }
1319 static box(values) {
1320 return box(values);
1321 }
1322 constructor() {
1323 let values = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1324 super(...arguments);
1325 this.values = copy(values);
1326 }
1327 add(key, value) {
1328 return this.merge(object(key, value));
1329 }
1330 remove(key) {
1331 return new Hash(copy(this.values, key));
1332 }
1333 get(key) {
1334 return this.values[key];
1335 }
1336 has(key) {
1337 return key in this.values;
1338 }
1339 merge(values) {
1340 return new Hash(merge(this.values, unbox(values)));
1341 }
1342 slice(keys) {
1343 const values = {};
1344 Array.from(keys).forEach(key => {
1345 if (this.has(key)) {
1346 values[key] = this.values[key];
1347 }
1348 });
1349 return new Hash(values);
1350 }
1351 getKeys() {
1352 return Object.keys(this.values);
1353 }
1354 getKeysCommonToHash(hash) {
1355 hash = box(hash);
1356 return this.getKeys().filter(key => this.values[key] === hash.values[key]);
1357 }
1358 isEqualTo(values) {
1359 return arraysAreEqual(this.toArray(), box(values).toArray());
1360 }
1361 isEmpty() {
1362 return this.getKeys().length === 0;
1363 }
1364 toArray() {
1365 if (!this.array) {
1366 const result = [];
1367 for (const key in this.values) {
1368 const value = this.values[key];
1369 result.push(result.push(key, value));
1370 }
1371 this.array = result.slice(0);
1372 }
1373 return this.array;
1374 }
1375 toObject() {
1376 return copy(this.values);
1377 }
1378 toJSON() {
1379 return this.toObject();
1380 }
1381 contentsForInspection() {
1382 return {
1383 values: JSON.stringify(this.values)
1384 };
1385 }
1386 }
1387 const object = function (key, value) {
1388 const result = {};
1389 result[key] = value;
1390 return result;
1391 };
1392 const merge = function (object, values) {
1393 const result = copy(object);
1394 for (const key in values) {
1395 const value = values[key];
1396 result[key] = value;
1397 }
1398 return result;
1399 };
1400 const copy = function (object, keyToRemove) {
1401 const result = {};
1402 const sortedKeys = Object.keys(object).sort();
1403 sortedKeys.forEach(key => {
1404 if (key !== keyToRemove) {
1405 result[key] = object[key];
1406 }
1407 });
1408 return result;
1409 };
1410 const box = function (object) {
1411 if (object instanceof Hash) {
1412 return object;
1413 } else {
1414 return new Hash(object);
1415 }
1416 };
1417 const unbox = function (object) {
1418 if (object instanceof Hash) {
1419 return object.values;
1420 } else {
1421 return object;
1422 }
1423 };
1424
1425 class ObjectGroup {
1426 static groupObjects() {
1427 let ungroupedObjects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
1428 let {
1429 depth,
1430 asTree
1431 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1432 let group;
1433 if (asTree) {
1434 if (depth == null) {
1435 depth = 0;
1436 }
1437 }
1438 const objects = [];
1439 Array.from(ungroupedObjects).forEach(object => {
1440 var _object$canBeGrouped2;
1441 if (group) {
1442 var _object$canBeGrouped, _group$canBeGroupedWi, _group;
1443 if ((_object$canBeGrouped = object.canBeGrouped) !== null && _object$canBeGrouped !== void 0 && _object$canBeGrouped.call(object, depth) && (_group$canBeGroupedWi = (_group = group[group.length - 1]).canBeGroupedWith) !== null && _group$canBeGroupedWi !== void 0 && _group$canBeGroupedWi.call(_group, object, depth)) {
1444 group.push(object);
1445 return;
1446 } else {
1447 objects.push(new this(group, {
1448 depth,
1449 asTree
1450 }));
1451 group = null;
1452 }
1453 }
1454 if ((_object$canBeGrouped2 = object.canBeGrouped) !== null && _object$canBeGrouped2 !== void 0 && _object$canBeGrouped2.call(object, depth)) {
1455 group = [object];
1456 } else {
1457 objects.push(object);
1458 }
1459 });
1460 if (group) {
1461 objects.push(new this(group, {
1462 depth,
1463 asTree
1464 }));
1465 }
1466 return objects;
1467 }
1468 constructor() {
1469 let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
1470 let {
1471 depth,
1472 asTree
1473 } = arguments.length > 1 ? arguments[1] : undefined;
1474 this.objects = objects;
1475 if (asTree) {
1476 this.depth = depth;
1477 this.objects = this.constructor.groupObjects(this.objects, {
1478 asTree,
1479 depth: this.depth + 1
1480 });
1481 }
1482 }
1483 getObjects() {
1484 return this.objects;
1485 }
1486 getDepth() {
1487 return this.depth;
1488 }
1489 getCacheKey() {
1490 const keys = ["objectGroup"];
1491 Array.from(this.getObjects()).forEach(object => {
1492 keys.push(object.getCacheKey());
1493 });
1494 return keys.join("/");
1495 }
1496 }
1497
1498 class ObjectMap extends BasicObject {
1499 constructor() {
1500 let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
1501 super(...arguments);
1502 this.objects = {};
1503 Array.from(objects).forEach(object => {
1504 const hash = JSON.stringify(object);
1505 if (this.objects[hash] == null) {
1506 this.objects[hash] = object;
1507 }
1508 });
1509 }
1510 find(object) {
1511 const hash = JSON.stringify(object);
1512 return this.objects[hash];
1513 }
1514 }
1515
1516 class ElementStore {
1517 constructor(elements) {
1518 this.reset(elements);
1519 }
1520 add(element) {
1521 const key = getKey(element);
1522 this.elements[key] = element;
1523 }
1524 remove(element) {
1525 const key = getKey(element);
1526 const value = this.elements[key];
1527 if (value) {
1528 delete this.elements[key];
1529 return value;
1530 }
1531 }
1532 reset() {
1533 let elements = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
1534 this.elements = {};
1535 Array.from(elements).forEach(element => {
1536 this.add(element);
1537 });
1538 return elements;
1539 }
1540 }
1541 const getKey = element => element.dataset.trixStoreKey;
1542
1543 class Operation extends BasicObject {
1544 isPerforming() {
1545 return this.performing === true;
1546 }
1547 hasPerformed() {
1548 return this.performed === true;
1549 }
1550 hasSucceeded() {
1551 return this.performed && this.succeeded;
1552 }
1553 hasFailed() {
1554 return this.performed && !this.succeeded;
1555 }
1556 getPromise() {
1557 if (!this.promise) {
1558 this.promise = new Promise((resolve, reject) => {
1559 this.performing = true;
1560 return this.perform((succeeded, result) => {
1561 this.succeeded = succeeded;
1562 this.performing = false;
1563 this.performed = true;
1564 if (this.succeeded) {
1565 resolve(result);
1566 } else {
1567 reject(result);
1568 }
1569 });
1570 });
1571 }
1572 return this.promise;
1573 }
1574 perform(callback) {
1575 return callback(false);
1576 }
1577 release() {
1578 var _this$promise, _this$promise$cancel;
1579 (_this$promise = this.promise) === null || _this$promise === void 0 || (_this$promise$cancel = _this$promise.cancel) === null || _this$promise$cancel === void 0 || _this$promise$cancel.call(_this$promise);
1580 this.promise = null;
1581 this.performing = null;
1582 this.performed = null;
1583 this.succeeded = null;
1584 }
1585 }
1586 Operation.proxyMethod("getPromise().then");
1587 Operation.proxyMethod("getPromise().catch");
1588
1589 class ObjectView extends BasicObject {
1590 constructor(object) {
1591 let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1592 super(...arguments);
1593 this.object = object;
1594 this.options = options;
1595 this.childViews = [];
1596 this.rootView = this;
1597 }
1598 getNodes() {
1599 if (!this.nodes) {
1600 this.nodes = this.createNodes();
1601 }
1602 return this.nodes.map(node => node.cloneNode(true));
1603 }
1604 invalidate() {
1605 var _this$parentView;
1606 this.nodes = null;
1607 this.childViews = [];
1608 return (_this$parentView = this.parentView) === null || _this$parentView === void 0 ? void 0 : _this$parentView.invalidate();
1609 }
1610 invalidateViewForObject(object) {
1611 var _this$findViewForObje;
1612 return (_this$findViewForObje = this.findViewForObject(object)) === null || _this$findViewForObje === void 0 ? void 0 : _this$findViewForObje.invalidate();
1613 }
1614 findOrCreateCachedChildView(viewClass, object, options) {
1615 let view = this.getCachedViewForObject(object);
1616 if (view) {
1617 this.recordChildView(view);
1618 } else {
1619 view = this.createChildView(...arguments);
1620 this.cacheViewForObject(view, object);
1621 }
1622 return view;
1623 }
1624 createChildView(viewClass, object) {
1625 let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
1626 if (object instanceof ObjectGroup) {
1627 options.viewClass = viewClass;
1628 viewClass = ObjectGroupView;
1629 }
1630 const view = new viewClass(object, options);
1631 return this.recordChildView(view);
1632 }
1633 recordChildView(view) {
1634 view.parentView = this;
1635 view.rootView = this.rootView;
1636 this.childViews.push(view);
1637 return view;
1638 }
1639 getAllChildViews() {
1640 let views = [];
1641 this.childViews.forEach(childView => {
1642 views.push(childView);
1643 views = views.concat(childView.getAllChildViews());
1644 });
1645 return views;
1646 }
1647 findElement() {
1648 return this.findElementForObject(this.object);
1649 }
1650 findElementForObject(object) {
1651 const id = object === null || object === void 0 ? void 0 : object.id;
1652 if (id) {
1653 return this.rootView.element.querySelector("[data-trix-id='".concat(id, "']"));
1654 }
1655 }
1656 findViewForObject(object) {
1657 for (const view of this.getAllChildViews()) {
1658 if (view.object === object) {
1659 return view;
1660 }
1661 }
1662 }
1663 getViewCache() {
1664 if (this.rootView === this) {
1665 if (this.isViewCachingEnabled()) {
1666 if (!this.viewCache) {
1667 this.viewCache = {};
1668 }
1669 return this.viewCache;
1670 }
1671 } else {
1672 return this.rootView.getViewCache();
1673 }
1674 }
1675 isViewCachingEnabled() {
1676 return this.shouldCacheViews !== false;
1677 }
1678 enableViewCaching() {
1679 this.shouldCacheViews = true;
1680 }
1681 disableViewCaching() {
1682 this.shouldCacheViews = false;
1683 }
1684 getCachedViewForObject(object) {
1685 var _this$getViewCache;
1686 return (_this$getViewCache = this.getViewCache()) === null || _this$getViewCache === void 0 ? void 0 : _this$getViewCache[object.getCacheKey()];
1687 }
1688 cacheViewForObject(view, object) {
1689 const cache = this.getViewCache();
1690 if (cache) {
1691 cache[object.getCacheKey()] = view;
1692 }
1693 }
1694 garbageCollectCachedViews() {
1695 const cache = this.getViewCache();
1696 if (cache) {
1697 const views = this.getAllChildViews().concat(this);
1698 const objectKeys = views.map(view => view.object.getCacheKey());
1699 for (const key in cache) {
1700 if (!objectKeys.includes(key)) {
1701 delete cache[key];
1702 }
1703 }
1704 }
1705 }
1706 }
1707 class ObjectGroupView extends ObjectView {
1708 constructor() {
1709 super(...arguments);
1710 this.objectGroup = this.object;
1711 this.viewClass = this.options.viewClass;
1712 delete this.options.viewClass;
1713 }
1714 getChildViews() {
1715 if (!this.childViews.length) {
1716 Array.from(this.objectGroup.getObjects()).forEach(object => {
1717 this.findOrCreateCachedChildView(this.viewClass, object, this.options);
1718 });
1719 }
1720 return this.childViews;
1721 }
1722 createNodes() {
1723 const element = this.createContainerElement();
1724 this.getChildViews().forEach(view => {
1725 Array.from(view.getNodes()).forEach(node => {
1726 element.appendChild(node);
1727 });
1728 });
1729 return [element];
1730 }
1731 createContainerElement() {
1732 let depth = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.objectGroup.getDepth();
1733 return this.getChildViews()[0].createContainerElement(depth);
1734 }
1735 }
1736
1737 /*! @license DOMPurify 3.2.3 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.3/LICENSE */
1738
1739 const {
1740 entries,
1741 setPrototypeOf,
1742 isFrozen,
1743 getPrototypeOf,
1744 getOwnPropertyDescriptor
1745 } = Object;
1746 let {
1747 freeze,
1748 seal,
1749 create
1750 } = Object; // eslint-disable-line import/no-mutable-exports
1751 let {
1752 apply,
1753 construct
1754 } = typeof Reflect !== 'undefined' && Reflect;
1755 if (!freeze) {
1756 freeze = function freeze(x) {
1757 return x;
1758 };
1759 }
1760 if (!seal) {
1761 seal = function seal(x) {
1762 return x;
1763 };
1764 }
1765 if (!apply) {
1766 apply = function apply(fun, thisValue, args) {
1767 return fun.apply(thisValue, args);
1768 };
1769 }
1770 if (!construct) {
1771 construct = function construct(Func, args) {
1772 return new Func(...args);
1773 };
1774 }
1775 const arrayForEach = unapply(Array.prototype.forEach);
1776 const arrayPop = unapply(Array.prototype.pop);
1777 const arrayPush = unapply(Array.prototype.push);
1778 const stringToLowerCase = unapply(String.prototype.toLowerCase);
1779 const stringToString = unapply(String.prototype.toString);
1780 const stringMatch = unapply(String.prototype.match);
1781 const stringReplace = unapply(String.prototype.replace);
1782 const stringIndexOf = unapply(String.prototype.indexOf);
1783 const stringTrim = unapply(String.prototype.trim);
1784 const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
1785 const regExpTest = unapply(RegExp.prototype.test);
1786 const typeErrorCreate = unconstruct(TypeError);
1787 /**
1788 * Creates a new function that calls the given function with a specified thisArg and arguments.
1789 *
1790 * @param func - The function to be wrapped and called.
1791 * @returns A new function that calls the given function with a specified thisArg and arguments.
1792 */
1793 function unapply(func) {
1794 return function (thisArg) {
1795 for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
1796 args[_key - 1] = arguments[_key];
1797 }
1798 return apply(func, thisArg, args);
1799 };
1800 }
1801 /**
1802 * Creates a new function that constructs an instance of the given constructor function with the provided arguments.
1803 *
1804 * @param func - The constructor function to be wrapped and called.
1805 * @returns A new function that constructs an instance of the given constructor function with the provided arguments.
1806 */
1807 function unconstruct(func) {
1808 return function () {
1809 for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
1810 args[_key2] = arguments[_key2];
1811 }
1812 return construct(func, args);
1813 };
1814 }
1815 /**
1816 * Add properties to a lookup table
1817 *
1818 * @param set - The set to which elements will be added.
1819 * @param array - The array containing elements to be added to the set.
1820 * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set.
1821 * @returns The modified set with added elements.
1822 */
1823 function addToSet(set, array) {
1824 let transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase;
1825 if (setPrototypeOf) {
1826 // Make 'in' and truthy checks like Boolean(set.constructor)
1827 // independent of any properties defined on Object.prototype.
1828 // Prevent prototype setters from intercepting set as a this value.
1829 setPrototypeOf(set, null);
1830 }
1831 let l = array.length;
1832 while (l--) {
1833 let element = array[l];
1834 if (typeof element === 'string') {
1835 const lcElement = transformCaseFunc(element);
1836 if (lcElement !== element) {
1837 // Config presets (e.g. tags.js, attrs.js) are immutable.
1838 if (!isFrozen(array)) {
1839 array[l] = lcElement;
1840 }
1841 element = lcElement;
1842 }
1843 }
1844 set[element] = true;
1845 }
1846 return set;
1847 }
1848 /**
1849 * Clean up an array to harden against CSPP
1850 *
1851 * @param array - The array to be cleaned.
1852 * @returns The cleaned version of the array
1853 */
1854 function cleanArray(array) {
1855 for (let index = 0; index < array.length; index++) {
1856 const isPropertyExist = objectHasOwnProperty(array, index);
1857 if (!isPropertyExist) {
1858 array[index] = null;
1859 }
1860 }
1861 return array;
1862 }
1863 /**
1864 * Shallow clone an object
1865 *
1866 * @param object - The object to be cloned.
1867 * @returns A new object that copies the original.
1868 */
1869 function clone(object) {
1870 const newObject = create(null);
1871 for (const [property, value] of entries(object)) {
1872 const isPropertyExist = objectHasOwnProperty(object, property);
1873 if (isPropertyExist) {
1874 if (Array.isArray(value)) {
1875 newObject[property] = cleanArray(value);
1876 } else if (value && typeof value === 'object' && value.constructor === Object) {
1877 newObject[property] = clone(value);
1878 } else {
1879 newObject[property] = value;
1880 }
1881 }
1882 }
1883 return newObject;
1884 }
1885 /**
1886 * This method automatically checks if the prop is function or getter and behaves accordingly.
1887 *
1888 * @param object - The object to look up the getter function in its prototype chain.
1889 * @param prop - The property name for which to find the getter function.
1890 * @returns The getter function found in the prototype chain or a fallback function.
1891 */
1892 function lookupGetter(object, prop) {
1893 while (object !== null) {
1894 const desc = getOwnPropertyDescriptor(object, prop);
1895 if (desc) {
1896 if (desc.get) {
1897 return unapply(desc.get);
1898 }
1899 if (typeof desc.value === 'function') {
1900 return unapply(desc.value);
1901 }
1902 }
1903 object = getPrototypeOf(object);
1904 }
1905 function fallbackValue() {
1906 return null;
1907 }
1908 return fallbackValue;
1909 }
1910 const html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);
1911 const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);
1912 const svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
1913 // List of SVG elements that are disallowed by default.
1914 // We still need to know them so that we can do namespace
1915 // checks properly in case one wants to add them to
1916 // allow-list.
1917 const svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);
1918 const mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'mprescripts']);
1919 // Similarly to SVG, we want to know all MathML elements,
1920 // even those that we disallow by default.
1921 const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
1922 const text = freeze(['#text']);
1923 const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);
1924 const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
1925 const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
1926 const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
1927
1928 // eslint-disable-next-line unicorn/better-regex
1929 const MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
1930 const ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
1931 const TMPLIT_EXPR = seal(/\$\{[\w\W]*}/gm); // eslint-disable-line unicorn/better-regex
1932 const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape
1933 const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
1934 const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
1935 );
1936
1937 const IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
1938 const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
1939 );
1940
1941 const DOCTYPE_NAME = seal(/^html$/i);
1942 const CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
1943 var EXPRESSIONS = /*#__PURE__*/Object.freeze({
1944 __proto__: null,
1945 ARIA_ATTR: ARIA_ATTR,
1946 ATTR_WHITESPACE: ATTR_WHITESPACE,
1947 CUSTOM_ELEMENT: CUSTOM_ELEMENT,
1948 DATA_ATTR: DATA_ATTR,
1949 DOCTYPE_NAME: DOCTYPE_NAME,
1950 ERB_EXPR: ERB_EXPR,
1951 IS_ALLOWED_URI: IS_ALLOWED_URI,
1952 IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,
1953 MUSTACHE_EXPR: MUSTACHE_EXPR,
1954 TMPLIT_EXPR: TMPLIT_EXPR
1955 });
1956
1957 /* eslint-disable @typescript-eslint/indent */
1958 // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
1959 const NODE_TYPE = {
1960 element: 1,
1961 attribute: 2,
1962 text: 3,
1963 cdataSection: 4,
1964 entityReference: 5,
1965 // Deprecated
1966 entityNode: 6,
1967 // Deprecated
1968 progressingInstruction: 7,
1969 comment: 8,
1970 document: 9,
1971 documentType: 10,
1972 documentFragment: 11,
1973 notation: 12 // Deprecated
1974 };
1975
1976 const getGlobal = function getGlobal() {
1977 return typeof window === 'undefined' ? null : window;
1978 };
1979 /**
1980 * Creates a no-op policy for internal use only.
1981 * Don't export this function outside this module!
1982 * @param trustedTypes The policy factory.
1983 * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).
1984 * @return The policy created (or null, if Trusted Types
1985 * are not supported or creating the policy failed).
1986 */
1987 const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {
1988 if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
1989 return null;
1990 }
1991 // Allow the callers to control the unique policy name
1992 // by adding a data-tt-policy-suffix to the script element with the DOMPurify.
1993 // Policy creation with duplicate names throws in Trusted Types.
1994 let suffix = null;
1995 const ATTR_NAME = 'data-tt-policy-suffix';
1996 if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {
1997 suffix = purifyHostElement.getAttribute(ATTR_NAME);
1998 }
1999 const policyName = 'dompurify' + (suffix ? '#' + suffix : '');
2000 try {
2001 return trustedTypes.createPolicy(policyName, {
2002 createHTML(html) {
2003 return html;
2004 },
2005 createScriptURL(scriptUrl) {
2006 return scriptUrl;
2007 }
2008 });
2009 } catch (_) {
2010 // Policy creation failed (most likely another DOMPurify script has
2011 // already run). Skip creating the policy, as this will only cause errors
2012 // if TT are enforced.
2013 console.warn('TrustedTypes policy ' + policyName + ' could not be created.');
2014 return null;
2015 }
2016 };
2017 const _createHooksMap = function _createHooksMap() {
2018 return {
2019 afterSanitizeAttributes: [],
2020 afterSanitizeElements: [],
2021 afterSanitizeShadowDOM: [],
2022 beforeSanitizeAttributes: [],
2023 beforeSanitizeElements: [],
2024 beforeSanitizeShadowDOM: [],
2025 uponSanitizeAttribute: [],
2026 uponSanitizeElement: [],
2027 uponSanitizeShadowNode: []
2028 };
2029 };
2030 function createDOMPurify() {
2031 let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
2032 const DOMPurify = root => createDOMPurify(root);
2033 DOMPurify.version = '3.2.3';
2034 DOMPurify.removed = [];
2035 if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document) {
2036 // Not running in a browser, provide a factory function
2037 // so that you can pass your own Window
2038 DOMPurify.isSupported = false;
2039 return DOMPurify;
2040 }
2041 let {
2042 document
2043 } = window;
2044 const originalDocument = document;
2045 const currentScript = originalDocument.currentScript;
2046 const {
2047 DocumentFragment,
2048 HTMLTemplateElement,
2049 Node,
2050 Element,
2051 NodeFilter,
2052 NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,
2053 HTMLFormElement,
2054 DOMParser,
2055 trustedTypes
2056 } = window;
2057 const ElementPrototype = Element.prototype;
2058 const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
2059 const remove = lookupGetter(ElementPrototype, 'remove');
2060 const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
2061 const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
2062 const getParentNode = lookupGetter(ElementPrototype, 'parentNode');
2063 // As per issue #47, the web-components registry is inherited by a
2064 // new document created via createHTMLDocument. As per the spec
2065 // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
2066 // a new empty registry is used when creating a template contents owner
2067 // document, so we use that as our parent document to ensure nothing
2068 // is inherited.
2069 if (typeof HTMLTemplateElement === 'function') {
2070 const template = document.createElement('template');
2071 if (template.content && template.content.ownerDocument) {
2072 document = template.content.ownerDocument;
2073 }
2074 }
2075 let trustedTypesPolicy;
2076 let emptyHTML = '';
2077 const {
2078 implementation,
2079 createNodeIterator,
2080 createDocumentFragment,
2081 getElementsByTagName
2082 } = document;
2083 const {
2084 importNode
2085 } = originalDocument;
2086 let hooks = _createHooksMap();
2087 /**
2088 * Expose whether this browser supports running the full DOMPurify.
2089 */
2090 DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;
2091 const {
2092 MUSTACHE_EXPR,
2093 ERB_EXPR,
2094 TMPLIT_EXPR,
2095 DATA_ATTR,
2096 ARIA_ATTR,
2097 IS_SCRIPT_OR_DATA,
2098 ATTR_WHITESPACE,
2099 CUSTOM_ELEMENT
2100 } = EXPRESSIONS;
2101 let {
2102 IS_ALLOWED_URI: IS_ALLOWED_URI$1
2103 } = EXPRESSIONS;
2104 /**
2105 * We consider the elements and attributes below to be safe. Ideally
2106 * don't add any new ones but feel free to remove unwanted ones.
2107 */
2108 /* allowed element names */
2109 let ALLOWED_TAGS = null;
2110 const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);
2111 /* Allowed attribute names */
2112 let ALLOWED_ATTR = null;
2113 const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);
2114 /*
2115 * Configure how DOMPurify should handle custom elements and their attributes as well as customized built-in elements.
2116 * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)
2117 * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)
2118 * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.
2119 */
2120 let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {
2121 tagNameCheck: {
2122 writable: true,
2123 configurable: false,
2124 enumerable: true,
2125 value: null
2126 },
2127 attributeNameCheck: {
2128 writable: true,
2129 configurable: false,
2130 enumerable: true,
2131 value: null
2132 },
2133 allowCustomizedBuiltInElements: {
2134 writable: true,
2135 configurable: false,
2136 enumerable: true,
2137 value: false
2138 }
2139 }));
2140 /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
2141 let FORBID_TAGS = null;
2142 /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
2143 let FORBID_ATTR = null;
2144 /* Decide if ARIA attributes are okay */
2145 let ALLOW_ARIA_ATTR = true;
2146 /* Decide if custom data attributes are okay */
2147 let ALLOW_DATA_ATTR = true;
2148 /* Decide if unknown protocols are okay */
2149 let ALLOW_UNKNOWN_PROTOCOLS = false;
2150 /* Decide if self-closing tags in attributes are allowed.
2151 * Usually removed due to a mXSS issue in jQuery 3.0 */
2152 let ALLOW_SELF_CLOSE_IN_ATTR = true;
2153 /* Output should be safe for common template engines.
2154 * This means, DOMPurify removes data attributes, mustaches and ERB
2155 */
2156 let SAFE_FOR_TEMPLATES = false;
2157 /* Output should be safe even for XML used within HTML and alike.
2158 * This means, DOMPurify removes comments when containing risky content.
2159 */
2160 let SAFE_FOR_XML = true;
2161 /* Decide if document with <html>... should be returned */
2162 let WHOLE_DOCUMENT = false;
2163 /* Track whether config is already set on this instance of DOMPurify. */
2164 let SET_CONFIG = false;
2165 /* Decide if all elements (e.g. style, script) must be children of
2166 * document.body. By default, browsers might move them to document.head */
2167 let FORCE_BODY = false;
2168 /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html
2169 * string (or a TrustedHTML object if Trusted Types are supported).
2170 * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
2171 */
2172 let RETURN_DOM = false;
2173 /* Decide if a DOM `DocumentFragment` should be returned, instead of a html
2174 * string (or a TrustedHTML object if Trusted Types are supported) */
2175 let RETURN_DOM_FRAGMENT = false;
2176 /* Try to return a Trusted Type object instead of a string, return a string in
2177 * case Trusted Types are not supported */
2178 let RETURN_TRUSTED_TYPE = false;
2179 /* Output should be free from DOM clobbering attacks?
2180 * This sanitizes markups named with colliding, clobberable built-in DOM APIs.
2181 */
2182 let SANITIZE_DOM = true;
2183 /* Achieve full DOM Clobbering protection by isolating the namespace of named
2184 * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.
2185 *
2186 * HTML/DOM spec rules that enable DOM Clobbering:
2187 * - Named Access on Window (§7.3.3)
2188 * - DOM Tree Accessors (§3.1.5)
2189 * - Form Element Parent-Child Relations (§4.10.3)
2190 * - Iframe srcdoc / Nested WindowProxies (§4.8.5)
2191 * - HTMLCollection (§4.2.10.2)
2192 *
2193 * Namespace isolation is implemented by prefixing `id` and `name` attributes
2194 * with a constant string, i.e., `user-content-`
2195 */
2196 let SANITIZE_NAMED_PROPS = false;
2197 const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';
2198 /* Keep element content when removing element? */
2199 let KEEP_CONTENT = true;
2200 /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead
2201 * of importing it into a new Document and returning a sanitized copy */
2202 let IN_PLACE = false;
2203 /* Allow usage of profiles like html, svg and mathMl */
2204 let USE_PROFILES = {};
2205 /* Tags to ignore content of when KEEP_CONTENT is true */
2206 let FORBID_CONTENTS = null;
2207 const DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);
2208 /* Tags that are safe for data: URIs */
2209 let DATA_URI_TAGS = null;
2210 const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);
2211 /* Attributes safe for values like "javascript:" */
2212 let URI_SAFE_ATTRIBUTES = null;
2213 const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);
2214 const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
2215 const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
2216 const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
2217 /* Document namespace */
2218 let NAMESPACE = HTML_NAMESPACE;
2219 let IS_EMPTY_INPUT = false;
2220 /* Allowed XHTML+XML namespaces */
2221 let ALLOWED_NAMESPACES = null;
2222 const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
2223 let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);
2224 let HTML_INTEGRATION_POINTS = addToSet({}, ['annotation-xml']);
2225 // Certain elements are allowed in both SVG and HTML
2226 // namespace. We need to specify them explicitly
2227 // so that they don't get erroneously deleted from
2228 // HTML namespace.
2229 const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);
2230 /* Parsing of strict XHTML documents */
2231 let PARSER_MEDIA_TYPE = null;
2232 const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];
2233 const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
2234 let transformCaseFunc = null;
2235 /* Keep a reference to config to pass to hooks */
2236 let CONFIG = null;
2237 /* Ideally, do not touch anything below this line */
2238 /* ______________________________________________ */
2239 const formElement = document.createElement('form');
2240 const isRegexOrFunction = function isRegexOrFunction(testValue) {
2241 return testValue instanceof RegExp || testValue instanceof Function;
2242 };
2243 /**
2244 * _parseConfig
2245 *
2246 * @param cfg optional config literal
2247 */
2248 // eslint-disable-next-line complexity
2249 const _parseConfig = function _parseConfig() {
2250 let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2251 if (CONFIG && CONFIG === cfg) {
2252 return;
2253 }
2254 /* Shield configuration object from tampering */
2255 if (!cfg || typeof cfg !== 'object') {
2256 cfg = {};
2257 }
2258 /* Shield configuration object from prototype pollution */
2259 cfg = clone(cfg);
2260 PARSER_MEDIA_TYPE =
2261 // eslint-disable-next-line unicorn/prefer-includes
2262 SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;
2263 // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
2264 transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
2265 /* Set configuration parameters */
2266 ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
2267 ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
2268 ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
2269 URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;
2270 DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;
2271 FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
2272 FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {};
2273 FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};
2274 USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;
2275 ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
2276 ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
2277 ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
2278 ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true
2279 SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false
2280 SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true
2281 WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
2282 RETURN_DOM = cfg.RETURN_DOM || false; // Default false
2283 RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
2284 RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false
2285 FORCE_BODY = cfg.FORCE_BODY || false; // Default false
2286 SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
2287 SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false
2288 KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
2289 IN_PLACE = cfg.IN_PLACE || false; // Default false
2290 IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;
2291 NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
2292 MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS;
2293 HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS;
2294 CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};
2295 if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
2296 CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
2297 }
2298 if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {
2299 CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;
2300 }
2301 if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {
2302 CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
2303 }
2304 if (SAFE_FOR_TEMPLATES) {
2305 ALLOW_DATA_ATTR = false;
2306 }
2307 if (RETURN_DOM_FRAGMENT) {
2308 RETURN_DOM = true;
2309 }
2310 /* Parse profile info */
2311 if (USE_PROFILES) {
2312 ALLOWED_TAGS = addToSet({}, text);
2313 ALLOWED_ATTR = [];
2314 if (USE_PROFILES.html === true) {
2315 addToSet(ALLOWED_TAGS, html$1);
2316 addToSet(ALLOWED_ATTR, html);
2317 }
2318 if (USE_PROFILES.svg === true) {
2319 addToSet(ALLOWED_TAGS, svg$1);
2320 addToSet(ALLOWED_ATTR, svg);
2321 addToSet(ALLOWED_ATTR, xml);
2322 }
2323 if (USE_PROFILES.svgFilters === true) {
2324 addToSet(ALLOWED_TAGS, svgFilters);
2325 addToSet(ALLOWED_ATTR, svg);
2326 addToSet(ALLOWED_ATTR, xml);
2327 }
2328 if (USE_PROFILES.mathMl === true) {
2329 addToSet(ALLOWED_TAGS, mathMl$1);
2330 addToSet(ALLOWED_ATTR, mathMl);
2331 addToSet(ALLOWED_ATTR, xml);
2332 }
2333 }
2334 /* Merge configuration parameters */
2335 if (cfg.ADD_TAGS) {
2336 if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
2337 ALLOWED_TAGS = clone(ALLOWED_TAGS);
2338 }
2339 addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
2340 }
2341 if (cfg.ADD_ATTR) {
2342 if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
2343 ALLOWED_ATTR = clone(ALLOWED_ATTR);
2344 }
2345 addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
2346 }
2347 if (cfg.ADD_URI_SAFE_ATTR) {
2348 addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
2349 }
2350 if (cfg.FORBID_CONTENTS) {
2351 if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
2352 FORBID_CONTENTS = clone(FORBID_CONTENTS);
2353 }
2354 addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
2355 }
2356 /* Add #text in case KEEP_CONTENT is set to true */
2357 if (KEEP_CONTENT) {
2358 ALLOWED_TAGS['#text'] = true;
2359 }
2360 /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
2361 if (WHOLE_DOCUMENT) {
2362 addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);
2363 }
2364 /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */
2365 if (ALLOWED_TAGS.table) {
2366 addToSet(ALLOWED_TAGS, ['tbody']);
2367 delete FORBID_TAGS.tbody;
2368 }
2369 if (cfg.TRUSTED_TYPES_POLICY) {
2370 if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {
2371 throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');
2372 }
2373 if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {
2374 throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
2375 }
2376 // Overwrite existing TrustedTypes policy.
2377 trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;
2378 // Sign local variables required by `sanitize`.
2379 emptyHTML = trustedTypesPolicy.createHTML('');
2380 } else {
2381 // Uninitialized policy, attempt to initialize the internal dompurify policy.
2382 if (trustedTypesPolicy === undefined) {
2383 trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
2384 }
2385 // If creating the internal policy succeeded sign internal variables.
2386 if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {
2387 emptyHTML = trustedTypesPolicy.createHTML('');
2388 }
2389 }
2390 // Prevent further manipulation of configuration.
2391 // Not available in IE8, Safari 5, etc.
2392 if (freeze) {
2393 freeze(cfg);
2394 }
2395 CONFIG = cfg;
2396 };
2397 /* Keep track of all possible SVG and MathML tags
2398 * so that we can perform the namespace checks
2399 * correctly. */
2400 const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);
2401 const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);
2402 /**
2403 * @param element a DOM element whose namespace is being checked
2404 * @returns Return false if the element has a
2405 * namespace that a spec-compliant parser would never
2406 * return. Return true otherwise.
2407 */
2408 const _checkValidNamespace = function _checkValidNamespace(element) {
2409 let parent = getParentNode(element);
2410 // In JSDOM, if we're inside shadow DOM, then parentNode
2411 // can be null. We just simulate parent in this case.
2412 if (!parent || !parent.tagName) {
2413 parent = {
2414 namespaceURI: NAMESPACE,
2415 tagName: 'template'
2416 };
2417 }
2418 const tagName = stringToLowerCase(element.tagName);
2419 const parentTagName = stringToLowerCase(parent.tagName);
2420 if (!ALLOWED_NAMESPACES[element.namespaceURI]) {
2421 return false;
2422 }
2423 if (element.namespaceURI === SVG_NAMESPACE) {
2424 // The only way to switch from HTML namespace to SVG
2425 // is via <svg>. If it happens via any other tag, then
2426 // it should be killed.
2427 if (parent.namespaceURI === HTML_NAMESPACE) {
2428 return tagName === 'svg';
2429 }
2430 // The only way to switch from MathML to SVG is via`
2431 // svg if parent is either <annotation-xml> or MathML
2432 // text integration points.
2433 if (parent.namespaceURI === MATHML_NAMESPACE) {
2434 return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
2435 }
2436 // We only allow elements that are defined in SVG
2437 // spec. All others are disallowed in SVG namespace.
2438 return Boolean(ALL_SVG_TAGS[tagName]);
2439 }
2440 if (element.namespaceURI === MATHML_NAMESPACE) {
2441 // The only way to switch from HTML namespace to MathML
2442 // is via <math>. If it happens via any other tag, then
2443 // it should be killed.
2444 if (parent.namespaceURI === HTML_NAMESPACE) {
2445 return tagName === 'math';
2446 }
2447 // The only way to switch from SVG to MathML is via
2448 // <math> and HTML integration points
2449 if (parent.namespaceURI === SVG_NAMESPACE) {
2450 return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];
2451 }
2452 // We only allow elements that are defined in MathML
2453 // spec. All others are disallowed in MathML namespace.
2454 return Boolean(ALL_MATHML_TAGS[tagName]);
2455 }
2456 if (element.namespaceURI === HTML_NAMESPACE) {
2457 // The only way to switch from SVG to HTML is via
2458 // HTML integration points, and from MathML to HTML
2459 // is via MathML text integration points
2460 if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
2461 return false;
2462 }
2463 if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
2464 return false;
2465 }
2466 // We disallow tags that are specific for MathML
2467 // or SVG and should never appear in HTML namespace
2468 return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
2469 }
2470 // For XHTML and XML documents that support custom namespaces
2471 if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {
2472 return true;
2473 }
2474 // The code should never reach this place (this means
2475 // that the element somehow got namespace that is not
2476 // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).
2477 // Return false just in case.
2478 return false;
2479 };
2480 /**
2481 * _forceRemove
2482 *
2483 * @param node a DOM node
2484 */
2485 const _forceRemove = function _forceRemove(node) {
2486 arrayPush(DOMPurify.removed, {
2487 element: node
2488 });
2489 try {
2490 // eslint-disable-next-line unicorn/prefer-dom-node-remove
2491 getParentNode(node).removeChild(node);
2492 } catch (_) {
2493 remove(node);
2494 }
2495 };
2496 /**
2497 * _removeAttribute
2498 *
2499 * @param name an Attribute name
2500 * @param element a DOM node
2501 */
2502 const _removeAttribute = function _removeAttribute(name, element) {
2503 try {
2504 arrayPush(DOMPurify.removed, {
2505 attribute: element.getAttributeNode(name),
2506 from: element
2507 });
2508 } catch (_) {
2509 arrayPush(DOMPurify.removed, {
2510 attribute: null,
2511 from: element
2512 });
2513 }
2514 element.removeAttribute(name);
2515 // We void attribute values for unremovable "is" attributes
2516 if (name === 'is') {
2517 if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
2518 try {
2519 _forceRemove(element);
2520 } catch (_) {}
2521 } else {
2522 try {
2523 element.setAttribute(name, '');
2524 } catch (_) {}
2525 }
2526 }
2527 };
2528 /**
2529 * _initDocument
2530 *
2531 * @param dirty - a string of dirty markup
2532 * @return a DOM, filled with the dirty markup
2533 */
2534 const _initDocument = function _initDocument(dirty) {
2535 /* Create a HTML document */
2536 let doc = null;
2537 let leadingWhitespace = null;
2538 if (FORCE_BODY) {
2539 dirty = '<remove></remove>' + dirty;
2540 } else {
2541 /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
2542 const matches = stringMatch(dirty, /^[\r\n\t ]+/);
2543 leadingWhitespace = matches && matches[0];
2544 }
2545 if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {
2546 // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)
2547 dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
2548 }
2549 const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
2550 /*
2551 * Use the DOMParser API by default, fallback later if needs be
2552 * DOMParser not work for svg when has multiple root element.
2553 */
2554 if (NAMESPACE === HTML_NAMESPACE) {
2555 try {
2556 doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
2557 } catch (_) {}
2558 }
2559 /* Use createHTMLDocument in case DOMParser is not available */
2560 if (!doc || !doc.documentElement) {
2561 doc = implementation.createDocument(NAMESPACE, 'template', null);
2562 try {
2563 doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;
2564 } catch (_) {
2565 // Syntax error if dirtyPayload is invalid xml
2566 }
2567 }
2568 const body = doc.body || doc.documentElement;
2569 if (dirty && leadingWhitespace) {
2570 body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
2571 }
2572 /* Work on whole document or just its body */
2573 if (NAMESPACE === HTML_NAMESPACE) {
2574 return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
2575 }
2576 return WHOLE_DOCUMENT ? doc.documentElement : body;
2577 };
2578 /**
2579 * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.
2580 *
2581 * @param root The root element or node to start traversing on.
2582 * @return The created NodeIterator
2583 */
2584 const _createNodeIterator = function _createNodeIterator(root) {
2585 return createNodeIterator.call(root.ownerDocument || root, root,
2586 // eslint-disable-next-line no-bitwise
2587 NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);
2588 };
2589 /**
2590 * _isClobbered
2591 *
2592 * @param element element to check for clobbering attacks
2593 * @return true if clobbered, false if safe
2594 */
2595 const _isClobbered = function _isClobbered(element) {
2596 return element instanceof HTMLFormElement && (typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' || !(element.attributes instanceof NamedNodeMap) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function');
2597 };
2598 /**
2599 * Checks whether the given object is a DOM node.
2600 *
2601 * @param value object to check whether it's a DOM node
2602 * @return true is object is a DOM node
2603 */
2604 const _isNode = function _isNode(value) {
2605 return typeof Node === 'function' && value instanceof Node;
2606 };
2607 function _executeHooks(hooks, currentNode, data) {
2608 arrayForEach(hooks, hook => {
2609 hook.call(DOMPurify, currentNode, data, CONFIG);
2610 });
2611 }
2612 /**
2613 * _sanitizeElements
2614 *
2615 * @protect nodeName
2616 * @protect textContent
2617 * @protect removeChild
2618 * @param currentNode to check for permission to exist
2619 * @return true if node was killed, false if left alive
2620 */
2621 const _sanitizeElements = function _sanitizeElements(currentNode) {
2622 let content = null;
2623 /* Execute a hook if present */
2624 _executeHooks(hooks.beforeSanitizeElements, currentNode, null);
2625 /* Check if element is clobbered or can clobber */
2626 if (_isClobbered(currentNode)) {
2627 _forceRemove(currentNode);
2628 return true;
2629 }
2630 /* Now let's check the element's type and name */
2631 const tagName = transformCaseFunc(currentNode.nodeName);
2632 /* Execute a hook if present */
2633 _executeHooks(hooks.uponSanitizeElement, currentNode, {
2634 tagName,
2635 allowedTags: ALLOWED_TAGS
2636 });
2637 /* Detect mXSS attempts abusing namespace confusion */
2638 if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) {
2639 _forceRemove(currentNode);
2640 return true;
2641 }
2642 /* Remove any occurrence of processing instructions */
2643 if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
2644 _forceRemove(currentNode);
2645 return true;
2646 }
2647 /* Remove any kind of possibly harmful comments */
2648 if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\w]/g, currentNode.data)) {
2649 _forceRemove(currentNode);
2650 return true;
2651 }
2652 /* Remove element if anything forbids its presence */
2653 if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
2654 /* Check if we have a custom element to handle */
2655 if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
2656 if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
2657 return false;
2658 }
2659 if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {
2660 return false;
2661 }
2662 }
2663 /* Keep content except for bad-listed elements */
2664 if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
2665 const parentNode = getParentNode(currentNode) || currentNode.parentNode;
2666 const childNodes = getChildNodes(currentNode) || currentNode.childNodes;
2667 if (childNodes && parentNode) {
2668 const childCount = childNodes.length;
2669 for (let i = childCount - 1; i >= 0; --i) {
2670 const childClone = cloneNode(childNodes[i], true);
2671 childClone.__removalCount = (currentNode.__removalCount || 0) + 1;
2672 parentNode.insertBefore(childClone, getNextSibling(currentNode));
2673 }
2674 }
2675 }
2676 _forceRemove(currentNode);
2677 return true;
2678 }
2679 /* Check whether element has a valid namespace */
2680 if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
2681 _forceRemove(currentNode);
2682 return true;
2683 }
2684 /* Make sure that older browsers don't get fallback-tag mXSS */
2685 if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\/no(script|embed|frames)/i, currentNode.innerHTML)) {
2686 _forceRemove(currentNode);
2687 return true;
2688 }
2689 /* Sanitize element content to be template-safe */
2690 if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
2691 /* Get the element's text content */
2692 content = currentNode.textContent;
2693 arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
2694 content = stringReplace(content, expr, ' ');
2695 });
2696 if (currentNode.textContent !== content) {
2697 arrayPush(DOMPurify.removed, {
2698 element: currentNode.cloneNode()
2699 });
2700 currentNode.textContent = content;
2701 }
2702 }
2703 /* Execute a hook if present */
2704 _executeHooks(hooks.afterSanitizeElements, currentNode, null);
2705 return false;
2706 };
2707 /**
2708 * _isValidAttribute
2709 *
2710 * @param lcTag Lowercase tag name of containing element.
2711 * @param lcName Lowercase attribute name.
2712 * @param value Attribute value.
2713 * @return Returns true if `value` is valid, otherwise false.
2714 */
2715 // eslint-disable-next-line complexity
2716 const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
2717 /* Make sure attribute cannot clobber */
2718 if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
2719 return false;
2720 }
2721 /* Allow valid data-* attributes: At least one character after "-"
2722 (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
2723 XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
2724 We don't need to check the value; it's always URI safe. */
2725 if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ;else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ;else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
2726 if (
2727 // First condition does a very basic check if a) it's basically a valid custom element tagname AND
2728 // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
2729 // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
2730 _isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) ||
2731 // Alternative, second condition checks if it's an `is`-attribute, AND
2732 // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
2733 lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ;else {
2734 return false;
2735 }
2736 /* Check value is safe. First, is attr inert? If so, is safe */
2737 } else if (URI_SAFE_ATTRIBUTES[lcName]) ;else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ;else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ;else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ;else if (value) {
2738 return false;
2739 } else ;
2740 return true;
2741 };
2742 /**
2743 * _isBasicCustomElement
2744 * checks if at least one dash is included in tagName, and it's not the first char
2745 * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name
2746 *
2747 * @param tagName name of the tag of the node to sanitize
2748 * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.
2749 */
2750 const _isBasicCustomElement = function _isBasicCustomElement(tagName) {
2751 return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT);
2752 };
2753 /**
2754 * _sanitizeAttributes
2755 *
2756 * @protect attributes
2757 * @protect nodeName
2758 * @protect removeAttribute
2759 * @protect setAttribute
2760 *
2761 * @param currentNode to sanitize
2762 */
2763 const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
2764 /* Execute a hook if present */
2765 _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
2766 const {
2767 attributes
2768 } = currentNode;
2769 /* Check if we have attributes; if not we might have a text node */
2770 if (!attributes || _isClobbered(currentNode)) {
2771 return;
2772 }
2773 const hookEvent = {
2774 attrName: '',
2775 attrValue: '',
2776 keepAttr: true,
2777 allowedAttributes: ALLOWED_ATTR,
2778 forceKeepAttr: undefined
2779 };
2780 let l = attributes.length;
2781 /* Go backwards over all attributes; safely remove bad ones */
2782 while (l--) {
2783 const attr = attributes[l];
2784 const {
2785 name,
2786 namespaceURI,
2787 value: attrValue
2788 } = attr;
2789 const lcName = transformCaseFunc(name);
2790 let value = name === 'value' ? attrValue : stringTrim(attrValue);
2791 /* Execute a hook if present */
2792 hookEvent.attrName = lcName;
2793 hookEvent.attrValue = value;
2794 hookEvent.keepAttr = true;
2795 hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
2796 _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);
2797 value = hookEvent.attrValue;
2798 /* Full DOM Clobbering protection via namespace isolation,
2799 * Prefix id and name attributes with `user-content-`
2800 */
2801 if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {
2802 // Remove the attribute with this value
2803 _removeAttribute(name, currentNode);
2804 // Prefix the value and later re-create the attribute with the sanitized value
2805 value = SANITIZE_NAMED_PROPS_PREFIX + value;
2806 }
2807 /* Work around a security issue with comments inside attributes */
2808 if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title)/i, value)) {
2809 _removeAttribute(name, currentNode);
2810 continue;
2811 }
2812 /* Did the hooks approve of the attribute? */
2813 if (hookEvent.forceKeepAttr) {
2814 continue;
2815 }
2816 /* Remove attribute */
2817 _removeAttribute(name, currentNode);
2818 /* Did the hooks approve of the attribute? */
2819 if (!hookEvent.keepAttr) {
2820 continue;
2821 }
2822 /* Work around a security issue in jQuery 3.0 */
2823 if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) {
2824 _removeAttribute(name, currentNode);
2825 continue;
2826 }
2827 /* Sanitize attribute content to be template-safe */
2828 if (SAFE_FOR_TEMPLATES) {
2829 arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
2830 value = stringReplace(value, expr, ' ');
2831 });
2832 }
2833 /* Is `value` valid for this attribute? */
2834 const lcTag = transformCaseFunc(currentNode.nodeName);
2835 if (!_isValidAttribute(lcTag, lcName, value)) {
2836 continue;
2837 }
2838 /* Handle attributes that require Trusted Types */
2839 if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') {
2840 if (namespaceURI) ;else {
2841 switch (trustedTypes.getAttributeType(lcTag, lcName)) {
2842 case 'TrustedHTML':
2843 {
2844 value = trustedTypesPolicy.createHTML(value);
2845 break;
2846 }
2847 case 'TrustedScriptURL':
2848 {
2849 value = trustedTypesPolicy.createScriptURL(value);
2850 break;
2851 }
2852 }
2853 }
2854 }
2855 /* Handle invalid data-* attribute set by try-catching it */
2856 try {
2857 if (namespaceURI) {
2858 currentNode.setAttributeNS(namespaceURI, name, value);
2859 } else {
2860 /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
2861 currentNode.setAttribute(name, value);
2862 }
2863 if (_isClobbered(currentNode)) {
2864 _forceRemove(currentNode);
2865 } else {
2866 arrayPop(DOMPurify.removed);
2867 }
2868 } catch (_) {}
2869 }
2870 /* Execute a hook if present */
2871 _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);
2872 };
2873 /**
2874 * _sanitizeShadowDOM
2875 *
2876 * @param fragment to iterate over recursively
2877 */
2878 const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
2879 let shadowNode = null;
2880 const shadowIterator = _createNodeIterator(fragment);
2881 /* Execute a hook if present */
2882 _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);
2883 while (shadowNode = shadowIterator.nextNode()) {
2884 /* Execute a hook if present */
2885 _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);
2886 /* Sanitize tags and elements */
2887 _sanitizeElements(shadowNode);
2888 /* Check attributes next */
2889 _sanitizeAttributes(shadowNode);
2890 /* Deep shadow DOM detected */
2891 if (shadowNode.content instanceof DocumentFragment) {
2892 _sanitizeShadowDOM(shadowNode.content);
2893 }
2894 }
2895 /* Execute a hook if present */
2896 _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
2897 };
2898 // eslint-disable-next-line complexity
2899 DOMPurify.sanitize = function (dirty) {
2900 let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
2901 let body = null;
2902 let importedNode = null;
2903 let currentNode = null;
2904 let returnNode = null;
2905 /* Make sure we have a string to sanitize.
2906 DO NOT return early, as this will return the wrong type if
2907 the user has requested a DOM object rather than a string */
2908 IS_EMPTY_INPUT = !dirty;
2909 if (IS_EMPTY_INPUT) {
2910 dirty = '<!-->';
2911 }
2912 /* Stringify, in case dirty is an object */
2913 if (typeof dirty !== 'string' && !_isNode(dirty)) {
2914 if (typeof dirty.toString === 'function') {
2915 dirty = dirty.toString();
2916 if (typeof dirty !== 'string') {
2917 throw typeErrorCreate('dirty is not a string, aborting');
2918 }
2919 } else {
2920 throw typeErrorCreate('toString is not a function');
2921 }
2922 }
2923 /* Return dirty HTML if DOMPurify cannot run */
2924 if (!DOMPurify.isSupported) {
2925 return dirty;
2926 }
2927 /* Assign config vars */
2928 if (!SET_CONFIG) {
2929 _parseConfig(cfg);
2930 }
2931 /* Clean up removed elements */
2932 DOMPurify.removed = [];
2933 /* Check if dirty is correctly typed for IN_PLACE */
2934 if (typeof dirty === 'string') {
2935 IN_PLACE = false;
2936 }
2937 if (IN_PLACE) {
2938 /* Do some early pre-sanitization to avoid unsafe root nodes */
2939 if (dirty.nodeName) {
2940 const tagName = transformCaseFunc(dirty.nodeName);
2941 if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
2942 throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
2943 }
2944 }
2945 } else if (dirty instanceof Node) {
2946 /* If dirty is a DOM element, append to an empty document to avoid
2947 elements being stripped by the parser */
2948 body = _initDocument('<!---->');
2949 importedNode = body.ownerDocument.importNode(dirty, true);
2950 if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === 'BODY') {
2951 /* Node is already a body, use as is */
2952 body = importedNode;
2953 } else if (importedNode.nodeName === 'HTML') {
2954 body = importedNode;
2955 } else {
2956 // eslint-disable-next-line unicorn/prefer-dom-node-append
2957 body.appendChild(importedNode);
2958 }
2959 } else {
2960 /* Exit directly if we have nothing to do */
2961 if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&
2962 // eslint-disable-next-line unicorn/prefer-includes
2963 dirty.indexOf('<') === -1) {
2964 return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
2965 }
2966 /* Initialize the document to work on */
2967 body = _initDocument(dirty);
2968 /* Check we have a DOM node from the data */
2969 if (!body) {
2970 return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';
2971 }
2972 }
2973 /* Remove first element node (ours) if FORCE_BODY is set */
2974 if (body && FORCE_BODY) {
2975 _forceRemove(body.firstChild);
2976 }
2977 /* Get node iterator */
2978 const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);
2979 /* Now start iterating over the created document */
2980 while (currentNode = nodeIterator.nextNode()) {
2981 /* Sanitize tags and elements */
2982 _sanitizeElements(currentNode);
2983 /* Check attributes next */
2984 _sanitizeAttributes(currentNode);
2985 /* Shadow DOM detected, sanitize it */
2986 if (currentNode.content instanceof DocumentFragment) {
2987 _sanitizeShadowDOM(currentNode.content);
2988 }
2989 }
2990 /* If we sanitized `dirty` in-place, return it. */
2991 if (IN_PLACE) {
2992 return dirty;
2993 }
2994 /* Return sanitized string or DOM */
2995 if (RETURN_DOM) {
2996 if (RETURN_DOM_FRAGMENT) {
2997 returnNode = createDocumentFragment.call(body.ownerDocument);
2998 while (body.firstChild) {
2999 // eslint-disable-next-line unicorn/prefer-dom-node-append
3000 returnNode.appendChild(body.firstChild);
3001 }
3002 } else {
3003 returnNode = body;
3004 }
3005 if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {
3006 /*
3007 AdoptNode() is not used because internal state is not reset
3008 (e.g. the past names map of a HTMLFormElement), this is safe
3009 in theory but we would rather not risk another attack vector.
3010 The state that is cloned by importNode() is explicitly defined
3011 by the specs.
3012 */
3013 returnNode = importNode.call(originalDocument, returnNode, true);
3014 }
3015 return returnNode;
3016 }
3017 let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
3018 /* Serialize doctype if allowed */
3019 if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
3020 serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML;
3021 }
3022 /* Sanitize final string template-safe */
3023 if (SAFE_FOR_TEMPLATES) {
3024 arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
3025 serializedHTML = stringReplace(serializedHTML, expr, ' ');
3026 });
3027 }
3028 return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
3029 };
3030 DOMPurify.setConfig = function () {
3031 let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
3032 _parseConfig(cfg);
3033 SET_CONFIG = true;
3034 };
3035 DOMPurify.clearConfig = function () {
3036 CONFIG = null;
3037 SET_CONFIG = false;
3038 };
3039 DOMPurify.isValidAttribute = function (tag, attr, value) {
3040 /* Initialize shared config vars if necessary. */
3041 if (!CONFIG) {
3042 _parseConfig({});
3043 }
3044 const lcTag = transformCaseFunc(tag);
3045 const lcName = transformCaseFunc(attr);
3046 return _isValidAttribute(lcTag, lcName, value);
3047 };
3048 DOMPurify.addHook = function (entryPoint, hookFunction) {
3049 if (typeof hookFunction !== 'function') {
3050 return;
3051 }
3052 arrayPush(hooks[entryPoint], hookFunction);
3053 };
3054 DOMPurify.removeHook = function (entryPoint) {
3055 return arrayPop(hooks[entryPoint]);
3056 };
3057 DOMPurify.removeHooks = function (entryPoint) {
3058 hooks[entryPoint] = [];
3059 };
3060 DOMPurify.removeAllHooks = function () {
3061 hooks = _createHooksMap();
3062 };
3063 return DOMPurify;
3064 }
3065 var purify = createDOMPurify();
3066
3067 const DEFAULT_ALLOWED_ATTRIBUTES = "style href src width height language class".split(" ");
3068 const DEFAULT_FORBIDDEN_PROTOCOLS = "javascript:".split(" ");
3069 const DEFAULT_FORBIDDEN_ELEMENTS = "script iframe form noscript".split(" ");
3070 class HTMLSanitizer extends BasicObject {
3071 static setHTML(element, html) {
3072 const sanitizedElement = new this(html).sanitize();
3073 const sanitizedHtml = sanitizedElement.getHTML ? sanitizedElement.getHTML() : sanitizedElement.outerHTML;
3074 element.innerHTML = sanitizedHtml;
3075 }
3076 static sanitize(html, options) {
3077 const sanitizer = new this(html, options);
3078 sanitizer.sanitize();
3079 return sanitizer;
3080 }
3081 constructor(html) {
3082 let {
3083 allowedAttributes,
3084 forbiddenProtocols,
3085 forbiddenElements
3086 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
3087 super(...arguments);
3088 this.allowedAttributes = allowedAttributes || DEFAULT_ALLOWED_ATTRIBUTES;
3089 this.forbiddenProtocols = forbiddenProtocols || DEFAULT_FORBIDDEN_PROTOCOLS;
3090 this.forbiddenElements = forbiddenElements || DEFAULT_FORBIDDEN_ELEMENTS;
3091 this.body = createBodyElementForHTML(html);
3092 }
3093 sanitize() {
3094 this.sanitizeElements();
3095 this.normalizeListElementNesting();
3096 return purify.sanitize(this.body, {
3097 ADD_ATTR: ["language"],
3098 RETURN_DOM: true
3099 });
3100 }
3101 getHTML() {
3102 return this.body.innerHTML;
3103 }
3104 getBody() {
3105 return this.body;
3106 }
3107
3108 // Private
3109
3110 sanitizeElements() {
3111 const walker = walkTree(this.body);
3112 const nodesToRemove = [];
3113 while (walker.nextNode()) {
3114 const node = walker.currentNode;
3115 switch (node.nodeType) {
3116 case Node.ELEMENT_NODE:
3117 if (this.elementIsRemovable(node)) {
3118 nodesToRemove.push(node);
3119 } else {
3120 this.sanitizeElement(node);
3121 }
3122 break;
3123 case Node.COMMENT_NODE:
3124 nodesToRemove.push(node);
3125 break;
3126 }
3127 }
3128 nodesToRemove.forEach(node => removeNode(node));
3129 return this.body;
3130 }
3131 sanitizeElement(element) {
3132 if (element.hasAttribute("href")) {
3133 if (this.forbiddenProtocols.includes(element.protocol)) {
3134 element.removeAttribute("href");
3135 }
3136 }
3137 Array.from(element.attributes).forEach(_ref => {
3138 let {
3139 name
3140 } = _ref;
3141 if (!this.allowedAttributes.includes(name) && name.indexOf("data-trix") !== 0) {
3142 element.removeAttribute(name);
3143 }
3144 });
3145 return element;
3146 }
3147 normalizeListElementNesting() {
3148 Array.from(this.body.querySelectorAll("ul,ol")).forEach(listElement => {
3149 const previousElement = listElement.previousElementSibling;
3150 if (previousElement) {
3151 if (tagName(previousElement) === "li") {
3152 previousElement.appendChild(listElement);
3153 }
3154 }
3155 });
3156 return this.body;
3157 }
3158 elementIsRemovable(element) {
3159 if ((element === null || element === void 0 ? void 0 : element.nodeType) !== Node.ELEMENT_NODE) return;
3160 return this.elementIsForbidden(element) || this.elementIsntSerializable(element);
3161 }
3162 elementIsForbidden(element) {
3163 return this.forbiddenElements.includes(tagName(element));
3164 }
3165 elementIsntSerializable(element) {
3166 return element.getAttribute("data-trix-serialize") === "false" && !nodeIsAttachmentElement(element);
3167 }
3168 }
3169 const createBodyElementForHTML = function () {
3170 let html = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
3171 // Remove everything after </html>
3172 html = html.replace(/<\/html[^>]*>[^]*$/i, "</html>");
3173 const doc = document.implementation.createHTMLDocument("");
3174 doc.documentElement.innerHTML = html;
3175 Array.from(doc.head.querySelectorAll("style")).forEach(element => {
3176 doc.body.appendChild(element);
3177 });
3178 return doc.body;
3179 };
3180
3181 const {
3182 css: css$2
3183 } = config;
3184 class AttachmentView extends ObjectView {
3185 constructor() {
3186 super(...arguments);
3187 this.attachment = this.object;
3188 this.attachment.uploadProgressDelegate = this;
3189 this.attachmentPiece = this.options.piece;
3190 }
3191 createContentNodes() {
3192 return [];
3193 }
3194 createNodes() {
3195 let innerElement;
3196 const figure = innerElement = makeElement({
3197 tagName: "figure",
3198 className: this.getClassName(),
3199 data: this.getData(),
3200 editable: false
3201 });
3202 const href = this.getHref();
3203 if (href) {
3204 innerElement = makeElement({
3205 tagName: "a",
3206 editable: false,
3207 attributes: {
3208 href,
3209 tabindex: -1
3210 }
3211 });
3212 figure.appendChild(innerElement);
3213 }
3214 if (this.attachment.hasContent()) {
3215 HTMLSanitizer.setHTML(innerElement, this.attachment.getContent());
3216 } else {
3217 this.createContentNodes().forEach(node => {
3218 innerElement.appendChild(node);
3219 });
3220 }
3221 innerElement.appendChild(this.createCaptionElement());
3222 if (this.attachment.isPending()) {
3223 this.progressElement = makeElement({
3224 tagName: "progress",
3225 attributes: {
3226 class: css$2.attachmentProgress,
3227 value: this.attachment.getUploadProgress(),
3228 max: 100
3229 },
3230 data: {
3231 trixMutable: true,
3232 trixStoreKey: ["progressElement", this.attachment.id].join("/")
3233 }
3234 });
3235 figure.appendChild(this.progressElement);
3236 }
3237 return [createCursorTarget("left"), figure, createCursorTarget("right")];
3238 }
3239 createCaptionElement() {
3240 const figcaption = makeElement({
3241 tagName: "figcaption",
3242 className: css$2.attachmentCaption
3243 });
3244 const caption = this.attachmentPiece.getCaption();
3245 if (caption) {
3246 figcaption.classList.add("".concat(css$2.attachmentCaption, "--edited"));
3247 figcaption.textContent = caption;
3248 } else {
3249 let name, size;
3250 const captionConfig = this.getCaptionConfig();
3251 if (captionConfig.name) {
3252 name = this.attachment.getFilename();
3253 }
3254 if (captionConfig.size) {
3255 size = this.attachment.getFormattedFilesize();
3256 }
3257 if (name) {
3258 const nameElement = makeElement({
3259 tagName: "span",
3260 className: css$2.attachmentName,
3261 textContent: name
3262 });
3263 figcaption.appendChild(nameElement);
3264 }
3265 if (size) {
3266 if (name) {
3267 figcaption.appendChild(document.createTextNode(" "));
3268 }
3269 const sizeElement = makeElement({
3270 tagName: "span",
3271 className: css$2.attachmentSize,
3272 textContent: size
3273 });
3274 figcaption.appendChild(sizeElement);
3275 }
3276 }
3277 return figcaption;
3278 }
3279 getClassName() {
3280 const names = [css$2.attachment, "".concat(css$2.attachment, "--").concat(this.attachment.getType())];
3281 const extension = this.attachment.getExtension();
3282 if (extension) {
3283 names.push("".concat(css$2.attachment, "--").concat(extension));
3284 }
3285 return names.join(" ");
3286 }
3287 getData() {
3288 const data = {
3289 trixAttachment: JSON.stringify(this.attachment),
3290 trixContentType: this.attachment.getContentType(),
3291 trixId: this.attachment.id
3292 };
3293 const {
3294 attributes
3295 } = this.attachmentPiece;
3296 if (!attributes.isEmpty()) {
3297 data.trixAttributes = JSON.stringify(attributes);
3298 }
3299 if (this.attachment.isPending()) {
3300 data.trixSerialize = false;
3301 }
3302 return data;
3303 }
3304 getHref() {
3305 if (!htmlContainsTagName(this.attachment.getContent(), "a")) {
3306 return this.attachment.getHref();
3307 }
3308 }
3309 getCaptionConfig() {
3310 var _config$attachments$t;
3311 const type = this.attachment.getType();
3312 const captionConfig = copyObject((_config$attachments$t = attachments[type]) === null || _config$attachments$t === void 0 ? void 0 : _config$attachments$t.caption);
3313 if (type === "file") {
3314 captionConfig.name = true;
3315 }
3316 return captionConfig;
3317 }
3318 findProgressElement() {
3319 var _this$findElement;
3320 return (_this$findElement = this.findElement()) === null || _this$findElement === void 0 ? void 0 : _this$findElement.querySelector("progress");
3321 }
3322
3323 // Attachment delegate
3324
3325 attachmentDidChangeUploadProgress() {
3326 const value = this.attachment.getUploadProgress();
3327 const progressElement = this.findProgressElement();
3328 if (progressElement) {
3329 progressElement.value = value;
3330 }
3331 }
3332 }
3333 const createCursorTarget = name => makeElement({
3334 tagName: "span",
3335 textContent: ZERO_WIDTH_SPACE,
3336 data: {
3337 trixCursorTarget: name,
3338 trixSerialize: false
3339 }
3340 });
3341 const htmlContainsTagName = function (html, tagName) {
3342 const div = makeElement("div");
3343 HTMLSanitizer.setHTML(div, html || "");
3344 return div.querySelector(tagName);
3345 };
3346
3347 class PreviewableAttachmentView extends AttachmentView {
3348 constructor() {
3349 super(...arguments);
3350 this.attachment.previewDelegate = this;
3351 }
3352 createContentNodes() {
3353 this.image = makeElement({
3354 tagName: "img",
3355 attributes: {
3356 src: ""
3357 },
3358 data: {
3359 trixMutable: true
3360 }
3361 });
3362 this.refresh(this.image);
3363 return [this.image];
3364 }
3365 createCaptionElement() {
3366 const figcaption = super.createCaptionElement(...arguments);
3367 if (!figcaption.textContent) {
3368 figcaption.setAttribute("data-trix-placeholder", lang$1.captionPlaceholder);
3369 }
3370 return figcaption;
3371 }
3372 refresh(image) {
3373 if (!image) {
3374 var _this$findElement;
3375 image = (_this$findElement = this.findElement()) === null || _this$findElement === void 0 ? void 0 : _this$findElement.querySelector("img");
3376 }
3377 if (image) {
3378 return this.updateAttributesForImage(image);
3379 }
3380 }
3381 updateAttributesForImage(image) {
3382 const url = this.attachment.getURL();
3383 const previewURL = this.attachment.getPreviewURL();
3384 image.src = previewURL || url;
3385 if (previewURL === url) {
3386 image.removeAttribute("data-trix-serialized-attributes");
3387 } else {
3388 const serializedAttributes = JSON.stringify({
3389 src: url
3390 });
3391 image.setAttribute("data-trix-serialized-attributes", serializedAttributes);
3392 }
3393 const width = this.attachment.getWidth();
3394 const height = this.attachment.getHeight();
3395 if (width != null) {
3396 image.width = width;
3397 }
3398 if (height != null) {
3399 image.height = height;
3400 }
3401 const storeKey = ["imageElement", this.attachment.id, image.src, image.width, image.height].join("/");
3402 image.dataset.trixStoreKey = storeKey;
3403 }
3404
3405 // Attachment delegate
3406
3407 attachmentDidChangeAttributes() {
3408 this.refresh(this.image);
3409 return this.refresh();
3410 }
3411 }
3412
3413 /* eslint-disable
3414 no-useless-escape,
3415 no-var,
3416 */
3417 class PieceView extends ObjectView {
3418 constructor() {
3419 super(...arguments);
3420 this.piece = this.object;
3421 this.attributes = this.piece.getAttributes();
3422 this.textConfig = this.options.textConfig;
3423 this.context = this.options.context;
3424 if (this.piece.attachment) {
3425 this.attachment = this.piece.attachment;
3426 } else {
3427 this.string = this.piece.toString();
3428 }
3429 }
3430 createNodes() {
3431 let nodes = this.attachment ? this.createAttachmentNodes() : this.createStringNodes();
3432 const element = this.createElement();
3433 if (element) {
3434 const innerElement = findInnerElement(element);
3435 Array.from(nodes).forEach(node => {
3436 innerElement.appendChild(node);
3437 });
3438 nodes = [element];
3439 }
3440 return nodes;
3441 }
3442 createAttachmentNodes() {
3443 const constructor = this.attachment.isPreviewable() ? PreviewableAttachmentView : AttachmentView;
3444 const view = this.createChildView(constructor, this.piece.attachment, {
3445 piece: this.piece
3446 });
3447 return view.getNodes();
3448 }
3449 createStringNodes() {
3450 var _this$textConfig;
3451 if ((_this$textConfig = this.textConfig) !== null && _this$textConfig !== void 0 && _this$textConfig.plaintext) {
3452 return [document.createTextNode(this.string)];
3453 } else {
3454 const nodes = [];
3455 const iterable = this.string.split("\n");
3456 for (let index = 0; index < iterable.length; index++) {
3457 const substring = iterable[index];
3458 if (index > 0) {
3459 const element = makeElement("br");
3460 nodes.push(element);
3461 }
3462 if (substring.length) {
3463 const node = document.createTextNode(this.preserveSpaces(substring));
3464 nodes.push(node);
3465 }
3466 }
3467 return nodes;
3468 }
3469 }
3470 createElement() {
3471 let element, key, value;
3472 const styles = {};
3473 for (key in this.attributes) {
3474 value = this.attributes[key];
3475 const config = getTextConfig(key);
3476 if (config) {
3477 if (config.tagName) {
3478 var innerElement;
3479 const pendingElement = makeElement(config.tagName);
3480 if (innerElement) {
3481 innerElement.appendChild(pendingElement);
3482 innerElement = pendingElement;
3483 } else {
3484 element = innerElement = pendingElement;
3485 }
3486 }
3487 if (config.styleProperty) {
3488 styles[config.styleProperty] = value;
3489 }
3490 if (config.style) {
3491 for (key in config.style) {
3492 value = config.style[key];
3493 styles[key] = value;
3494 }
3495 }
3496 }
3497 }
3498 if (Object.keys(styles).length) {
3499 if (!element) {
3500 element = makeElement("span");
3501 }
3502 for (key in styles) {
3503 value = styles[key];
3504 element.style[key] = value;
3505 }
3506 }
3507 return element;
3508 }
3509 createContainerElement() {
3510 for (const key in this.attributes) {
3511 const value = this.attributes[key];
3512 const config = getTextConfig(key);
3513 if (config) {
3514 if (config.groupTagName) {
3515 const attributes = {};
3516 attributes[key] = value;
3517 return makeElement(config.groupTagName, attributes);
3518 }
3519 }
3520 }
3521 }
3522 preserveSpaces(string) {
3523 if (this.context.isLast) {
3524 string = string.replace(/\ $/, NON_BREAKING_SPACE);
3525 }
3526 string = string.replace(/(\S)\ {3}(\S)/g, "$1 ".concat(NON_BREAKING_SPACE, " $2")).replace(/\ {2}/g, "".concat(NON_BREAKING_SPACE, " ")).replace(/\ {2}/g, " ".concat(NON_BREAKING_SPACE));
3527 if (this.context.isFirst || this.context.followsWhitespace) {
3528 string = string.replace(/^\ /, NON_BREAKING_SPACE);
3529 }
3530 return string;
3531 }
3532 }
3533
3534 /* eslint-disable
3535 no-var,
3536 */
3537 class TextView extends ObjectView {
3538 constructor() {
3539 super(...arguments);
3540 this.text = this.object;
3541 this.textConfig = this.options.textConfig;
3542 }
3543 createNodes() {
3544 const nodes = [];
3545 const pieces = ObjectGroup.groupObjects(this.getPieces());
3546 const lastIndex = pieces.length - 1;
3547 for (let index = 0; index < pieces.length; index++) {
3548 const piece = pieces[index];
3549 const context = {};
3550 if (index === 0) {
3551 context.isFirst = true;
3552 }
3553 if (index === lastIndex) {
3554 context.isLast = true;
3555 }
3556 if (endsWithWhitespace(previousPiece)) {
3557 context.followsWhitespace = true;
3558 }
3559 const view = this.findOrCreateCachedChildView(PieceView, piece, {
3560 textConfig: this.textConfig,
3561 context
3562 });
3563 nodes.push(...Array.from(view.getNodes() || []));
3564 var previousPiece = piece;
3565 }
3566 return nodes;
3567 }
3568 getPieces() {
3569 return Array.from(this.text.getPieces()).filter(piece => !piece.hasAttribute("blockBreak"));
3570 }
3571 }
3572 const endsWithWhitespace = piece => /\s$/.test(piece === null || piece === void 0 ? void 0 : piece.toString());
3573
3574 const {
3575 css: css$1
3576 } = config;
3577 class BlockView extends ObjectView {
3578 constructor() {
3579 super(...arguments);
3580 this.block = this.object;
3581 this.attributes = this.block.getAttributes();
3582 }
3583 createNodes() {
3584 const comment = document.createComment("block");
3585 const nodes = [comment];
3586 if (this.block.isEmpty()) {
3587 nodes.push(makeElement("br"));
3588 } else {
3589 var _getBlockConfig;
3590 const textConfig = (_getBlockConfig = getBlockConfig(this.block.getLastAttribute())) === null || _getBlockConfig === void 0 ? void 0 : _getBlockConfig.text;
3591 const textView = this.findOrCreateCachedChildView(TextView, this.block.text, {
3592 textConfig
3593 });
3594 nodes.push(...Array.from(textView.getNodes() || []));
3595 if (this.shouldAddExtraNewlineElement()) {
3596 nodes.push(makeElement("br"));
3597 }
3598 }
3599 if (this.attributes.length) {
3600 return nodes;
3601 } else {
3602 let attributes$1;
3603 const {
3604 tagName
3605 } = attributes.default;
3606 if (this.block.isRTL()) {
3607 attributes$1 = {
3608 dir: "rtl"
3609 };
3610 }
3611 const element = makeElement({
3612 tagName,
3613 attributes: attributes$1
3614 });
3615 nodes.forEach(node => element.appendChild(node));
3616 return [element];
3617 }
3618 }
3619 createContainerElement(depth) {
3620 const attributes = {};
3621 let className;
3622 const attributeName = this.attributes[depth];
3623 const {
3624 tagName,
3625 htmlAttributes = []
3626 } = getBlockConfig(attributeName);
3627 if (depth === 0 && this.block.isRTL()) {
3628 Object.assign(attributes, {
3629 dir: "rtl"
3630 });
3631 }
3632 if (attributeName === "attachmentGallery") {
3633 const size = this.block.getBlockBreakPosition();
3634 className = "".concat(css$1.attachmentGallery, " ").concat(css$1.attachmentGallery, "--").concat(size);
3635 }
3636 Object.entries(this.block.htmlAttributes).forEach(_ref => {
3637 let [name, value] = _ref;
3638 if (htmlAttributes.includes(name)) {
3639 attributes[name] = value;
3640 }
3641 });
3642 return makeElement({
3643 tagName,
3644 className,
3645 attributes
3646 });
3647 }
3648
3649 // A single <br> at the end of a block element has no visual representation
3650 // so add an extra one.
3651 shouldAddExtraNewlineElement() {
3652 return /\n\n$/.test(this.block.toString());
3653 }
3654 }
3655
3656 class DocumentView extends ObjectView {
3657 static render(document) {
3658 const element = makeElement("div");
3659 const view = new this(document, {
3660 element
3661 });
3662 view.render();
3663 view.sync();
3664 return element;
3665 }
3666 constructor() {
3667 super(...arguments);
3668 this.element = this.options.element;
3669 this.elementStore = new ElementStore();
3670 this.setDocument(this.object);
3671 }
3672 setDocument(document) {
3673 if (!document.isEqualTo(this.document)) {
3674 this.document = this.object = document;
3675 }
3676 }
3677 render() {
3678 this.childViews = [];
3679 this.shadowElement = makeElement("div");
3680 if (!this.document.isEmpty()) {
3681 const objects = ObjectGroup.groupObjects(this.document.getBlocks(), {
3682 asTree: true
3683 });
3684 Array.from(objects).forEach(object => {
3685 const view = this.findOrCreateCachedChildView(BlockView, object);
3686 Array.from(view.getNodes()).map(node => this.shadowElement.appendChild(node));
3687 });
3688 }
3689 }
3690 isSynced() {
3691 return elementsHaveEqualHTML(this.shadowElement, this.element);
3692 }
3693 sync() {
3694 const fragment = this.createDocumentFragmentForSync();
3695 while (this.element.lastChild) {
3696 this.element.removeChild(this.element.lastChild);
3697 }
3698 this.element.appendChild(fragment);
3699 return this.didSync();
3700 }
3701
3702 // Private
3703
3704 didSync() {
3705 this.elementStore.reset(findStoredElements(this.element));
3706 return defer(() => this.garbageCollectCachedViews());
3707 }
3708 createDocumentFragmentForSync() {
3709 const fragment = document.createDocumentFragment();
3710 Array.from(this.shadowElement.childNodes).forEach(node => {
3711 fragment.appendChild(node.cloneNode(true));
3712 });
3713 Array.from(findStoredElements(fragment)).forEach(element => {
3714 const storedElement = this.elementStore.remove(element);
3715 if (storedElement) {
3716 element.parentNode.replaceChild(storedElement, element);
3717 }
3718 });
3719 return fragment;
3720 }
3721 }
3722 const findStoredElements = element => element.querySelectorAll("[data-trix-store-key]");
3723 const elementsHaveEqualHTML = (element, otherElement) => ignoreSpaces(element.innerHTML) === ignoreSpaces(otherElement.innerHTML);
3724 const ignoreSpaces = html => html.replace(/&nbsp;/g, " ");
3725
3726 function _AsyncGenerator(e) {
3727 var r, t;
3728 function resume(r, t) {
3729 try {
3730 var n = e[r](t),
3731 o = n.value,
3732 u = o instanceof _OverloadYield;
3733 Promise.resolve(u ? o.v : o).then(function (t) {
3734 if (u) {
3735 var i = "return" === r ? "return" : "next";
3736 if (!o.k || t.done) return resume(i, t);
3737 t = e[i](t).value;
3738 }
3739 settle(n.done ? "return" : "normal", t);
3740 }, function (e) {
3741 resume("throw", e);
3742 });
3743 } catch (e) {
3744 settle("throw", e);
3745 }
3746 }
3747 function settle(e, n) {
3748 switch (e) {
3749 case "return":
3750 r.resolve({
3751 value: n,
3752 done: !0
3753 });
3754 break;
3755 case "throw":
3756 r.reject(n);
3757 break;
3758 default:
3759 r.resolve({
3760 value: n,
3761 done: !1
3762 });
3763 }
3764 (r = r.next) ? resume(r.key, r.arg) : t = null;
3765 }
3766 this._invoke = function (e, n) {
3767 return new Promise(function (o, u) {
3768 var i = {
3769 key: e,
3770 arg: n,
3771 resolve: o,
3772 reject: u,
3773 next: null
3774 };
3775 t ? t = t.next = i : (r = t = i, resume(e, n));
3776 });
3777 }, "function" != typeof e.return && (this.return = void 0);
3778 }
3779 _AsyncGenerator.prototype["function" == typeof Symbol && Symbol.asyncIterator || "@@asyncIterator"] = function () {
3780 return this;
3781 }, _AsyncGenerator.prototype.next = function (e) {
3782 return this._invoke("next", e);
3783 }, _AsyncGenerator.prototype.throw = function (e) {
3784 return this._invoke("throw", e);
3785 }, _AsyncGenerator.prototype.return = function (e) {
3786 return this._invoke("return", e);
3787 };
3788 function _OverloadYield(t, e) {
3789 this.v = t, this.k = e;
3790 }
3791 function old_createMetadataMethodsForProperty(e, t, a, r) {
3792 return {
3793 getMetadata: function (o) {
3794 old_assertNotFinished(r, "getMetadata"), old_assertMetadataKey(o);
3795 var i = e[o];
3796 if (void 0 !== i) if (1 === t) {
3797 var n = i.public;
3798 if (void 0 !== n) return n[a];
3799 } else if (2 === t) {
3800 var l = i.private;
3801 if (void 0 !== l) return l.get(a);
3802 } else if (Object.hasOwnProperty.call(i, "constructor")) return i.constructor;
3803 },
3804 setMetadata: function (o, i) {
3805 old_assertNotFinished(r, "setMetadata"), old_assertMetadataKey(o);
3806 var n = e[o];
3807 if (void 0 === n && (n = e[o] = {}), 1 === t) {
3808 var l = n.public;
3809 void 0 === l && (l = n.public = {}), l[a] = i;
3810 } else if (2 === t) {
3811 var s = n.priv;
3812 void 0 === s && (s = n.private = new Map()), s.set(a, i);
3813 } else n.constructor = i;
3814 }
3815 };
3816 }
3817 function old_convertMetadataMapToFinal(e, t) {
3818 var a = e[Symbol.metadata || Symbol.for("Symbol.metadata")],
3819 r = Object.getOwnPropertySymbols(t);
3820 if (0 !== r.length) {
3821 for (var o = 0; o < r.length; o++) {
3822 var i = r[o],
3823 n = t[i],
3824 l = a ? a[i] : null,
3825 s = n.public,
3826 c = l ? l.public : null;
3827 s && c && Object.setPrototypeOf(s, c);
3828 var d = n.private;
3829 if (d) {
3830 var u = Array.from(d.values()),
3831 f = l ? l.private : null;
3832 f && (u = u.concat(f)), n.private = u;
3833 }
3834 l && Object.setPrototypeOf(n, l);
3835 }
3836 a && Object.setPrototypeOf(t, a), e[Symbol.metadata || Symbol.for("Symbol.metadata")] = t;
3837 }
3838 }
3839 function old_createAddInitializerMethod(e, t) {
3840 return function (a) {
3841 old_assertNotFinished(t, "addInitializer"), old_assertCallable(a, "An initializer"), e.push(a);
3842 };
3843 }
3844 function old_memberDec(e, t, a, r, o, i, n, l, s) {
3845 var c;
3846 switch (i) {
3847 case 1:
3848 c = "accessor";
3849 break;
3850 case 2:
3851 c = "method";
3852 break;
3853 case 3:
3854 c = "getter";
3855 break;
3856 case 4:
3857 c = "setter";
3858 break;
3859 default:
3860 c = "field";
3861 }
3862 var d,
3863 u,
3864 f = {
3865 kind: c,
3866 name: l ? "#" + t : t,
3867 isStatic: n,
3868 isPrivate: l
3869 },
3870 p = {
3871 v: !1
3872 };
3873 if (0 !== i && (f.addInitializer = old_createAddInitializerMethod(o, p)), l) {
3874 d = 2, u = Symbol(t);
3875 var v = {};
3876 0 === i ? (v.get = a.get, v.set = a.set) : 2 === i ? v.get = function () {
3877 return a.value;
3878 } : (1 !== i && 3 !== i || (v.get = function () {
3879 return a.get.call(this);
3880 }), 1 !== i && 4 !== i || (v.set = function (e) {
3881 a.set.call(this, e);
3882 })), f.access = v;
3883 } else d = 1, u = t;
3884 try {
3885 return e(s, Object.assign(f, old_createMetadataMethodsForProperty(r, d, u, p)));
3886 } finally {
3887 p.v = !0;
3888 }
3889 }
3890 function old_assertNotFinished(e, t) {
3891 if (e.v) throw new Error("attempted to call " + t + " after decoration was finished");
3892 }
3893 function old_assertMetadataKey(e) {
3894 if ("symbol" != typeof e) throw new TypeError("Metadata keys must be symbols, received: " + e);
3895 }
3896 function old_assertCallable(e, t) {
3897 if ("function" != typeof e) throw new TypeError(t + " must be a function");
3898 }
3899 function old_assertValidReturnValue(e, t) {
3900 var a = typeof t;
3901 if (1 === e) {
3902 if ("object" !== a || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
3903 void 0 !== t.get && old_assertCallable(t.get, "accessor.get"), void 0 !== t.set && old_assertCallable(t.set, "accessor.set"), void 0 !== t.init && old_assertCallable(t.init, "accessor.init"), void 0 !== t.initializer && old_assertCallable(t.initializer, "accessor.initializer");
3904 } else if ("function" !== a) {
3905 var r;
3906 throw r = 0 === e ? "field" : 10 === e ? "class" : "method", new TypeError(r + " decorators must return a function or void 0");
3907 }
3908 }
3909 function old_getInit(e) {
3910 var t;
3911 return null == (t = e.init) && (t = e.initializer) && "undefined" != typeof console && console.warn(".initializer has been renamed to .init as of March 2022"), t;
3912 }
3913 function old_applyMemberDec(e, t, a, r, o, i, n, l, s) {
3914 var c,
3915 d,
3916 u,
3917 f,
3918 p,
3919 v,
3920 h = a[0];
3921 if (n ? c = 0 === o || 1 === o ? {
3922 get: a[3],
3923 set: a[4]
3924 } : 3 === o ? {
3925 get: a[3]
3926 } : 4 === o ? {
3927 set: a[3]
3928 } : {
3929 value: a[3]
3930 } : 0 !== o && (c = Object.getOwnPropertyDescriptor(t, r)), 1 === o ? u = {
3931 get: c.get,
3932 set: c.set
3933 } : 2 === o ? u = c.value : 3 === o ? u = c.get : 4 === o && (u = c.set), "function" == typeof h) void 0 !== (f = old_memberDec(h, r, c, l, s, o, i, n, u)) && (old_assertValidReturnValue(o, f), 0 === o ? d = f : 1 === o ? (d = old_getInit(f), p = f.get || u.get, v = f.set || u.set, u = {
3934 get: p,
3935 set: v
3936 }) : u = f);else for (var y = h.length - 1; y >= 0; y--) {
3937 var b;
3938 if (void 0 !== (f = old_memberDec(h[y], r, c, l, s, o, i, n, u))) old_assertValidReturnValue(o, f), 0 === o ? b = f : 1 === o ? (b = old_getInit(f), p = f.get || u.get, v = f.set || u.set, u = {
3939 get: p,
3940 set: v
3941 }) : u = f, void 0 !== b && (void 0 === d ? d = b : "function" == typeof d ? d = [d, b] : d.push(b));
3942 }
3943 if (0 === o || 1 === o) {
3944 if (void 0 === d) d = function (e, t) {
3945 return t;
3946 };else if ("function" != typeof d) {
3947 var g = d;
3948 d = function (e, t) {
3949 for (var a = t, r = 0; r < g.length; r++) a = g[r].call(e, a);
3950 return a;
3951 };
3952 } else {
3953 var m = d;
3954 d = function (e, t) {
3955 return m.call(e, t);
3956 };
3957 }
3958 e.push(d);
3959 }
3960 0 !== o && (1 === o ? (c.get = u.get, c.set = u.set) : 2 === o ? c.value = u : 3 === o ? c.get = u : 4 === o && (c.set = u), n ? 1 === o ? (e.push(function (e, t) {
3961 return u.get.call(e, t);
3962 }), e.push(function (e, t) {
3963 return u.set.call(e, t);
3964 })) : 2 === o ? e.push(u) : e.push(function (e, t) {
3965 return u.call(e, t);
3966 }) : Object.defineProperty(t, r, c));
3967 }
3968 function old_applyMemberDecs(e, t, a, r, o) {
3969 for (var i, n, l = new Map(), s = new Map(), c = 0; c < o.length; c++) {
3970 var d = o[c];
3971 if (Array.isArray(d)) {
3972 var u,
3973 f,
3974 p,
3975 v = d[1],
3976 h = d[2],
3977 y = d.length > 3,
3978 b = v >= 5;
3979 if (b ? (u = t, f = r, 0 !== (v -= 5) && (p = n = n || [])) : (u = t.prototype, f = a, 0 !== v && (p = i = i || [])), 0 !== v && !y) {
3980 var g = b ? s : l,
3981 m = g.get(h) || 0;
3982 if (!0 === m || 3 === m && 4 !== v || 4 === m && 3 !== v) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + h);
3983 !m && v > 2 ? g.set(h, v) : g.set(h, !0);
3984 }
3985 old_applyMemberDec(e, u, d, h, v, b, y, f, p);
3986 }
3987 }
3988 old_pushInitializers(e, i), old_pushInitializers(e, n);
3989 }
3990 function old_pushInitializers(e, t) {
3991 t && e.push(function (e) {
3992 for (var a = 0; a < t.length; a++) t[a].call(e);
3993 return e;
3994 });
3995 }
3996 function old_applyClassDecs(e, t, a, r) {
3997 if (r.length > 0) {
3998 for (var o = [], i = t, n = t.name, l = r.length - 1; l >= 0; l--) {
3999 var s = {
4000 v: !1
4001 };
4002 try {
4003 var c = Object.assign({
4004 kind: "class",
4005 name: n,
4006 addInitializer: old_createAddInitializerMethod(o, s)
4007 }, old_createMetadataMethodsForProperty(a, 0, n, s)),
4008 d = r[l](i, c);
4009 } finally {
4010 s.v = !0;
4011 }
4012 void 0 !== d && (old_assertValidReturnValue(10, d), i = d);
4013 }
4014 e.push(i, function () {
4015 for (var e = 0; e < o.length; e++) o[e].call(i);
4016 });
4017 }
4018 }
4019 function _applyDecs(e, t, a) {
4020 var r = [],
4021 o = {},
4022 i = {};
4023 return old_applyMemberDecs(r, e, i, o, t), old_convertMetadataMapToFinal(e.prototype, i), old_applyClassDecs(r, e, o, a), old_convertMetadataMapToFinal(e, o), r;
4024 }
4025 function applyDecs2203Factory() {
4026 function createAddInitializerMethod(e, t) {
4027 return function (r) {
4028 !function (e, t) {
4029 if (e.v) throw new Error("attempted to call " + t + " after decoration was finished");
4030 }(t, "addInitializer"), assertCallable(r, "An initializer"), e.push(r);
4031 };
4032 }
4033 function memberDec(e, t, r, a, n, i, s, o) {
4034 var c;
4035 switch (n) {
4036 case 1:
4037 c = "accessor";
4038 break;
4039 case 2:
4040 c = "method";
4041 break;
4042 case 3:
4043 c = "getter";
4044 break;
4045 case 4:
4046 c = "setter";
4047 break;
4048 default:
4049 c = "field";
4050 }
4051 var l,
4052 u,
4053 f = {
4054 kind: c,
4055 name: s ? "#" + t : t,
4056 static: i,
4057 private: s
4058 },
4059 p = {
4060 v: !1
4061 };
4062 0 !== n && (f.addInitializer = createAddInitializerMethod(a, p)), 0 === n ? s ? (l = r.get, u = r.set) : (l = function () {
4063 return this[t];
4064 }, u = function (e) {
4065 this[t] = e;
4066 }) : 2 === n ? l = function () {
4067 return r.value;
4068 } : (1 !== n && 3 !== n || (l = function () {
4069 return r.get.call(this);
4070 }), 1 !== n && 4 !== n || (u = function (e) {
4071 r.set.call(this, e);
4072 })), f.access = l && u ? {
4073 get: l,
4074 set: u
4075 } : l ? {
4076 get: l
4077 } : {
4078 set: u
4079 };
4080 try {
4081 return e(o, f);
4082 } finally {
4083 p.v = !0;
4084 }
4085 }
4086 function assertCallable(e, t) {
4087 if ("function" != typeof e) throw new TypeError(t + " must be a function");
4088 }
4089 function assertValidReturnValue(e, t) {
4090 var r = typeof t;
4091 if (1 === e) {
4092 if ("object" !== r || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
4093 void 0 !== t.get && assertCallable(t.get, "accessor.get"), void 0 !== t.set && assertCallable(t.set, "accessor.set"), void 0 !== t.init && assertCallable(t.init, "accessor.init");
4094 } else if ("function" !== r) {
4095 var a;
4096 throw a = 0 === e ? "field" : 10 === e ? "class" : "method", new TypeError(a + " decorators must return a function or void 0");
4097 }
4098 }
4099 function applyMemberDec(e, t, r, a, n, i, s, o) {
4100 var c,
4101 l,
4102 u,
4103 f,
4104 p,
4105 d,
4106 h = r[0];
4107 if (s ? c = 0 === n || 1 === n ? {
4108 get: r[3],
4109 set: r[4]
4110 } : 3 === n ? {
4111 get: r[3]
4112 } : 4 === n ? {
4113 set: r[3]
4114 } : {
4115 value: r[3]
4116 } : 0 !== n && (c = Object.getOwnPropertyDescriptor(t, a)), 1 === n ? u = {
4117 get: c.get,
4118 set: c.set
4119 } : 2 === n ? u = c.value : 3 === n ? u = c.get : 4 === n && (u = c.set), "function" == typeof h) void 0 !== (f = memberDec(h, a, c, o, n, i, s, u)) && (assertValidReturnValue(n, f), 0 === n ? l = f : 1 === n ? (l = f.init, p = f.get || u.get, d = f.set || u.set, u = {
4120 get: p,
4121 set: d
4122 }) : u = f);else for (var v = h.length - 1; v >= 0; v--) {
4123 var g;
4124 if (void 0 !== (f = memberDec(h[v], a, c, o, n, i, s, u))) assertValidReturnValue(n, f), 0 === n ? g = f : 1 === n ? (g = f.init, p = f.get || u.get, d = f.set || u.set, u = {
4125 get: p,
4126 set: d
4127 }) : u = f, void 0 !== g && (void 0 === l ? l = g : "function" == typeof l ? l = [l, g] : l.push(g));
4128 }
4129 if (0 === n || 1 === n) {
4130 if (void 0 === l) l = function (e, t) {
4131 return t;
4132 };else if ("function" != typeof l) {
4133 var y = l;
4134 l = function (e, t) {
4135 for (var r = t, a = 0; a < y.length; a++) r = y[a].call(e, r);
4136 return r;
4137 };
4138 } else {
4139 var m = l;
4140 l = function (e, t) {
4141 return m.call(e, t);
4142 };
4143 }
4144 e.push(l);
4145 }
4146 0 !== n && (1 === n ? (c.get = u.get, c.set = u.set) : 2 === n ? c.value = u : 3 === n ? c.get = u : 4 === n && (c.set = u), s ? 1 === n ? (e.push(function (e, t) {
4147 return u.get.call(e, t);
4148 }), e.push(function (e, t) {
4149 return u.set.call(e, t);
4150 })) : 2 === n ? e.push(u) : e.push(function (e, t) {
4151 return u.call(e, t);
4152 }) : Object.defineProperty(t, a, c));
4153 }
4154 function pushInitializers(e, t) {
4155 t && e.push(function (e) {
4156 for (var r = 0; r < t.length; r++) t[r].call(e);
4157 return e;
4158 });
4159 }
4160 return function (e, t, r) {
4161 var a = [];
4162 return function (e, t, r) {
4163 for (var a, n, i = new Map(), s = new Map(), o = 0; o < r.length; o++) {
4164 var c = r[o];
4165 if (Array.isArray(c)) {
4166 var l,
4167 u,
4168 f = c[1],
4169 p = c[2],
4170 d = c.length > 3,
4171 h = f >= 5;
4172 if (h ? (l = t, 0 != (f -= 5) && (u = n = n || [])) : (l = t.prototype, 0 !== f && (u = a = a || [])), 0 !== f && !d) {
4173 var v = h ? s : i,
4174 g = v.get(p) || 0;
4175 if (!0 === g || 3 === g && 4 !== f || 4 === g && 3 !== f) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + p);
4176 !g && f > 2 ? v.set(p, f) : v.set(p, !0);
4177 }
4178 applyMemberDec(e, l, c, p, f, h, d, u);
4179 }
4180 }
4181 pushInitializers(e, a), pushInitializers(e, n);
4182 }(a, e, t), function (e, t, r) {
4183 if (r.length > 0) {
4184 for (var a = [], n = t, i = t.name, s = r.length - 1; s >= 0; s--) {
4185 var o = {
4186 v: !1
4187 };
4188 try {
4189 var c = r[s](n, {
4190 kind: "class",
4191 name: i,
4192 addInitializer: createAddInitializerMethod(a, o)
4193 });
4194 } finally {
4195 o.v = !0;
4196 }
4197 void 0 !== c && (assertValidReturnValue(10, c), n = c);
4198 }
4199 e.push(n, function () {
4200 for (var e = 0; e < a.length; e++) a[e].call(n);
4201 });
4202 }
4203 }(a, e, r), a;
4204 };
4205 }
4206 var applyDecs2203Impl;
4207 function _applyDecs2203(e, t, r) {
4208 return (applyDecs2203Impl = applyDecs2203Impl || applyDecs2203Factory())(e, t, r);
4209 }
4210 function applyDecs2203RFactory() {
4211 function createAddInitializerMethod(e, t) {
4212 return function (r) {
4213 !function (e, t) {
4214 if (e.v) throw new Error("attempted to call " + t + " after decoration was finished");
4215 }(t, "addInitializer"), assertCallable(r, "An initializer"), e.push(r);
4216 };
4217 }
4218 function memberDec(e, t, r, n, a, i, s, o) {
4219 var c;
4220 switch (a) {
4221 case 1:
4222 c = "accessor";
4223 break;
4224 case 2:
4225 c = "method";
4226 break;
4227 case 3:
4228 c = "getter";
4229 break;
4230 case 4:
4231 c = "setter";
4232 break;
4233 default:
4234 c = "field";
4235 }
4236 var l,
4237 u,
4238 f = {
4239 kind: c,
4240 name: s ? "#" + t : t,
4241 static: i,
4242 private: s
4243 },
4244 p = {
4245 v: !1
4246 };
4247 0 !== a && (f.addInitializer = createAddInitializerMethod(n, p)), 0 === a ? s ? (l = r.get, u = r.set) : (l = function () {
4248 return this[t];
4249 }, u = function (e) {
4250 this[t] = e;
4251 }) : 2 === a ? l = function () {
4252 return r.value;
4253 } : (1 !== a && 3 !== a || (l = function () {
4254 return r.get.call(this);
4255 }), 1 !== a && 4 !== a || (u = function (e) {
4256 r.set.call(this, e);
4257 })), f.access = l && u ? {
4258 get: l,
4259 set: u
4260 } : l ? {
4261 get: l
4262 } : {
4263 set: u
4264 };
4265 try {
4266 return e(o, f);
4267 } finally {
4268 p.v = !0;
4269 }
4270 }
4271 function assertCallable(e, t) {
4272 if ("function" != typeof e) throw new TypeError(t + " must be a function");
4273 }
4274 function assertValidReturnValue(e, t) {
4275 var r = typeof t;
4276 if (1 === e) {
4277 if ("object" !== r || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
4278 void 0 !== t.get && assertCallable(t.get, "accessor.get"), void 0 !== t.set && assertCallable(t.set, "accessor.set"), void 0 !== t.init && assertCallable(t.init, "accessor.init");
4279 } else if ("function" !== r) {
4280 var n;
4281 throw n = 0 === e ? "field" : 10 === e ? "class" : "method", new TypeError(n + " decorators must return a function or void 0");
4282 }
4283 }
4284 function applyMemberDec(e, t, r, n, a, i, s, o) {
4285 var c,
4286 l,
4287 u,
4288 f,
4289 p,
4290 d,
4291 h = r[0];
4292 if (s ? c = 0 === a || 1 === a ? {
4293 get: r[3],
4294 set: r[4]
4295 } : 3 === a ? {
4296 get: r[3]
4297 } : 4 === a ? {
4298 set: r[3]
4299 } : {
4300 value: r[3]
4301 } : 0 !== a && (c = Object.getOwnPropertyDescriptor(t, n)), 1 === a ? u = {
4302 get: c.get,
4303 set: c.set
4304 } : 2 === a ? u = c.value : 3 === a ? u = c.get : 4 === a && (u = c.set), "function" == typeof h) void 0 !== (f = memberDec(h, n, c, o, a, i, s, u)) && (assertValidReturnValue(a, f), 0 === a ? l = f : 1 === a ? (l = f.init, p = f.get || u.get, d = f.set || u.set, u = {
4305 get: p,
4306 set: d
4307 }) : u = f);else for (var v = h.length - 1; v >= 0; v--) {
4308 var g;
4309 if (void 0 !== (f = memberDec(h[v], n, c, o, a, i, s, u))) assertValidReturnValue(a, f), 0 === a ? g = f : 1 === a ? (g = f.init, p = f.get || u.get, d = f.set || u.set, u = {
4310 get: p,
4311 set: d
4312 }) : u = f, void 0 !== g && (void 0 === l ? l = g : "function" == typeof l ? l = [l, g] : l.push(g));
4313 }
4314 if (0 === a || 1 === a) {
4315 if (void 0 === l) l = function (e, t) {
4316 return t;
4317 };else if ("function" != typeof l) {
4318 var y = l;
4319 l = function (e, t) {
4320 for (var r = t, n = 0; n < y.length; n++) r = y[n].call(e, r);
4321 return r;
4322 };
4323 } else {
4324 var m = l;
4325 l = function (e, t) {
4326 return m.call(e, t);
4327 };
4328 }
4329 e.push(l);
4330 }
4331 0 !== a && (1 === a ? (c.get = u.get, c.set = u.set) : 2 === a ? c.value = u : 3 === a ? c.get = u : 4 === a && (c.set = u), s ? 1 === a ? (e.push(function (e, t) {
4332 return u.get.call(e, t);
4333 }), e.push(function (e, t) {
4334 return u.set.call(e, t);
4335 })) : 2 === a ? e.push(u) : e.push(function (e, t) {
4336 return u.call(e, t);
4337 }) : Object.defineProperty(t, n, c));
4338 }
4339 function applyMemberDecs(e, t) {
4340 for (var r, n, a = [], i = new Map(), s = new Map(), o = 0; o < t.length; o++) {
4341 var c = t[o];
4342 if (Array.isArray(c)) {
4343 var l,
4344 u,
4345 f = c[1],
4346 p = c[2],
4347 d = c.length > 3,
4348 h = f >= 5;
4349 if (h ? (l = e, 0 !== (f -= 5) && (u = n = n || [])) : (l = e.prototype, 0 !== f && (u = r = r || [])), 0 !== f && !d) {
4350 var v = h ? s : i,
4351 g = v.get(p) || 0;
4352 if (!0 === g || 3 === g && 4 !== f || 4 === g && 3 !== f) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + p);
4353 !g && f > 2 ? v.set(p, f) : v.set(p, !0);
4354 }
4355 applyMemberDec(a, l, c, p, f, h, d, u);
4356 }
4357 }
4358 return pushInitializers(a, r), pushInitializers(a, n), a;
4359 }
4360 function pushInitializers(e, t) {
4361 t && e.push(function (e) {
4362 for (var r = 0; r < t.length; r++) t[r].call(e);
4363 return e;
4364 });
4365 }
4366 return function (e, t, r) {
4367 return {
4368 e: applyMemberDecs(e, t),
4369 get c() {
4370 return function (e, t) {
4371 if (t.length > 0) {
4372 for (var r = [], n = e, a = e.name, i = t.length - 1; i >= 0; i--) {
4373 var s = {
4374 v: !1
4375 };
4376 try {
4377 var o = t[i](n, {
4378 kind: "class",
4379 name: a,
4380 addInitializer: createAddInitializerMethod(r, s)
4381 });
4382 } finally {
4383 s.v = !0;
4384 }
4385 void 0 !== o && (assertValidReturnValue(10, o), n = o);
4386 }
4387 return [n, function () {
4388 for (var e = 0; e < r.length; e++) r[e].call(n);
4389 }];
4390 }
4391 }(e, r);
4392 }
4393 };
4394 };
4395 }
4396 function _applyDecs2203R(e, t, r) {
4397 return (_applyDecs2203R = applyDecs2203RFactory())(e, t, r);
4398 }
4399 function applyDecs2301Factory() {
4400 function createAddInitializerMethod(e, t) {
4401 return function (r) {
4402 !function (e, t) {
4403 if (e.v) throw new Error("attempted to call " + t + " after decoration was finished");
4404 }(t, "addInitializer"), assertCallable(r, "An initializer"), e.push(r);
4405 };
4406 }
4407 function assertInstanceIfPrivate(e, t) {
4408 if (!e(t)) throw new TypeError("Attempted to access private element on non-instance");
4409 }
4410 function memberDec(e, t, r, n, a, i, s, o, c) {
4411 var u;
4412 switch (a) {
4413 case 1:
4414 u = "accessor";
4415 break;
4416 case 2:
4417 u = "method";
4418 break;
4419 case 3:
4420 u = "getter";
4421 break;
4422 case 4:
4423 u = "setter";
4424 break;
4425 default:
4426 u = "field";
4427 }
4428 var l,
4429 f,
4430 p = {
4431 kind: u,
4432 name: s ? "#" + t : t,
4433 static: i,
4434 private: s
4435 },
4436 d = {
4437 v: !1
4438 };
4439 if (0 !== a && (p.addInitializer = createAddInitializerMethod(n, d)), s || 0 !== a && 2 !== a) {
4440 if (2 === a) l = function (e) {
4441 return assertInstanceIfPrivate(c, e), r.value;
4442 };else {
4443 var h = 0 === a || 1 === a;
4444 (h || 3 === a) && (l = s ? function (e) {
4445 return assertInstanceIfPrivate(c, e), r.get.call(e);
4446 } : function (e) {
4447 return r.get.call(e);
4448 }), (h || 4 === a) && (f = s ? function (e, t) {
4449 assertInstanceIfPrivate(c, e), r.set.call(e, t);
4450 } : function (e, t) {
4451 r.set.call(e, t);
4452 });
4453 }
4454 } else l = function (e) {
4455 return e[t];
4456 }, 0 === a && (f = function (e, r) {
4457 e[t] = r;
4458 });
4459 var v = s ? c.bind() : function (e) {
4460 return t in e;
4461 };
4462 p.access = l && f ? {
4463 get: l,
4464 set: f,
4465 has: v
4466 } : l ? {
4467 get: l,
4468 has: v
4469 } : {
4470 set: f,
4471 has: v
4472 };
4473 try {
4474 return e(o, p);
4475 } finally {
4476 d.v = !0;
4477 }
4478 }
4479 function assertCallable(e, t) {
4480 if ("function" != typeof e) throw new TypeError(t + " must be a function");
4481 }
4482 function assertValidReturnValue(e, t) {
4483 var r = typeof t;
4484 if (1 === e) {
4485 if ("object" !== r || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
4486 void 0 !== t.get && assertCallable(t.get, "accessor.get"), void 0 !== t.set && assertCallable(t.set, "accessor.set"), void 0 !== t.init && assertCallable(t.init, "accessor.init");
4487 } else if ("function" !== r) {
4488 var n;
4489 throw n = 0 === e ? "field" : 10 === e ? "class" : "method", new TypeError(n + " decorators must return a function or void 0");
4490 }
4491 }
4492 function curryThis2(e) {
4493 return function (t) {
4494 e(this, t);
4495 };
4496 }
4497 function applyMemberDec(e, t, r, n, a, i, s, o, c) {
4498 var u,
4499 l,
4500 f,
4501 p,
4502 d,
4503 h,
4504 v,
4505 g = r[0];
4506 if (s ? u = 0 === a || 1 === a ? {
4507 get: (p = r[3], function () {
4508 return p(this);
4509 }),
4510 set: curryThis2(r[4])
4511 } : 3 === a ? {
4512 get: r[3]
4513 } : 4 === a ? {
4514 set: r[3]
4515 } : {
4516 value: r[3]
4517 } : 0 !== a && (u = Object.getOwnPropertyDescriptor(t, n)), 1 === a ? f = {
4518 get: u.get,
4519 set: u.set
4520 } : 2 === a ? f = u.value : 3 === a ? f = u.get : 4 === a && (f = u.set), "function" == typeof g) void 0 !== (d = memberDec(g, n, u, o, a, i, s, f, c)) && (assertValidReturnValue(a, d), 0 === a ? l = d : 1 === a ? (l = d.init, h = d.get || f.get, v = d.set || f.set, f = {
4521 get: h,
4522 set: v
4523 }) : f = d);else for (var y = g.length - 1; y >= 0; y--) {
4524 var m;
4525 if (void 0 !== (d = memberDec(g[y], n, u, o, a, i, s, f, c))) assertValidReturnValue(a, d), 0 === a ? m = d : 1 === a ? (m = d.init, h = d.get || f.get, v = d.set || f.set, f = {
4526 get: h,
4527 set: v
4528 }) : f = d, void 0 !== m && (void 0 === l ? l = m : "function" == typeof l ? l = [l, m] : l.push(m));
4529 }
4530 if (0 === a || 1 === a) {
4531 if (void 0 === l) l = function (e, t) {
4532 return t;
4533 };else if ("function" != typeof l) {
4534 var b = l;
4535 l = function (e, t) {
4536 for (var r = t, n = 0; n < b.length; n++) r = b[n].call(e, r);
4537 return r;
4538 };
4539 } else {
4540 var I = l;
4541 l = function (e, t) {
4542 return I.call(e, t);
4543 };
4544 }
4545 e.push(l);
4546 }
4547 0 !== a && (1 === a ? (u.get = f.get, u.set = f.set) : 2 === a ? u.value = f : 3 === a ? u.get = f : 4 === a && (u.set = f), s ? 1 === a ? (e.push(function (e, t) {
4548 return f.get.call(e, t);
4549 }), e.push(function (e, t) {
4550 return f.set.call(e, t);
4551 })) : 2 === a ? e.push(f) : e.push(function (e, t) {
4552 return f.call(e, t);
4553 }) : Object.defineProperty(t, n, u));
4554 }
4555 function applyMemberDecs(e, t, r) {
4556 for (var n, a, i, s = [], o = new Map(), c = new Map(), u = 0; u < t.length; u++) {
4557 var l = t[u];
4558 if (Array.isArray(l)) {
4559 var f,
4560 p,
4561 d = l[1],
4562 h = l[2],
4563 v = l.length > 3,
4564 g = d >= 5,
4565 y = r;
4566 if (g ? (f = e, 0 !== (d -= 5) && (p = a = a || []), v && !i && (i = function (t) {
4567 return _checkInRHS(t) === e;
4568 }), y = i) : (f = e.prototype, 0 !== d && (p = n = n || [])), 0 !== d && !v) {
4569 var m = g ? c : o,
4570 b = m.get(h) || 0;
4571 if (!0 === b || 3 === b && 4 !== d || 4 === b && 3 !== d) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + h);
4572 !b && d > 2 ? m.set(h, d) : m.set(h, !0);
4573 }
4574 applyMemberDec(s, f, l, h, d, g, v, p, y);
4575 }
4576 }
4577 return pushInitializers(s, n), pushInitializers(s, a), s;
4578 }
4579 function pushInitializers(e, t) {
4580 t && e.push(function (e) {
4581 for (var r = 0; r < t.length; r++) t[r].call(e);
4582 return e;
4583 });
4584 }
4585 return function (e, t, r, n) {
4586 return {
4587 e: applyMemberDecs(e, t, n),
4588 get c() {
4589 return function (e, t) {
4590 if (t.length > 0) {
4591 for (var r = [], n = e, a = e.name, i = t.length - 1; i >= 0; i--) {
4592 var s = {
4593 v: !1
4594 };
4595 try {
4596 var o = t[i](n, {
4597 kind: "class",
4598 name: a,
4599 addInitializer: createAddInitializerMethod(r, s)
4600 });
4601 } finally {
4602 s.v = !0;
4603 }
4604 void 0 !== o && (assertValidReturnValue(10, o), n = o);
4605 }
4606 return [n, function () {
4607 for (var e = 0; e < r.length; e++) r[e].call(n);
4608 }];
4609 }
4610 }(e, r);
4611 }
4612 };
4613 };
4614 }
4615 function _applyDecs2301(e, t, r, n) {
4616 return (_applyDecs2301 = applyDecs2301Factory())(e, t, r, n);
4617 }
4618 function createAddInitializerMethod(e, t) {
4619 return function (r) {
4620 assertNotFinished(t, "addInitializer"), assertCallable(r, "An initializer"), e.push(r);
4621 };
4622 }
4623 function assertInstanceIfPrivate(e, t) {
4624 if (!e(t)) throw new TypeError("Attempted to access private element on non-instance");
4625 }
4626 function memberDec(e, t, r, a, n, i, s, o, c, l, u) {
4627 var f;
4628 switch (i) {
4629 case 1:
4630 f = "accessor";
4631 break;
4632 case 2:
4633 f = "method";
4634 break;
4635 case 3:
4636 f = "getter";
4637 break;
4638 case 4:
4639 f = "setter";
4640 break;
4641 default:
4642 f = "field";
4643 }
4644 var d,
4645 p,
4646 h = {
4647 kind: f,
4648 name: o ? "#" + r : r,
4649 static: s,
4650 private: o,
4651 metadata: u
4652 },
4653 v = {
4654 v: !1
4655 };
4656 if (0 !== i && (h.addInitializer = createAddInitializerMethod(n, v)), o || 0 !== i && 2 !== i) {
4657 if (2 === i) d = function (e) {
4658 return assertInstanceIfPrivate(l, e), a.value;
4659 };else {
4660 var y = 0 === i || 1 === i;
4661 (y || 3 === i) && (d = o ? function (e) {
4662 return assertInstanceIfPrivate(l, e), a.get.call(e);
4663 } : function (e) {
4664 return a.get.call(e);
4665 }), (y || 4 === i) && (p = o ? function (e, t) {
4666 assertInstanceIfPrivate(l, e), a.set.call(e, t);
4667 } : function (e, t) {
4668 a.set.call(e, t);
4669 });
4670 }
4671 } else d = function (e) {
4672 return e[r];
4673 }, 0 === i && (p = function (e, t) {
4674 e[r] = t;
4675 });
4676 var m = o ? l.bind() : function (e) {
4677 return r in e;
4678 };
4679 h.access = d && p ? {
4680 get: d,
4681 set: p,
4682 has: m
4683 } : d ? {
4684 get: d,
4685 has: m
4686 } : {
4687 set: p,
4688 has: m
4689 };
4690 try {
4691 return e.call(t, c, h);
4692 } finally {
4693 v.v = !0;
4694 }
4695 }
4696 function assertNotFinished(e, t) {
4697 if (e.v) throw new Error("attempted to call " + t + " after decoration was finished");
4698 }
4699 function assertCallable(e, t) {
4700 if ("function" != typeof e) throw new TypeError(t + " must be a function");
4701 }
4702 function assertValidReturnValue(e, t) {
4703 var r = typeof t;
4704 if (1 === e) {
4705 if ("object" !== r || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
4706 void 0 !== t.get && assertCallable(t.get, "accessor.get"), void 0 !== t.set && assertCallable(t.set, "accessor.set"), void 0 !== t.init && assertCallable(t.init, "accessor.init");
4707 } else if ("function" !== r) {
4708 var a;
4709 throw a = 0 === e ? "field" : 5 === e ? "class" : "method", new TypeError(a + " decorators must return a function or void 0");
4710 }
4711 }
4712 function curryThis1(e) {
4713 return function () {
4714 return e(this);
4715 };
4716 }
4717 function curryThis2(e) {
4718 return function (t) {
4719 e(this, t);
4720 };
4721 }
4722 function applyMemberDec(e, t, r, a, n, i, s, o, c, l, u) {
4723 var f,
4724 d,
4725 p,
4726 h,
4727 v,
4728 y,
4729 m = r[0];
4730 a || Array.isArray(m) || (m = [m]), o ? f = 0 === i || 1 === i ? {
4731 get: curryThis1(r[3]),
4732 set: curryThis2(r[4])
4733 } : 3 === i ? {
4734 get: r[3]
4735 } : 4 === i ? {
4736 set: r[3]
4737 } : {
4738 value: r[3]
4739 } : 0 !== i && (f = Object.getOwnPropertyDescriptor(t, n)), 1 === i ? p = {
4740 get: f.get,
4741 set: f.set
4742 } : 2 === i ? p = f.value : 3 === i ? p = f.get : 4 === i && (p = f.set);
4743 for (var g = a ? 2 : 1, b = m.length - 1; b >= 0; b -= g) {
4744 var I;
4745 if (void 0 !== (h = memberDec(m[b], a ? m[b - 1] : void 0, n, f, c, i, s, o, p, l, u))) assertValidReturnValue(i, h), 0 === i ? I = h : 1 === i ? (I = h.init, v = h.get || p.get, y = h.set || p.set, p = {
4746 get: v,
4747 set: y
4748 }) : p = h, void 0 !== I && (void 0 === d ? d = I : "function" == typeof d ? d = [d, I] : d.push(I));
4749 }
4750 if (0 === i || 1 === i) {
4751 if (void 0 === d) d = function (e, t) {
4752 return t;
4753 };else if ("function" != typeof d) {
4754 var w = d;
4755 d = function (e, t) {
4756 for (var r = t, a = w.length - 1; a >= 0; a--) r = w[a].call(e, r);
4757 return r;
4758 };
4759 } else {
4760 var M = d;
4761 d = function (e, t) {
4762 return M.call(e, t);
4763 };
4764 }
4765 e.push(d);
4766 }
4767 0 !== i && (1 === i ? (f.get = p.get, f.set = p.set) : 2 === i ? f.value = p : 3 === i ? f.get = p : 4 === i && (f.set = p), o ? 1 === i ? (e.push(function (e, t) {
4768 return p.get.call(e, t);
4769 }), e.push(function (e, t) {
4770 return p.set.call(e, t);
4771 })) : 2 === i ? e.push(p) : e.push(function (e, t) {
4772 return p.call(e, t);
4773 }) : Object.defineProperty(t, n, f));
4774 }
4775 function applyMemberDecs(e, t, r, a) {
4776 for (var n, i, s, o = [], c = new Map(), l = new Map(), u = 0; u < t.length; u++) {
4777 var f = t[u];
4778 if (Array.isArray(f)) {
4779 var d,
4780 p,
4781 h = f[1],
4782 v = f[2],
4783 y = f.length > 3,
4784 m = 16 & h,
4785 g = !!(8 & h),
4786 b = r;
4787 if (h &= 7, g ? (d = e, 0 !== h && (p = i = i || []), y && !s && (s = function (t) {
4788 return _checkInRHS(t) === e;
4789 }), b = s) : (d = e.prototype, 0 !== h && (p = n = n || [])), 0 !== h && !y) {
4790 var I = g ? l : c,
4791 w = I.get(v) || 0;
4792 if (!0 === w || 3 === w && 4 !== h || 4 === w && 3 !== h) throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + v);
4793 I.set(v, !(!w && h > 2) || h);
4794 }
4795 applyMemberDec(o, d, f, m, v, h, g, y, p, b, a);
4796 }
4797 }
4798 return pushInitializers(o, n), pushInitializers(o, i), o;
4799 }
4800 function pushInitializers(e, t) {
4801 t && e.push(function (e) {
4802 for (var r = 0; r < t.length; r++) t[r].call(e);
4803 return e;
4804 });
4805 }
4806 function applyClassDecs(e, t, r, a) {
4807 if (t.length) {
4808 for (var n = [], i = e, s = e.name, o = r ? 2 : 1, c = t.length - 1; c >= 0; c -= o) {
4809 var l = {
4810 v: !1
4811 };
4812 try {
4813 var u = t[c].call(r ? t[c - 1] : void 0, i, {
4814 kind: "class",
4815 name: s,
4816 addInitializer: createAddInitializerMethod(n, l),
4817 metadata: a
4818 });
4819 } finally {
4820 l.v = !0;
4821 }
4822 void 0 !== u && (assertValidReturnValue(5, u), i = u);
4823 }
4824 return [defineMetadata(i, a), function () {
4825 for (var e = 0; e < n.length; e++) n[e].call(i);
4826 }];
4827 }
4828 }
4829 function defineMetadata(e, t) {
4830 return Object.defineProperty(e, Symbol.metadata || Symbol.for("Symbol.metadata"), {
4831 configurable: !0,
4832 enumerable: !0,
4833 value: t
4834 });
4835 }
4836 function _applyDecs2305(e, t, r, a, n, i) {
4837 if (arguments.length >= 6) var s = i[Symbol.metadata || Symbol.for("Symbol.metadata")];
4838 var o = Object.create(void 0 === s ? null : s),
4839 c = applyMemberDecs(e, t, n, o);
4840 return r.length || defineMetadata(e, o), {
4841 e: c,
4842 get c() {
4843 return applyClassDecs(e, r, a, o);
4844 }
4845 };
4846 }
4847 function _asyncGeneratorDelegate(t) {
4848 var e = {},
4849 n = !1;
4850 function pump(e, r) {
4851 return n = !0, r = new Promise(function (n) {
4852 n(t[e](r));
4853 }), {
4854 done: !1,
4855 value: new _OverloadYield(r, 1)
4856 };
4857 }
4858 return e["undefined" != typeof Symbol && Symbol.iterator || "@@iterator"] = function () {
4859 return this;
4860 }, e.next = function (t) {
4861 return n ? (n = !1, t) : pump("next", t);
4862 }, "function" == typeof t.throw && (e.throw = function (t) {
4863 if (n) throw n = !1, t;
4864 return pump("throw", t);
4865 }), "function" == typeof t.return && (e.return = function (t) {
4866 return n ? (n = !1, t) : pump("return", t);
4867 }), e;
4868 }
4869 function _asyncIterator(r) {
4870 var n,
4871 t,
4872 o,
4873 e = 2;
4874 for ("undefined" != typeof Symbol && (t = Symbol.asyncIterator, o = Symbol.iterator); e--;) {
4875 if (t && null != (n = r[t])) return n.call(r);
4876 if (o && null != (n = r[o])) return new AsyncFromSyncIterator(n.call(r));
4877 t = "@@asyncIterator", o = "@@iterator";
4878 }
4879 throw new TypeError("Object is not async iterable");
4880 }
4881 function AsyncFromSyncIterator(r) {
4882 function AsyncFromSyncIteratorContinuation(r) {
4883 if (Object(r) !== r) return Promise.reject(new TypeError(r + " is not an object."));
4884 var n = r.done;
4885 return Promise.resolve(r.value).then(function (r) {
4886 return {
4887 value: r,
4888 done: n
4889 };
4890 });
4891 }
4892 return AsyncFromSyncIterator = function (r) {
4893 this.s = r, this.n = r.next;
4894 }, AsyncFromSyncIterator.prototype = {
4895 s: null,
4896 n: null,
4897 next: function () {
4898 return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments));
4899 },
4900 return: function (r) {
4901 var n = this.s.return;
4902 return void 0 === n ? Promise.resolve({
4903 value: r,
4904 done: !0
4905 }) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments));
4906 },
4907 throw: function (r) {
4908 var n = this.s.return;
4909 return void 0 === n ? Promise.reject(r) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments));
4910 }
4911 }, new AsyncFromSyncIterator(r);
4912 }
4913 function _awaitAsyncGenerator(e) {
4914 return new _OverloadYield(e, 0);
4915 }
4916 function _checkInRHS(e) {
4917 if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null"));
4918 return e;
4919 }
4920 function _defineAccessor(e, r, n, t) {
4921 var c = {
4922 configurable: !0,
4923 enumerable: !0
4924 };
4925 return c[e] = t, Object.defineProperty(r, n, c);
4926 }
4927 function dispose_SuppressedError(r, e) {
4928 return "undefined" != typeof SuppressedError ? dispose_SuppressedError = SuppressedError : (dispose_SuppressedError = function (r, e) {
4929 this.suppressed = r, this.error = e, this.stack = new Error().stack;
4930 }, dispose_SuppressedError.prototype = Object.create(Error.prototype, {
4931 constructor: {
4932 value: dispose_SuppressedError,
4933 writable: !0,
4934 configurable: !0
4935 }
4936 })), new dispose_SuppressedError(r, e);
4937 }
4938 function _dispose(r, e, s) {
4939 function next() {
4940 for (; r.length > 0;) try {
4941 var o = r.pop(),
4942 p = o.d.call(o.v);
4943 if (o.a) return Promise.resolve(p).then(next, err);
4944 } catch (r) {
4945 return err(r);
4946 }
4947 if (s) throw e;
4948 }
4949 function err(r) {
4950 return e = s ? new dispose_SuppressedError(r, e) : r, s = !0, next();
4951 }
4952 return next();
4953 }
4954 function _importDeferProxy(e) {
4955 var t = null,
4956 constValue = function (e) {
4957 return function () {
4958 return e;
4959 };
4960 },
4961 proxy = function (r) {
4962 return function (n, o, f) {
4963 return null === t && (t = e()), r(t, o, f);
4964 };
4965 };
4966 return new Proxy({}, {
4967 defineProperty: constValue(!1),
4968 deleteProperty: constValue(!1),
4969 get: proxy(Reflect.get),
4970 getOwnPropertyDescriptor: proxy(Reflect.getOwnPropertyDescriptor),
4971 getPrototypeOf: constValue(null),
4972 isExtensible: constValue(!1),
4973 has: proxy(Reflect.has),
4974 ownKeys: proxy(Reflect.ownKeys),
4975 preventExtensions: constValue(!0),
4976 set: constValue(!1),
4977 setPrototypeOf: constValue(!1)
4978 });
4979 }
4980 function _iterableToArrayLimit(r, l) {
4981 var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
4982 if (null != t) {
4983 var e,
4984 n,
4985 i,
4986 u,
4987 a = [],
4988 f = !0,
4989 o = !1;
4990 try {
4991 if (i = (t = t.call(r)).next, 0 === l) {
4992 if (Object(t) !== t) return;
4993 f = !1;
4994 } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
4995 } catch (r) {
4996 o = !0, n = r;
4997 } finally {
4998 try {
4999 if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
5000 } finally {
5001 if (o) throw n;
5002 }
5003 }
5004 return a;
5005 }
5006 }
5007 function _iterableToArrayLimitLoose(e, r) {
5008 var t = e && ("undefined" != typeof Symbol && e[Symbol.iterator] || e["@@iterator"]);
5009 if (null != t) {
5010 var o,
5011 l = [];
5012 for (t = t.call(e); e.length < r && !(o = t.next()).done;) l.push(o.value);
5013 return l;
5014 }
5015 }
5016 var REACT_ELEMENT_TYPE;
5017 function _jsx(e, r, E, l) {
5018 REACT_ELEMENT_TYPE || (REACT_ELEMENT_TYPE = "function" == typeof Symbol && Symbol.for && Symbol.for("react.element") || 60103);
5019 var o = e && e.defaultProps,
5020 n = arguments.length - 3;
5021 if (r || 0 === n || (r = {
5022 children: void 0
5023 }), 1 === n) r.children = l;else if (n > 1) {
5024 for (var t = new Array(n), f = 0; f < n; f++) t[f] = arguments[f + 3];
5025 r.children = t;
5026 }
5027 if (r && o) for (var i in o) void 0 === r[i] && (r[i] = o[i]);else r || (r = o || {});
5028 return {
5029 $$typeof: REACT_ELEMENT_TYPE,
5030 type: e,
5031 key: void 0 === E ? null : "" + E,
5032 ref: null,
5033 props: r,
5034 _owner: null
5035 };
5036 }
5037 function ownKeys(e, r) {
5038 var t = Object.keys(e);
5039 if (Object.getOwnPropertySymbols) {
5040 var o = Object.getOwnPropertySymbols(e);
5041 r && (o = o.filter(function (r) {
5042 return Object.getOwnPropertyDescriptor(e, r).enumerable;
5043 })), t.push.apply(t, o);
5044 }
5045 return t;
5046 }
5047 function _objectSpread2(e) {
5048 for (var r = 1; r < arguments.length; r++) {
5049 var t = null != arguments[r] ? arguments[r] : {};
5050 r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
5051 _defineProperty(e, r, t[r]);
5052 }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
5053 Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
5054 });
5055 }
5056 return e;
5057 }
5058 function _regeneratorRuntime() {
5059 "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
5060 _regeneratorRuntime = function () {
5061 return e;
5062 };
5063 var t,
5064 e = {},
5065 r = Object.prototype,
5066 n = r.hasOwnProperty,
5067 o = Object.defineProperty || function (t, e, r) {
5068 t[e] = r.value;
5069 },
5070 i = "function" == typeof Symbol ? Symbol : {},
5071 a = i.iterator || "@@iterator",
5072 c = i.asyncIterator || "@@asyncIterator",
5073 u = i.toStringTag || "@@toStringTag";
5074 function define(t, e, r) {
5075 return Object.defineProperty(t, e, {
5076 value: r,
5077 enumerable: !0,
5078 configurable: !0,
5079 writable: !0
5080 }), t[e];
5081 }
5082 try {
5083 define({}, "");
5084 } catch (t) {
5085 define = function (t, e, r) {
5086 return t[e] = r;
5087 };
5088 }
5089 function wrap(t, e, r, n) {
5090 var i = e && e.prototype instanceof Generator ? e : Generator,
5091 a = Object.create(i.prototype),
5092 c = new Context(n || []);
5093 return o(a, "_invoke", {
5094 value: makeInvokeMethod(t, r, c)
5095 }), a;
5096 }
5097 function tryCatch(t, e, r) {
5098 try {
5099 return {
5100 type: "normal",
5101 arg: t.call(e, r)
5102 };
5103 } catch (t) {
5104 return {
5105 type: "throw",
5106 arg: t
5107 };
5108 }
5109 }
5110 e.wrap = wrap;
5111 var h = "suspendedStart",
5112 l = "suspendedYield",
5113 f = "executing",
5114 s = "completed",
5115 y = {};
5116 function Generator() {}
5117 function GeneratorFunction() {}
5118 function GeneratorFunctionPrototype() {}
5119 var p = {};
5120 define(p, a, function () {
5121 return this;
5122 });
5123 var d = Object.getPrototypeOf,
5124 v = d && d(d(values([])));
5125 v && v !== r && n.call(v, a) && (p = v);
5126 var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p);
5127 function defineIteratorMethods(t) {
5128 ["next", "throw", "return"].forEach(function (e) {
5129 define(t, e, function (t) {
5130 return this._invoke(e, t);
5131 });
5132 });
5133 }
5134 function AsyncIterator(t, e) {
5135 function invoke(r, o, i, a) {
5136 var c = tryCatch(t[r], t, o);
5137 if ("throw" !== c.type) {
5138 var u = c.arg,
5139 h = u.value;
5140 return h && "object" == typeof h && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) {
5141 invoke("next", t, i, a);
5142 }, function (t) {
5143 invoke("throw", t, i, a);
5144 }) : e.resolve(h).then(function (t) {
5145 u.value = t, i(u);
5146 }, function (t) {
5147 return invoke("throw", t, i, a);
5148 });
5149 }
5150 a(c.arg);
5151 }
5152 var r;
5153 o(this, "_invoke", {
5154 value: function (t, n) {
5155 function callInvokeWithMethodAndArg() {
5156 return new e(function (e, r) {
5157 invoke(t, n, e, r);
5158 });
5159 }
5160 return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
5161 }
5162 });
5163 }
5164 function makeInvokeMethod(e, r, n) {
5165 var o = h;
5166 return function (i, a) {
5167 if (o === f) throw new Error("Generator is already running");
5168 if (o === s) {
5169 if ("throw" === i) throw a;
5170 return {
5171 value: t,
5172 done: !0
5173 };
5174 }
5175 for (n.method = i, n.arg = a;;) {
5176 var c = n.delegate;
5177 if (c) {
5178 var u = maybeInvokeDelegate(c, n);
5179 if (u) {
5180 if (u === y) continue;
5181 return u;
5182 }
5183 }
5184 if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) {
5185 if (o === h) throw o = s, n.arg;
5186 n.dispatchException(n.arg);
5187 } else "return" === n.method && n.abrupt("return", n.arg);
5188 o = f;
5189 var p = tryCatch(e, r, n);
5190 if ("normal" === p.type) {
5191 if (o = n.done ? s : l, p.arg === y) continue;
5192 return {
5193 value: p.arg,
5194 done: n.done
5195 };
5196 }
5197 "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg);
5198 }
5199 };
5200 }
5201 function maybeInvokeDelegate(e, r) {
5202 var n = r.method,
5203 o = e.iterator[n];
5204 if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y;
5205 var i = tryCatch(o, e.iterator, r.arg);
5206 if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y;
5207 var a = i.arg;
5208 return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y);
5209 }
5210 function pushTryEntry(t) {
5211 var e = {
5212 tryLoc: t[0]
5213 };
5214 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e);
5215 }
5216 function resetTryEntry(t) {
5217 var e = t.completion || {};
5218 e.type = "normal", delete e.arg, t.completion = e;
5219 }
5220 function Context(t) {
5221 this.tryEntries = [{
5222 tryLoc: "root"
5223 }], t.forEach(pushTryEntry, this), this.reset(!0);
5224 }
5225 function values(e) {
5226 if (e || "" === e) {
5227 var r = e[a];
5228 if (r) return r.call(e);
5229 if ("function" == typeof e.next) return e;
5230 if (!isNaN(e.length)) {
5231 var o = -1,
5232 i = function next() {
5233 for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next;
5234 return next.value = t, next.done = !0, next;
5235 };
5236 return i.next = i;
5237 }
5238 }
5239 throw new TypeError(typeof e + " is not iterable");
5240 }
5241 return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", {
5242 value: GeneratorFunctionPrototype,
5243 configurable: !0
5244 }), o(GeneratorFunctionPrototype, "constructor", {
5245 value: GeneratorFunction,
5246 configurable: !0
5247 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) {
5248 var e = "function" == typeof t && t.constructor;
5249 return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name));
5250 }, e.mark = function (t) {
5251 return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t;
5252 }, e.awrap = function (t) {
5253 return {
5254 __await: t
5255 };
5256 }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () {
5257 return this;
5258 }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) {
5259 void 0 === i && (i = Promise);
5260 var a = new AsyncIterator(wrap(t, r, n, o), i);
5261 return e.isGeneratorFunction(r) ? a : a.next().then(function (t) {
5262 return t.done ? t.value : a.next();
5263 });
5264 }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () {
5265 return this;
5266 }), define(g, "toString", function () {
5267 return "[object Generator]";
5268 }), e.keys = function (t) {
5269 var e = Object(t),
5270 r = [];
5271 for (var n in e) r.push(n);
5272 return r.reverse(), function next() {
5273 for (; r.length;) {
5274 var t = r.pop();
5275 if (t in e) return next.value = t, next.done = !1, next;
5276 }
5277 return next.done = !0, next;
5278 };
5279 }, e.values = values, Context.prototype = {
5280 constructor: Context,
5281 reset: function (e) {
5282 if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t);
5283 },
5284 stop: function () {
5285 this.done = !0;
5286 var t = this.tryEntries[0].completion;
5287 if ("throw" === t.type) throw t.arg;
5288 return this.rval;
5289 },
5290 dispatchException: function (e) {
5291 if (this.done) throw e;
5292 var r = this;
5293 function handle(n, o) {
5294 return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o;
5295 }
5296 for (var o = this.tryEntries.length - 1; o >= 0; --o) {
5297 var i = this.tryEntries[o],
5298 a = i.completion;
5299 if ("root" === i.tryLoc) return handle("end");
5300 if (i.tryLoc <= this.prev) {
5301 var c = n.call(i, "catchLoc"),
5302 u = n.call(i, "finallyLoc");
5303 if (c && u) {
5304 if (this.prev < i.catchLoc) return handle(i.catchLoc, !0);
5305 if (this.prev < i.finallyLoc) return handle(i.finallyLoc);
5306 } else if (c) {
5307 if (this.prev < i.catchLoc) return handle(i.catchLoc, !0);
5308 } else {
5309 if (!u) throw new Error("try statement without catch or finally");
5310 if (this.prev < i.finallyLoc) return handle(i.finallyLoc);
5311 }
5312 }
5313 }
5314 },
5315 abrupt: function (t, e) {
5316 for (var r = this.tryEntries.length - 1; r >= 0; --r) {
5317 var o = this.tryEntries[r];
5318 if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) {
5319 var i = o;
5320 break;
5321 }
5322 }
5323 i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null);
5324 var a = i ? i.completion : {};
5325 return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a);
5326 },
5327 complete: function (t, e) {
5328 if ("throw" === t.type) throw t.arg;
5329 return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y;
5330 },
5331 finish: function (t) {
5332 for (var e = this.tryEntries.length - 1; e >= 0; --e) {
5333 var r = this.tryEntries[e];
5334 if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y;
5335 }
5336 },
5337 catch: function (t) {
5338 for (var e = this.tryEntries.length - 1; e >= 0; --e) {
5339 var r = this.tryEntries[e];
5340 if (r.tryLoc === t) {
5341 var n = r.completion;
5342 if ("throw" === n.type) {
5343 var o = n.arg;
5344 resetTryEntry(r);
5345 }
5346 return o;
5347 }
5348 }
5349 throw new Error("illegal catch attempt");
5350 },
5351 delegateYield: function (e, r, n) {
5352 return this.delegate = {
5353 iterator: values(e),
5354 resultName: r,
5355 nextLoc: n
5356 }, "next" === this.method && (this.arg = t), y;
5357 }
5358 }, e;
5359 }
5360 function _typeof(o) {
5361 "@babel/helpers - typeof";
5362
5363 return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
5364 return typeof o;
5365 } : function (o) {
5366 return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
5367 }, _typeof(o);
5368 }
5369 function _using(o, e, n) {
5370 if (null == e) return e;
5371 if ("object" != typeof e) throw new TypeError("using declarations can only be used with objects, null, or undefined.");
5372 if (n) var r = e[Symbol.asyncDispose || Symbol.for("Symbol.asyncDispose")];
5373 if (null == r && (r = e[Symbol.dispose || Symbol.for("Symbol.dispose")]), "function" != typeof r) throw new TypeError("Property [Symbol.dispose] is not a function.");
5374 return o.push({
5375 v: e,
5376 d: r,
5377 a: n
5378 }), e;
5379 }
5380 function _wrapRegExp() {
5381 _wrapRegExp = function (e, r) {
5382 return new BabelRegExp(e, void 0, r);
5383 };
5384 var e = RegExp.prototype,
5385 r = new WeakMap();
5386 function BabelRegExp(e, t, p) {
5387 var o = new RegExp(e, t);
5388 return r.set(o, p || r.get(e)), _setPrototypeOf(o, BabelRegExp.prototype);
5389 }
5390 function buildGroups(e, t) {
5391 var p = r.get(t);
5392 return Object.keys(p).reduce(function (r, t) {
5393 var o = p[t];
5394 if ("number" == typeof o) r[t] = e[o];else {
5395 for (var i = 0; void 0 === e[o[i]] && i + 1 < o.length;) i++;
5396 r[t] = e[o[i]];
5397 }
5398 return r;
5399 }, Object.create(null));
5400 }
5401 return _inherits(BabelRegExp, RegExp), BabelRegExp.prototype.exec = function (r) {
5402 var t = e.exec.call(this, r);
5403 if (t) {
5404 t.groups = buildGroups(t, this);
5405 var p = t.indices;
5406 p && (p.groups = buildGroups(p, this));
5407 }
5408 return t;
5409 }, BabelRegExp.prototype[Symbol.replace] = function (t, p) {
5410 if ("string" == typeof p) {
5411 var o = r.get(this);
5412 return e[Symbol.replace].call(this, t, p.replace(/\$<([^>]+)>/g, function (e, r) {
5413 var t = o[r];
5414 return "$" + (Array.isArray(t) ? t.join("$") : t);
5415 }));
5416 }
5417 if ("function" == typeof p) {
5418 var i = this;
5419 return e[Symbol.replace].call(this, t, function () {
5420 var e = arguments;
5421 return "object" != typeof e[e.length - 1] && (e = [].slice.call(e)).push(buildGroups(e, i)), p.apply(this, e);
5422 });
5423 }
5424 return e[Symbol.replace].call(this, t, p);
5425 }, _wrapRegExp.apply(this, arguments);
5426 }
5427 function _AwaitValue(value) {
5428 this.wrapped = value;
5429 }
5430 function _wrapAsyncGenerator(fn) {
5431 return function () {
5432 return new _AsyncGenerator(fn.apply(this, arguments));
5433 };
5434 }
5435 function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
5436 try {
5437 var info = gen[key](arg);
5438 var value = info.value;
5439 } catch (error) {
5440 reject(error);
5441 return;
5442 }
5443 if (info.done) {
5444 resolve(value);
5445 } else {
5446 Promise.resolve(value).then(_next, _throw);
5447 }
5448 }
5449 function _asyncToGenerator(fn) {
5450 return function () {
5451 var self = this,
5452 args = arguments;
5453 return new Promise(function (resolve, reject) {
5454 var gen = fn.apply(self, args);
5455 function _next(value) {
5456 asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
5457 }
5458 function _throw(err) {
5459 asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
5460 }
5461 _next(undefined);
5462 });
5463 };
5464 }
5465 function _classCallCheck(instance, Constructor) {
5466 if (!(instance instanceof Constructor)) {
5467 throw new TypeError("Cannot call a class as a function");
5468 }
5469 }
5470 function _defineProperties(target, props) {
5471 for (var i = 0; i < props.length; i++) {
5472 var descriptor = props[i];
5473 descriptor.enumerable = descriptor.enumerable || false;
5474 descriptor.configurable = true;
5475 if ("value" in descriptor) descriptor.writable = true;
5476 Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor);
5477 }
5478 }
5479 function _createClass(Constructor, protoProps, staticProps) {
5480 if (protoProps) _defineProperties(Constructor.prototype, protoProps);
5481 if (staticProps) _defineProperties(Constructor, staticProps);
5482 Object.defineProperty(Constructor, "prototype", {
5483 writable: false
5484 });
5485 return Constructor;
5486 }
5487 function _defineEnumerableProperties(obj, descs) {
5488 for (var key in descs) {
5489 var desc = descs[key];
5490 desc.configurable = desc.enumerable = true;
5491 if ("value" in desc) desc.writable = true;
5492 Object.defineProperty(obj, key, desc);
5493 }
5494 if (Object.getOwnPropertySymbols) {
5495 var objectSymbols = Object.getOwnPropertySymbols(descs);
5496 for (var i = 0; i < objectSymbols.length; i++) {
5497 var sym = objectSymbols[i];
5498 var desc = descs[sym];
5499 desc.configurable = desc.enumerable = true;
5500 if ("value" in desc) desc.writable = true;
5501 Object.defineProperty(obj, sym, desc);
5502 }
5503 }
5504 return obj;
5505 }
5506 function _defaults(obj, defaults) {
5507 var keys = Object.getOwnPropertyNames(defaults);
5508 for (var i = 0; i < keys.length; i++) {
5509 var key = keys[i];
5510 var value = Object.getOwnPropertyDescriptor(defaults, key);
5511 if (value && value.configurable && obj[key] === undefined) {
5512 Object.defineProperty(obj, key, value);
5513 }
5514 }
5515 return obj;
5516 }
5517 function _defineProperty(obj, key, value) {
5518 key = _toPropertyKey(key);
5519 if (key in obj) {
5520 Object.defineProperty(obj, key, {
5521 value: value,
5522 enumerable: true,
5523 configurable: true,
5524 writable: true
5525 });
5526 } else {
5527 obj[key] = value;
5528 }
5529 return obj;
5530 }
5531 function _extends() {
5532 _extends = Object.assign ? Object.assign.bind() : function (target) {
5533 for (var i = 1; i < arguments.length; i++) {
5534 var source = arguments[i];
5535 for (var key in source) {
5536 if (Object.prototype.hasOwnProperty.call(source, key)) {
5537 target[key] = source[key];
5538 }
5539 }
5540 }
5541 return target;
5542 };
5543 return _extends.apply(this, arguments);
5544 }
5545 function _objectSpread(target) {
5546 for (var i = 1; i < arguments.length; i++) {
5547 var source = arguments[i] != null ? Object(arguments[i]) : {};
5548 var ownKeys = Object.keys(source);
5549 if (typeof Object.getOwnPropertySymbols === 'function') {
5550 ownKeys.push.apply(ownKeys, Object.getOwnPropertySymbols(source).filter(function (sym) {
5551 return Object.getOwnPropertyDescriptor(source, sym).enumerable;
5552 }));
5553 }
5554 ownKeys.forEach(function (key) {
5555 _defineProperty(target, key, source[key]);
5556 });
5557 }
5558 return target;
5559 }
5560 function _inherits(subClass, superClass) {
5561 if (typeof superClass !== "function" && superClass !== null) {
5562 throw new TypeError("Super expression must either be null or a function");
5563 }
5564 subClass.prototype = Object.create(superClass && superClass.prototype, {
5565 constructor: {
5566 value: subClass,
5567 writable: true,
5568 configurable: true
5569 }
5570 });
5571 Object.defineProperty(subClass, "prototype", {
5572 writable: false
5573 });
5574 if (superClass) _setPrototypeOf(subClass, superClass);
5575 }
5576 function _inheritsLoose(subClass, superClass) {
5577 subClass.prototype = Object.create(superClass.prototype);
5578 subClass.prototype.constructor = subClass;
5579 _setPrototypeOf(subClass, superClass);
5580 }
5581 function _getPrototypeOf(o) {
5582 _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) {
5583 return o.__proto__ || Object.getPrototypeOf(o);
5584 };
5585 return _getPrototypeOf(o);
5586 }
5587 function _setPrototypeOf(o, p) {
5588 _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
5589 o.__proto__ = p;
5590 return o;
5591 };
5592 return _setPrototypeOf(o, p);
5593 }
5594 function _isNativeReflectConstruct() {
5595 if (typeof Reflect === "undefined" || !Reflect.construct) return false;
5596 if (Reflect.construct.sham) return false;
5597 if (typeof Proxy === "function") return true;
5598 try {
5599 Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
5600 return true;
5601 } catch (e) {
5602 return false;
5603 }
5604 }
5605 function _construct(Parent, args, Class) {
5606 if (_isNativeReflectConstruct()) {
5607 _construct = Reflect.construct.bind();
5608 } else {
5609 _construct = function _construct(Parent, args, Class) {
5610 var a = [null];
5611 a.push.apply(a, args);
5612 var Constructor = Function.bind.apply(Parent, a);
5613 var instance = new Constructor();
5614 if (Class) _setPrototypeOf(instance, Class.prototype);
5615 return instance;
5616 };
5617 }
5618 return _construct.apply(null, arguments);
5619 }
5620 function _isNativeFunction(fn) {
5621 return Function.toString.call(fn).indexOf("[native code]") !== -1;
5622 }
5623 function _wrapNativeSuper(Class) {
5624 var _cache = typeof Map === "function" ? new Map() : undefined;
5625 _wrapNativeSuper = function _wrapNativeSuper(Class) {
5626 if (Class === null || !_isNativeFunction(Class)) return Class;
5627 if (typeof Class !== "function") {
5628 throw new TypeError("Super expression must either be null or a function");
5629 }
5630 if (typeof _cache !== "undefined") {
5631 if (_cache.has(Class)) return _cache.get(Class);
5632 _cache.set(Class, Wrapper);
5633 }
5634 function Wrapper() {
5635 return _construct(Class, arguments, _getPrototypeOf(this).constructor);
5636 }
5637 Wrapper.prototype = Object.create(Class.prototype, {
5638 constructor: {
5639 value: Wrapper,
5640 enumerable: false,
5641 writable: true,
5642 configurable: true
5643 }
5644 });
5645 return _setPrototypeOf(Wrapper, Class);
5646 };
5647 return _wrapNativeSuper(Class);
5648 }
5649 function _instanceof(left, right) {
5650 if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
5651 return !!right[Symbol.hasInstance](left);
5652 } else {
5653 return left instanceof right;
5654 }
5655 }
5656 function _interopRequireDefault(obj) {
5657 return obj && obj.__esModule ? obj : {
5658 default: obj
5659 };
5660 }
5661 function _getRequireWildcardCache(nodeInterop) {
5662 if (typeof WeakMap !== "function") return null;
5663 var cacheBabelInterop = new WeakMap();
5664 var cacheNodeInterop = new WeakMap();
5665 return (_getRequireWildcardCache = function (nodeInterop) {
5666 return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
5667 })(nodeInterop);
5668 }
5669 function _interopRequireWildcard(obj, nodeInterop) {
5670 if (!nodeInterop && obj && obj.__esModule) {
5671 return obj;
5672 }
5673 if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
5674 return {
5675 default: obj
5676 };
5677 }
5678 var cache = _getRequireWildcardCache(nodeInterop);
5679 if (cache && cache.has(obj)) {
5680 return cache.get(obj);
5681 }
5682 var newObj = {};
5683 var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
5684 for (var key in obj) {
5685 if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
5686 var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
5687 if (desc && (desc.get || desc.set)) {
5688 Object.defineProperty(newObj, key, desc);
5689 } else {
5690 newObj[key] = obj[key];
5691 }
5692 }
5693 }
5694 newObj.default = obj;
5695 if (cache) {
5696 cache.set(obj, newObj);
5697 }
5698 return newObj;
5699 }
5700 function _newArrowCheck(innerThis, boundThis) {
5701 if (innerThis !== boundThis) {
5702 throw new TypeError("Cannot instantiate an arrow function");
5703 }
5704 }
5705 function _objectDestructuringEmpty(obj) {
5706 if (obj == null) throw new TypeError("Cannot destructure " + obj);
5707 }
5708 function _objectWithoutPropertiesLoose(source, excluded) {
5709 if (source == null) return {};
5710 var target = {};
5711 var sourceKeys = Object.keys(source);
5712 var key, i;
5713 for (i = 0; i < sourceKeys.length; i++) {
5714 key = sourceKeys[i];
5715 if (excluded.indexOf(key) >= 0) continue;
5716 target[key] = source[key];
5717 }
5718 return target;
5719 }
5720 function _objectWithoutProperties(source, excluded) {
5721 if (source == null) return {};
5722 var target = _objectWithoutPropertiesLoose(source, excluded);
5723 var key, i;
5724 if (Object.getOwnPropertySymbols) {
5725 var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
5726 for (i = 0; i < sourceSymbolKeys.length; i++) {
5727 key = sourceSymbolKeys[i];
5728 if (excluded.indexOf(key) >= 0) continue;
5729 if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
5730 target[key] = source[key];
5731 }
5732 }
5733 return target;
5734 }
5735 function _assertThisInitialized(self) {
5736 if (self === void 0) {
5737 throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
5738 }
5739 return self;
5740 }
5741 function _possibleConstructorReturn(self, call) {
5742 if (call && (typeof call === "object" || typeof call === "function")) {
5743 return call;
5744 } else if (call !== void 0) {
5745 throw new TypeError("Derived constructors may only return object or undefined");
5746 }
5747 return _assertThisInitialized(self);
5748 }
5749 function _createSuper(Derived) {
5750 var hasNativeReflectConstruct = _isNativeReflectConstruct();
5751 return function _createSuperInternal() {
5752 var Super = _getPrototypeOf(Derived),
5753 result;
5754 if (hasNativeReflectConstruct) {
5755 var NewTarget = _getPrototypeOf(this).constructor;
5756 result = Reflect.construct(Super, arguments, NewTarget);
5757 } else {
5758 result = Super.apply(this, arguments);
5759 }
5760 return _possibleConstructorReturn(this, result);
5761 };
5762 }
5763 function _superPropBase(object, property) {
5764 while (!Object.prototype.hasOwnProperty.call(object, property)) {
5765 object = _getPrototypeOf(object);
5766 if (object === null) break;
5767 }
5768 return object;
5769 }
5770 function _get() {
5771 if (typeof Reflect !== "undefined" && Reflect.get) {
5772 _get = Reflect.get.bind();
5773 } else {
5774 _get = function _get(target, property, receiver) {
5775 var base = _superPropBase(target, property);
5776 if (!base) return;
5777 var desc = Object.getOwnPropertyDescriptor(base, property);
5778 if (desc.get) {
5779 return desc.get.call(arguments.length < 3 ? target : receiver);
5780 }
5781 return desc.value;
5782 };
5783 }
5784 return _get.apply(this, arguments);
5785 }
5786 function set(target, property, value, receiver) {
5787 if (typeof Reflect !== "undefined" && Reflect.set) {
5788 set = Reflect.set;
5789 } else {
5790 set = function set(target, property, value, receiver) {
5791 var base = _superPropBase(target, property);
5792 var desc;
5793 if (base) {
5794 desc = Object.getOwnPropertyDescriptor(base, property);
5795 if (desc.set) {
5796 desc.set.call(receiver, value);
5797 return true;
5798 } else if (!desc.writable) {
5799 return false;
5800 }
5801 }
5802 desc = Object.getOwnPropertyDescriptor(receiver, property);
5803 if (desc) {
5804 if (!desc.writable) {
5805 return false;
5806 }
5807 desc.value = value;
5808 Object.defineProperty(receiver, property, desc);
5809 } else {
5810 _defineProperty(receiver, property, value);
5811 }
5812 return true;
5813 };
5814 }
5815 return set(target, property, value, receiver);
5816 }
5817 function _set(target, property, value, receiver, isStrict) {
5818 var s = set(target, property, value, receiver || target);
5819 if (!s && isStrict) {
5820 throw new TypeError('failed to set property');
5821 }
5822 return value;
5823 }
5824 function _taggedTemplateLiteral(strings, raw) {
5825 if (!raw) {
5826 raw = strings.slice(0);
5827 }
5828 return Object.freeze(Object.defineProperties(strings, {
5829 raw: {
5830 value: Object.freeze(raw)
5831 }
5832 }));
5833 }
5834 function _taggedTemplateLiteralLoose(strings, raw) {
5835 if (!raw) {
5836 raw = strings.slice(0);
5837 }
5838 strings.raw = raw;
5839 return strings;
5840 }
5841 function _readOnlyError(name) {
5842 throw new TypeError("\"" + name + "\" is read-only");
5843 }
5844 function _writeOnlyError(name) {
5845 throw new TypeError("\"" + name + "\" is write-only");
5846 }
5847 function _classNameTDZError(name) {
5848 throw new ReferenceError("Class \"" + name + "\" cannot be referenced in computed property keys.");
5849 }
5850 function _temporalUndefined() {}
5851 function _tdz(name) {
5852 throw new ReferenceError(name + " is not defined - temporal dead zone");
5853 }
5854 function _temporalRef(val, name) {
5855 return val === _temporalUndefined ? _tdz(name) : val;
5856 }
5857 function _slicedToArray(arr, i) {
5858 return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
5859 }
5860 function _slicedToArrayLoose(arr, i) {
5861 return _arrayWithHoles(arr) || _iterableToArrayLimitLoose(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
5862 }
5863 function _toArray(arr) {
5864 return _arrayWithHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableRest();
5865 }
5866 function _toConsumableArray(arr) {
5867 return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
5868 }
5869 function _arrayWithoutHoles(arr) {
5870 if (Array.isArray(arr)) return _arrayLikeToArray(arr);
5871 }
5872 function _arrayWithHoles(arr) {
5873 if (Array.isArray(arr)) return arr;
5874 }
5875 function _maybeArrayLike(next, arr, i) {
5876 if (arr && !Array.isArray(arr) && typeof arr.length === "number") {
5877 var len = arr.length;
5878 return _arrayLikeToArray(arr, i !== void 0 && i < len ? i : len);
5879 }
5880 return next(arr, i);
5881 }
5882 function _iterableToArray(iter) {
5883 if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
5884 }
5885 function _unsupportedIterableToArray(o, minLen) {
5886 if (!o) return;
5887 if (typeof o === "string") return _arrayLikeToArray(o, minLen);
5888 var n = Object.prototype.toString.call(o).slice(8, -1);
5889 if (n === "Object" && o.constructor) n = o.constructor.name;
5890 if (n === "Map" || n === "Set") return Array.from(o);
5891 if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
5892 }
5893 function _arrayLikeToArray(arr, len) {
5894 if (len == null || len > arr.length) len = arr.length;
5895 for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
5896 return arr2;
5897 }
5898 function _nonIterableSpread() {
5899 throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
5900 }
5901 function _nonIterableRest() {
5902 throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
5903 }
5904 function _createForOfIteratorHelper(o, allowArrayLike) {
5905 var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
5906 if (!it) {
5907 if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
5908 if (it) o = it;
5909 var i = 0;
5910 var F = function () {};
5911 return {
5912 s: F,
5913 n: function () {
5914 if (i >= o.length) return {
5915 done: true
5916 };
5917 return {
5918 done: false,
5919 value: o[i++]
5920 };
5921 },
5922 e: function (e) {
5923 throw e;
5924 },
5925 f: F
5926 };
5927 }
5928 throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
5929 }
5930 var normalCompletion = true,
5931 didErr = false,
5932 err;
5933 return {
5934 s: function () {
5935 it = it.call(o);
5936 },
5937 n: function () {
5938 var step = it.next();
5939 normalCompletion = step.done;
5940 return step;
5941 },
5942 e: function (e) {
5943 didErr = true;
5944 err = e;
5945 },
5946 f: function () {
5947 try {
5948 if (!normalCompletion && it.return != null) it.return();
5949 } finally {
5950 if (didErr) throw err;
5951 }
5952 }
5953 };
5954 }
5955 function _createForOfIteratorHelperLoose(o, allowArrayLike) {
5956 var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
5957 if (it) return (it = it.call(o)).next.bind(it);
5958 if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
5959 if (it) o = it;
5960 var i = 0;
5961 return function () {
5962 if (i >= o.length) return {
5963 done: true
5964 };
5965 return {
5966 done: false,
5967 value: o[i++]
5968 };
5969 };
5970 }
5971 throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
5972 }
5973 function _skipFirstGeneratorNext(fn) {
5974 return function () {
5975 var it = fn.apply(this, arguments);
5976 it.next();
5977 return it;
5978 };
5979 }
5980 function _toPrimitive(input, hint) {
5981 if (typeof input !== "object" || input === null) return input;
5982 var prim = input[Symbol.toPrimitive];
5983 if (prim !== undefined) {
5984 var res = prim.call(input, hint || "default");
5985 if (typeof res !== "object") return res;
5986 throw new TypeError("@@toPrimitive must return a primitive value.");
5987 }
5988 return (hint === "string" ? String : Number)(input);
5989 }
5990 function _toPropertyKey(arg) {
5991 var key = _toPrimitive(arg, "string");
5992 return typeof key === "symbol" ? key : String(key);
5993 }
5994 function _initializerWarningHelper(descriptor, context) {
5995 throw new Error('Decorating class property failed. Please ensure that ' + 'transform-class-properties is enabled and runs after the decorators transform.');
5996 }
5997 function _initializerDefineProperty(target, property, descriptor, context) {
5998 if (!descriptor) return;
5999 Object.defineProperty(target, property, {
6000 enumerable: descriptor.enumerable,
6001 configurable: descriptor.configurable,
6002 writable: descriptor.writable,
6003 value: descriptor.initializer ? descriptor.initializer.call(context) : void 0
6004 });
6005 }
6006 function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
6007 var desc = {};
6008 Object.keys(descriptor).forEach(function (key) {
6009 desc[key] = descriptor[key];
6010 });
6011 desc.enumerable = !!desc.enumerable;
6012 desc.configurable = !!desc.configurable;
6013 if ('value' in desc || desc.initializer) {
6014 desc.writable = true;
6015 }
6016 desc = decorators.slice().reverse().reduce(function (desc, decorator) {
6017 return decorator(target, property, desc) || desc;
6018 }, desc);
6019 if (context && desc.initializer !== void 0) {
6020 desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
6021 desc.initializer = undefined;
6022 }
6023 if (desc.initializer === void 0) {
6024 Object.defineProperty(target, property, desc);
6025 desc = null;
6026 }
6027 return desc;
6028 }
6029 var id$1 = 0;
6030 function _classPrivateFieldLooseKey(name) {
6031 return "__private_" + id$1++ + "_" + name;
6032 }
6033 function _classPrivateFieldLooseBase(receiver, privateKey) {
6034 if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
6035 throw new TypeError("attempted to use private field on non-instance");
6036 }
6037 return receiver;
6038 }
6039 function _classPrivateFieldGet(receiver, privateMap) {
6040 var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get");
6041 return _classApplyDescriptorGet(receiver, descriptor);
6042 }
6043 function _classPrivateFieldSet(receiver, privateMap, value) {
6044 var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set");
6045 _classApplyDescriptorSet(receiver, descriptor, value);
6046 return value;
6047 }
6048 function _classPrivateFieldDestructureSet(receiver, privateMap) {
6049 var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set");
6050 return _classApplyDescriptorDestructureSet(receiver, descriptor);
6051 }
6052 function _classExtractFieldDescriptor(receiver, privateMap, action) {
6053 if (!privateMap.has(receiver)) {
6054 throw new TypeError("attempted to " + action + " private field on non-instance");
6055 }
6056 return privateMap.get(receiver);
6057 }
6058 function _classStaticPrivateFieldSpecGet(receiver, classConstructor, descriptor) {
6059 _classCheckPrivateStaticAccess(receiver, classConstructor);
6060 _classCheckPrivateStaticFieldDescriptor(descriptor, "get");
6061 return _classApplyDescriptorGet(receiver, descriptor);
6062 }
6063 function _classStaticPrivateFieldSpecSet(receiver, classConstructor, descriptor, value) {
6064 _classCheckPrivateStaticAccess(receiver, classConstructor);
6065 _classCheckPrivateStaticFieldDescriptor(descriptor, "set");
6066 _classApplyDescriptorSet(receiver, descriptor, value);
6067 return value;
6068 }
6069 function _classStaticPrivateMethodGet(receiver, classConstructor, method) {
6070 _classCheckPrivateStaticAccess(receiver, classConstructor);
6071 return method;
6072 }
6073 function _classStaticPrivateMethodSet() {
6074 throw new TypeError("attempted to set read only static private field");
6075 }
6076 function _classApplyDescriptorGet(receiver, descriptor) {
6077 if (descriptor.get) {
6078 return descriptor.get.call(receiver);
6079 }
6080 return descriptor.value;
6081 }
6082 function _classApplyDescriptorSet(receiver, descriptor, value) {
6083 if (descriptor.set) {
6084 descriptor.set.call(receiver, value);
6085 } else {
6086 if (!descriptor.writable) {
6087 throw new TypeError("attempted to set read only private field");
6088 }
6089 descriptor.value = value;
6090 }
6091 }
6092 function _classApplyDescriptorDestructureSet(receiver, descriptor) {
6093 if (descriptor.set) {
6094 if (!("__destrObj" in descriptor)) {
6095 descriptor.__destrObj = {
6096 set value(v) {
6097 descriptor.set.call(receiver, v);
6098 }
6099 };
6100 }
6101 return descriptor.__destrObj;
6102 } else {
6103 if (!descriptor.writable) {
6104 throw new TypeError("attempted to set read only private field");
6105 }
6106 return descriptor;
6107 }
6108 }
6109 function _classStaticPrivateFieldDestructureSet(receiver, classConstructor, descriptor) {
6110 _classCheckPrivateStaticAccess(receiver, classConstructor);
6111 _classCheckPrivateStaticFieldDescriptor(descriptor, "set");
6112 return _classApplyDescriptorDestructureSet(receiver, descriptor);
6113 }
6114 function _classCheckPrivateStaticAccess(receiver, classConstructor) {
6115 if (receiver !== classConstructor) {
6116 throw new TypeError("Private static access of wrong provenance");
6117 }
6118 }
6119 function _classCheckPrivateStaticFieldDescriptor(descriptor, action) {
6120 if (descriptor === undefined) {
6121 throw new TypeError("attempted to " + action + " private static field before its declaration");
6122 }
6123 }
6124 function _decorate(decorators, factory, superClass, mixins) {
6125 var api = _getDecoratorsApi();
6126 if (mixins) {
6127 for (var i = 0; i < mixins.length; i++) {
6128 api = mixins[i](api);
6129 }
6130 }
6131 var r = factory(function initialize(O) {
6132 api.initializeInstanceElements(O, decorated.elements);
6133 }, superClass);
6134 var decorated = api.decorateClass(_coalesceClassElements(r.d.map(_createElementDescriptor)), decorators);
6135 api.initializeClassElements(r.F, decorated.elements);
6136 return api.runClassFinishers(r.F, decorated.finishers);
6137 }
6138 function _getDecoratorsApi() {
6139 _getDecoratorsApi = function () {
6140 return api;
6141 };
6142 var api = {
6143 elementsDefinitionOrder: [["method"], ["field"]],
6144 initializeInstanceElements: function (O, elements) {
6145 ["method", "field"].forEach(function (kind) {
6146 elements.forEach(function (element) {
6147 if (element.kind === kind && element.placement === "own") {
6148 this.defineClassElement(O, element);
6149 }
6150 }, this);
6151 }, this);
6152 },
6153 initializeClassElements: function (F, elements) {
6154 var proto = F.prototype;
6155 ["method", "field"].forEach(function (kind) {
6156 elements.forEach(function (element) {
6157 var placement = element.placement;
6158 if (element.kind === kind && (placement === "static" || placement === "prototype")) {
6159 var receiver = placement === "static" ? F : proto;
6160 this.defineClassElement(receiver, element);
6161 }
6162 }, this);
6163 }, this);
6164 },
6165 defineClassElement: function (receiver, element) {
6166 var descriptor = element.descriptor;
6167 if (element.kind === "field") {
6168 var initializer = element.initializer;
6169 descriptor = {
6170 enumerable: descriptor.enumerable,
6171 writable: descriptor.writable,
6172 configurable: descriptor.configurable,
6173 value: initializer === void 0 ? void 0 : initializer.call(receiver)
6174 };
6175 }
6176 Object.defineProperty(receiver, element.key, descriptor);
6177 },
6178 decorateClass: function (elements, decorators) {
6179 var newElements = [];
6180 var finishers = [];
6181 var placements = {
6182 static: [],
6183 prototype: [],
6184 own: []
6185 };
6186 elements.forEach(function (element) {
6187 this.addElementPlacement(element, placements);
6188 }, this);
6189 elements.forEach(function (element) {
6190 if (!_hasDecorators(element)) return newElements.push(element);
6191 var elementFinishersExtras = this.decorateElement(element, placements);
6192 newElements.push(elementFinishersExtras.element);
6193 newElements.push.apply(newElements, elementFinishersExtras.extras);
6194 finishers.push.apply(finishers, elementFinishersExtras.finishers);
6195 }, this);
6196 if (!decorators) {
6197 return {
6198 elements: newElements,
6199 finishers: finishers
6200 };
6201 }
6202 var result = this.decorateConstructor(newElements, decorators);
6203 finishers.push.apply(finishers, result.finishers);
6204 result.finishers = finishers;
6205 return result;
6206 },
6207 addElementPlacement: function (element, placements, silent) {
6208 var keys = placements[element.placement];
6209 if (!silent && keys.indexOf(element.key) !== -1) {
6210 throw new TypeError("Duplicated element (" + element.key + ")");
6211 }
6212 keys.push(element.key);
6213 },
6214 decorateElement: function (element, placements) {
6215 var extras = [];
6216 var finishers = [];
6217 for (var decorators = element.decorators, i = decorators.length - 1; i >= 0; i--) {
6218 var keys = placements[element.placement];
6219 keys.splice(keys.indexOf(element.key), 1);
6220 var elementObject = this.fromElementDescriptor(element);
6221 var elementFinisherExtras = this.toElementFinisherExtras((0, decorators[i])(elementObject) || elementObject);
6222 element = elementFinisherExtras.element;
6223 this.addElementPlacement(element, placements);
6224 if (elementFinisherExtras.finisher) {
6225 finishers.push(elementFinisherExtras.finisher);
6226 }
6227 var newExtras = elementFinisherExtras.extras;
6228 if (newExtras) {
6229 for (var j = 0; j < newExtras.length; j++) {
6230 this.addElementPlacement(newExtras[j], placements);
6231 }
6232 extras.push.apply(extras, newExtras);
6233 }
6234 }
6235 return {
6236 element: element,
6237 finishers: finishers,
6238 extras: extras
6239 };
6240 },
6241 decorateConstructor: function (elements, decorators) {
6242 var finishers = [];
6243 for (var i = decorators.length - 1; i >= 0; i--) {
6244 var obj = this.fromClassDescriptor(elements);
6245 var elementsAndFinisher = this.toClassDescriptor((0, decorators[i])(obj) || obj);
6246 if (elementsAndFinisher.finisher !== undefined) {
6247 finishers.push(elementsAndFinisher.finisher);
6248 }
6249 if (elementsAndFinisher.elements !== undefined) {
6250 elements = elementsAndFinisher.elements;
6251 for (var j = 0; j < elements.length - 1; j++) {
6252 for (var k = j + 1; k < elements.length; k++) {
6253 if (elements[j].key === elements[k].key && elements[j].placement === elements[k].placement) {
6254 throw new TypeError("Duplicated element (" + elements[j].key + ")");
6255 }
6256 }
6257 }
6258 }
6259 }
6260 return {
6261 elements: elements,
6262 finishers: finishers
6263 };
6264 },
6265 fromElementDescriptor: function (element) {
6266 var obj = {
6267 kind: element.kind,
6268 key: element.key,
6269 placement: element.placement,
6270 descriptor: element.descriptor
6271 };
6272 var desc = {
6273 value: "Descriptor",
6274 configurable: true
6275 };
6276 Object.defineProperty(obj, Symbol.toStringTag, desc);
6277 if (element.kind === "field") obj.initializer = element.initializer;
6278 return obj;
6279 },
6280 toElementDescriptors: function (elementObjects) {
6281 if (elementObjects === undefined) return;
6282 return _toArray(elementObjects).map(function (elementObject) {
6283 var element = this.toElementDescriptor(elementObject);
6284 this.disallowProperty(elementObject, "finisher", "An element descriptor");
6285 this.disallowProperty(elementObject, "extras", "An element descriptor");
6286 return element;
6287 }, this);
6288 },
6289 toElementDescriptor: function (elementObject) {
6290 var kind = String(elementObject.kind);
6291 if (kind !== "method" && kind !== "field") {
6292 throw new TypeError('An element descriptor\'s .kind property must be either "method" or' + ' "field", but a decorator created an element descriptor with' + ' .kind "' + kind + '"');
6293 }
6294 var key = _toPropertyKey(elementObject.key);
6295 var placement = String(elementObject.placement);
6296 if (placement !== "static" && placement !== "prototype" && placement !== "own") {
6297 throw new TypeError('An element descriptor\'s .placement property must be one of "static",' + ' "prototype" or "own", but a decorator created an element descriptor' + ' with .placement "' + placement + '"');
6298 }
6299 var descriptor = elementObject.descriptor;
6300 this.disallowProperty(elementObject, "elements", "An element descriptor");
6301 var element = {
6302 kind: kind,
6303 key: key,
6304 placement: placement,
6305 descriptor: Object.assign({}, descriptor)
6306 };
6307 if (kind !== "field") {
6308 this.disallowProperty(elementObject, "initializer", "A method descriptor");
6309 } else {
6310 this.disallowProperty(descriptor, "get", "The property descriptor of a field descriptor");
6311 this.disallowProperty(descriptor, "set", "The property descriptor of a field descriptor");
6312 this.disallowProperty(descriptor, "value", "The property descriptor of a field descriptor");
6313 element.initializer = elementObject.initializer;
6314 }
6315 return element;
6316 },
6317 toElementFinisherExtras: function (elementObject) {
6318 var element = this.toElementDescriptor(elementObject);
6319 var finisher = _optionalCallableProperty(elementObject, "finisher");
6320 var extras = this.toElementDescriptors(elementObject.extras);
6321 return {
6322 element: element,
6323 finisher: finisher,
6324 extras: extras
6325 };
6326 },
6327 fromClassDescriptor: function (elements) {
6328 var obj = {
6329 kind: "class",
6330 elements: elements.map(this.fromElementDescriptor, this)
6331 };
6332 var desc = {
6333 value: "Descriptor",
6334 configurable: true
6335 };
6336 Object.defineProperty(obj, Symbol.toStringTag, desc);
6337 return obj;
6338 },
6339 toClassDescriptor: function (obj) {
6340 var kind = String(obj.kind);
6341 if (kind !== "class") {
6342 throw new TypeError('A class descriptor\'s .kind property must be "class", but a decorator' + ' created a class descriptor with .kind "' + kind + '"');
6343 }
6344 this.disallowProperty(obj, "key", "A class descriptor");
6345 this.disallowProperty(obj, "placement", "A class descriptor");
6346 this.disallowProperty(obj, "descriptor", "A class descriptor");
6347 this.disallowProperty(obj, "initializer", "A class descriptor");
6348 this.disallowProperty(obj, "extras", "A class descriptor");
6349 var finisher = _optionalCallableProperty(obj, "finisher");
6350 var elements = this.toElementDescriptors(obj.elements);
6351 return {
6352 elements: elements,
6353 finisher: finisher
6354 };
6355 },
6356 runClassFinishers: function (constructor, finishers) {
6357 for (var i = 0; i < finishers.length; i++) {
6358 var newConstructor = (0, finishers[i])(constructor);
6359 if (newConstructor !== undefined) {
6360 if (typeof newConstructor !== "function") {
6361 throw new TypeError("Finishers must return a constructor.");
6362 }
6363 constructor = newConstructor;
6364 }
6365 }
6366 return constructor;
6367 },
6368 disallowProperty: function (obj, name, objectType) {
6369 if (obj[name] !== undefined) {
6370 throw new TypeError(objectType + " can't have a ." + name + " property.");
6371 }
6372 }
6373 };
6374 return api;
6375 }
6376 function _createElementDescriptor(def) {
6377 var key = _toPropertyKey(def.key);
6378 var descriptor;
6379 if (def.kind === "method") {
6380 descriptor = {
6381 value: def.value,
6382 writable: true,
6383 configurable: true,
6384 enumerable: false
6385 };
6386 } else if (def.kind === "get") {
6387 descriptor = {
6388 get: def.value,
6389 configurable: true,
6390 enumerable: false
6391 };
6392 } else if (def.kind === "set") {
6393 descriptor = {
6394 set: def.value,
6395 configurable: true,
6396 enumerable: false
6397 };
6398 } else if (def.kind === "field") {
6399 descriptor = {
6400 configurable: true,
6401 writable: true,
6402 enumerable: true
6403 };
6404 }
6405 var element = {
6406 kind: def.kind === "field" ? "field" : "method",
6407 key: key,
6408 placement: def.static ? "static" : def.kind === "field" ? "own" : "prototype",
6409 descriptor: descriptor
6410 };
6411 if (def.decorators) element.decorators = def.decorators;
6412 if (def.kind === "field") element.initializer = def.value;
6413 return element;
6414 }
6415 function _coalesceGetterSetter(element, other) {
6416 if (element.descriptor.get !== undefined) {
6417 other.descriptor.get = element.descriptor.get;
6418 } else {
6419 other.descriptor.set = element.descriptor.set;
6420 }
6421 }
6422 function _coalesceClassElements(elements) {
6423 var newElements = [];
6424 var isSameElement = function (other) {
6425 return other.kind === "method" && other.key === element.key && other.placement === element.placement;
6426 };
6427 for (var i = 0; i < elements.length; i++) {
6428 var element = elements[i];
6429 var other;
6430 if (element.kind === "method" && (other = newElements.find(isSameElement))) {
6431 if (_isDataDescriptor(element.descriptor) || _isDataDescriptor(other.descriptor)) {
6432 if (_hasDecorators(element) || _hasDecorators(other)) {
6433 throw new ReferenceError("Duplicated methods (" + element.key + ") can't be decorated.");
6434 }
6435 other.descriptor = element.descriptor;
6436 } else {
6437 if (_hasDecorators(element)) {
6438 if (_hasDecorators(other)) {
6439 throw new ReferenceError("Decorators can't be placed on different accessors with for " + "the same property (" + element.key + ").");
6440 }
6441 other.decorators = element.decorators;
6442 }
6443 _coalesceGetterSetter(element, other);
6444 }
6445 } else {
6446 newElements.push(element);
6447 }
6448 }
6449 return newElements;
6450 }
6451 function _hasDecorators(element) {
6452 return element.decorators && element.decorators.length;
6453 }
6454 function _isDataDescriptor(desc) {
6455 return desc !== undefined && !(desc.value === undefined && desc.writable === undefined);
6456 }
6457 function _optionalCallableProperty(obj, name) {
6458 var value = obj[name];
6459 if (value !== undefined && typeof value !== "function") {
6460 throw new TypeError("Expected '" + name + "' to be a function");
6461 }
6462 return value;
6463 }
6464 function _classPrivateMethodGet(receiver, privateSet, fn) {
6465 if (!privateSet.has(receiver)) {
6466 throw new TypeError("attempted to get private field on non-instance");
6467 }
6468 return fn;
6469 }
6470 function _checkPrivateRedeclaration(obj, privateCollection) {
6471 if (privateCollection.has(obj)) {
6472 throw new TypeError("Cannot initialize the same private elements twice on an object");
6473 }
6474 }
6475 function _classPrivateFieldInitSpec(obj, privateMap, value) {
6476 _checkPrivateRedeclaration(obj, privateMap);
6477 privateMap.set(obj, value);
6478 }
6479 function _classPrivateMethodInitSpec(obj, privateSet) {
6480 _checkPrivateRedeclaration(obj, privateSet);
6481 privateSet.add(obj);
6482 }
6483 function _classPrivateMethodSet() {
6484 throw new TypeError("attempted to reassign private method");
6485 }
6486 function _identity(x) {
6487 return x;
6488 }
6489 function _nullishReceiverError(r) {
6490 throw new TypeError("Cannot set property of null or undefined.");
6491 }
6492
6493 class Piece extends TrixObject {
6494 static registerType(type, constructor) {
6495 constructor.type = type;
6496 this.types[type] = constructor;
6497 }
6498 static fromJSON(pieceJSON) {
6499 const constructor = this.types[pieceJSON.type];
6500 if (constructor) {
6501 return constructor.fromJSON(pieceJSON);
6502 }
6503 }
6504 constructor(value) {
6505 let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
6506 super(...arguments);
6507 this.attributes = Hash.box(attributes);
6508 }
6509 copyWithAttributes(attributes) {
6510 return new this.constructor(this.getValue(), attributes);
6511 }
6512 copyWithAdditionalAttributes(attributes) {
6513 return this.copyWithAttributes(this.attributes.merge(attributes));
6514 }
6515 copyWithoutAttribute(attribute) {
6516 return this.copyWithAttributes(this.attributes.remove(attribute));
6517 }
6518 copy() {
6519 return this.copyWithAttributes(this.attributes);
6520 }
6521 getAttribute(attribute) {
6522 return this.attributes.get(attribute);
6523 }
6524 getAttributesHash() {
6525 return this.attributes;
6526 }
6527 getAttributes() {
6528 return this.attributes.toObject();
6529 }
6530 hasAttribute(attribute) {
6531 return this.attributes.has(attribute);
6532 }
6533 hasSameStringValueAsPiece(piece) {
6534 return piece && this.toString() === piece.toString();
6535 }
6536 hasSameAttributesAsPiece(piece) {
6537 return piece && (this.attributes === piece.attributes || this.attributes.isEqualTo(piece.attributes));
6538 }
6539 isBlockBreak() {
6540 return false;
6541 }
6542 isEqualTo(piece) {
6543 return super.isEqualTo(...arguments) || this.hasSameConstructorAs(piece) && this.hasSameStringValueAsPiece(piece) && this.hasSameAttributesAsPiece(piece);
6544 }
6545 isEmpty() {
6546 return this.length === 0;
6547 }
6548 isSerializable() {
6549 return true;
6550 }
6551 toJSON() {
6552 return {
6553 type: this.constructor.type,
6554 attributes: this.getAttributes()
6555 };
6556 }
6557 contentsForInspection() {
6558 return {
6559 type: this.constructor.type,
6560 attributes: this.attributes.inspect()
6561 };
6562 }
6563
6564 // Grouping
6565
6566 canBeGrouped() {
6567 return this.hasAttribute("href");
6568 }
6569 canBeGroupedWith(piece) {
6570 return this.getAttribute("href") === piece.getAttribute("href");
6571 }
6572
6573 // Splittable
6574
6575 getLength() {
6576 return this.length;
6577 }
6578 canBeConsolidatedWith(piece) {
6579 return false;
6580 }
6581 }
6582 _defineProperty(Piece, "types", {});
6583
6584 class ImagePreloadOperation extends Operation {
6585 constructor(url) {
6586 super(...arguments);
6587 this.url = url;
6588 }
6589 perform(callback) {
6590 const image = new Image();
6591 image.onload = () => {
6592 image.width = this.width = image.naturalWidth;
6593 image.height = this.height = image.naturalHeight;
6594 return callback(true, image);
6595 };
6596 image.onerror = () => callback(false);
6597 image.src = this.url;
6598 }
6599 }
6600
6601 class Attachment extends TrixObject {
6602 static attachmentForFile(file) {
6603 const attributes = this.attributesForFile(file);
6604 const attachment = new this(attributes);
6605 attachment.setFile(file);
6606 return attachment;
6607 }
6608 static attributesForFile(file) {
6609 return new Hash({
6610 filename: file.name,
6611 filesize: file.size,
6612 contentType: file.type
6613 });
6614 }
6615 static fromJSON(attachmentJSON) {
6616 return new this(attachmentJSON);
6617 }
6618 constructor() {
6619 let attributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6620 super(attributes);
6621 this.releaseFile = this.releaseFile.bind(this);
6622 this.attributes = Hash.box(attributes);
6623 this.didChangeAttributes();
6624 }
6625 getAttribute(attribute) {
6626 return this.attributes.get(attribute);
6627 }
6628 hasAttribute(attribute) {
6629 return this.attributes.has(attribute);
6630 }
6631 getAttributes() {
6632 return this.attributes.toObject();
6633 }
6634 setAttributes() {
6635 let attributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6636 const newAttributes = this.attributes.merge(attributes);
6637 if (!this.attributes.isEqualTo(newAttributes)) {
6638 var _this$previewDelegate, _this$previewDelegate2, _this$delegate, _this$delegate$attach;
6639 this.attributes = newAttributes;
6640 this.didChangeAttributes();
6641 (_this$previewDelegate = this.previewDelegate) === null || _this$previewDelegate === void 0 || (_this$previewDelegate2 = _this$previewDelegate.attachmentDidChangeAttributes) === null || _this$previewDelegate2 === void 0 || _this$previewDelegate2.call(_this$previewDelegate, this);
6642 return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$attach = _this$delegate.attachmentDidChangeAttributes) === null || _this$delegate$attach === void 0 ? void 0 : _this$delegate$attach.call(_this$delegate, this);
6643 }
6644 }
6645 didChangeAttributes() {
6646 if (this.isPreviewable()) {
6647 return this.preloadURL();
6648 }
6649 }
6650 isPending() {
6651 return this.file != null && !(this.getURL() || this.getHref());
6652 }
6653 isPreviewable() {
6654 if (this.attributes.has("previewable")) {
6655 return this.attributes.get("previewable");
6656 } else {
6657 return Attachment.previewablePattern.test(this.getContentType());
6658 }
6659 }
6660 getType() {
6661 if (this.hasContent()) {
6662 return "content";
6663 } else if (this.isPreviewable()) {
6664 return "preview";
6665 } else {
6666 return "file";
6667 }
6668 }
6669 getURL() {
6670 return this.attributes.get("url");
6671 }
6672 getHref() {
6673 return this.attributes.get("href");
6674 }
6675 getFilename() {
6676 return this.attributes.get("filename") || "";
6677 }
6678 getFilesize() {
6679 return this.attributes.get("filesize");
6680 }
6681 getFormattedFilesize() {
6682 const filesize = this.attributes.get("filesize");
6683 if (typeof filesize === "number") {
6684 return file_size_formatting.formatter(filesize);
6685 } else {
6686 return "";
6687 }
6688 }
6689 getExtension() {
6690 var _this$getFilename$mat;
6691 return (_this$getFilename$mat = this.getFilename().match(/\.(\w+)$/)) === null || _this$getFilename$mat === void 0 ? void 0 : _this$getFilename$mat[1].toLowerCase();
6692 }
6693 getContentType() {
6694 return this.attributes.get("contentType");
6695 }
6696 hasContent() {
6697 return this.attributes.has("content");
6698 }
6699 getContent() {
6700 return this.attributes.get("content");
6701 }
6702 getWidth() {
6703 return this.attributes.get("width");
6704 }
6705 getHeight() {
6706 return this.attributes.get("height");
6707 }
6708 getFile() {
6709 return this.file;
6710 }
6711 setFile(file) {
6712 this.file = file;
6713 if (this.isPreviewable()) {
6714 return this.preloadFile();
6715 }
6716 }
6717 releaseFile() {
6718 this.releasePreloadedFile();
6719 this.file = null;
6720 }
6721 getUploadProgress() {
6722 return this.uploadProgress != null ? this.uploadProgress : 0;
6723 }
6724 setUploadProgress(value) {
6725 if (this.uploadProgress !== value) {
6726 var _this$uploadProgressD, _this$uploadProgressD2;
6727 this.uploadProgress = value;
6728 return (_this$uploadProgressD = this.uploadProgressDelegate) === null || _this$uploadProgressD === void 0 || (_this$uploadProgressD2 = _this$uploadProgressD.attachmentDidChangeUploadProgress) === null || _this$uploadProgressD2 === void 0 ? void 0 : _this$uploadProgressD2.call(_this$uploadProgressD, this);
6729 }
6730 }
6731 toJSON() {
6732 return this.getAttributes();
6733 }
6734 getCacheKey() {
6735 return [super.getCacheKey(...arguments), this.attributes.getCacheKey(), this.getPreviewURL()].join("/");
6736 }
6737
6738 // Previewable
6739
6740 getPreviewURL() {
6741 return this.previewURL || this.preloadingURL;
6742 }
6743 setPreviewURL(url) {
6744 if (url !== this.getPreviewURL()) {
6745 var _this$previewDelegate3, _this$previewDelegate4, _this$delegate2, _this$delegate2$attac;
6746 this.previewURL = url;
6747 (_this$previewDelegate3 = this.previewDelegate) === null || _this$previewDelegate3 === void 0 || (_this$previewDelegate4 = _this$previewDelegate3.attachmentDidChangeAttributes) === null || _this$previewDelegate4 === void 0 || _this$previewDelegate4.call(_this$previewDelegate3, this);
6748 return (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || (_this$delegate2$attac = _this$delegate2.attachmentDidChangePreviewURL) === null || _this$delegate2$attac === void 0 ? void 0 : _this$delegate2$attac.call(_this$delegate2, this);
6749 }
6750 }
6751 preloadURL() {
6752 return this.preload(this.getURL(), this.releaseFile);
6753 }
6754 preloadFile() {
6755 if (this.file) {
6756 this.fileObjectURL = URL.createObjectURL(this.file);
6757 return this.preload(this.fileObjectURL);
6758 }
6759 }
6760 releasePreloadedFile() {
6761 if (this.fileObjectURL) {
6762 URL.revokeObjectURL(this.fileObjectURL);
6763 this.fileObjectURL = null;
6764 }
6765 }
6766 preload(url, callback) {
6767 if (url && url !== this.getPreviewURL()) {
6768 this.preloadingURL = url;
6769 const operation = new ImagePreloadOperation(url);
6770 return operation.then(_ref => {
6771 let {
6772 width,
6773 height
6774 } = _ref;
6775 if (!this.getWidth() || !this.getHeight()) {
6776 this.setAttributes({
6777 width,
6778 height
6779 });
6780 }
6781 this.preloadingURL = null;
6782 this.setPreviewURL(url);
6783 return callback === null || callback === void 0 ? void 0 : callback();
6784 }).catch(() => {
6785 this.preloadingURL = null;
6786 return callback === null || callback === void 0 ? void 0 : callback();
6787 });
6788 }
6789 }
6790 }
6791 _defineProperty(Attachment, "previewablePattern", /^image(\/(gif|png|webp|jpe?g)|$)/);
6792
6793 class AttachmentPiece extends Piece {
6794 static fromJSON(pieceJSON) {
6795 return new this(Attachment.fromJSON(pieceJSON.attachment), pieceJSON.attributes);
6796 }
6797 constructor(attachment) {
6798 super(...arguments);
6799 this.attachment = attachment;
6800 this.length = 1;
6801 this.ensureAttachmentExclusivelyHasAttribute("href");
6802 if (!this.attachment.hasContent()) {
6803 this.removeProhibitedAttributes();
6804 }
6805 }
6806 ensureAttachmentExclusivelyHasAttribute(attribute) {
6807 if (this.hasAttribute(attribute)) {
6808 if (!this.attachment.hasAttribute(attribute)) {
6809 this.attachment.setAttributes(this.attributes.slice([attribute]));
6810 }
6811 this.attributes = this.attributes.remove(attribute);
6812 }
6813 }
6814 removeProhibitedAttributes() {
6815 const attributes = this.attributes.slice(AttachmentPiece.permittedAttributes);
6816 if (!attributes.isEqualTo(this.attributes)) {
6817 this.attributes = attributes;
6818 }
6819 }
6820 getValue() {
6821 return this.attachment;
6822 }
6823 isSerializable() {
6824 return !this.attachment.isPending();
6825 }
6826 getCaption() {
6827 return this.attributes.get("caption") || "";
6828 }
6829 isEqualTo(piece) {
6830 var _piece$attachment;
6831 return super.isEqualTo(piece) && this.attachment.id === (piece === null || piece === void 0 || (_piece$attachment = piece.attachment) === null || _piece$attachment === void 0 ? void 0 : _piece$attachment.id);
6832 }
6833 toString() {
6834 return OBJECT_REPLACEMENT_CHARACTER;
6835 }
6836 toJSON() {
6837 const json = super.toJSON(...arguments);
6838 json.attachment = this.attachment;
6839 return json;
6840 }
6841 getCacheKey() {
6842 return [super.getCacheKey(...arguments), this.attachment.getCacheKey()].join("/");
6843 }
6844 toConsole() {
6845 return JSON.stringify(this.toString());
6846 }
6847 }
6848 _defineProperty(AttachmentPiece, "permittedAttributes", ["caption", "presentation"]);
6849 Piece.registerType("attachment", AttachmentPiece);
6850
6851 class StringPiece extends Piece {
6852 static fromJSON(pieceJSON) {
6853 return new this(pieceJSON.string, pieceJSON.attributes);
6854 }
6855 constructor(string) {
6856 super(...arguments);
6857 this.string = normalizeNewlines(string);
6858 this.length = this.string.length;
6859 }
6860 getValue() {
6861 return this.string;
6862 }
6863 toString() {
6864 return this.string.toString();
6865 }
6866 isBlockBreak() {
6867 return this.toString() === "\n" && this.getAttribute("blockBreak") === true;
6868 }
6869 toJSON() {
6870 const result = super.toJSON(...arguments);
6871 result.string = this.string;
6872 return result;
6873 }
6874
6875 // Splittable
6876
6877 canBeConsolidatedWith(piece) {
6878 return piece && this.hasSameConstructorAs(piece) && this.hasSameAttributesAsPiece(piece);
6879 }
6880 consolidateWith(piece) {
6881 return new this.constructor(this.toString() + piece.toString(), this.attributes);
6882 }
6883 splitAtOffset(offset) {
6884 let left, right;
6885 if (offset === 0) {
6886 left = null;
6887 right = this;
6888 } else if (offset === this.length) {
6889 left = this;
6890 right = null;
6891 } else {
6892 left = new this.constructor(this.string.slice(0, offset), this.attributes);
6893 right = new this.constructor(this.string.slice(offset), this.attributes);
6894 }
6895 return [left, right];
6896 }
6897 toConsole() {
6898 let {
6899 string
6900 } = this;
6901 if (string.length > 15) {
6902 string = string.slice(0, 14) + "…";
6903 }
6904 return JSON.stringify(string.toString());
6905 }
6906 }
6907 Piece.registerType("string", StringPiece);
6908
6909 /* eslint-disable
6910 prefer-const,
6911 */
6912 class SplittableList extends TrixObject {
6913 static box(objects) {
6914 if (objects instanceof this) {
6915 return objects;
6916 } else {
6917 return new this(objects);
6918 }
6919 }
6920 constructor() {
6921 let objects = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
6922 super(...arguments);
6923 this.objects = objects.slice(0);
6924 this.length = this.objects.length;
6925 }
6926 indexOf(object) {
6927 return this.objects.indexOf(object);
6928 }
6929 splice() {
6930 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
6931 args[_key] = arguments[_key];
6932 }
6933 return new this.constructor(spliceArray(this.objects, ...args));
6934 }
6935 eachObject(callback) {
6936 return this.objects.map((object, index) => callback(object, index));
6937 }
6938 insertObjectAtIndex(object, index) {
6939 return this.splice(index, 0, object);
6940 }
6941 insertSplittableListAtIndex(splittableList, index) {
6942 return this.splice(index, 0, ...splittableList.objects);
6943 }
6944 insertSplittableListAtPosition(splittableList, position) {
6945 const [objects, index] = this.splitObjectAtPosition(position);
6946 return new this.constructor(objects).insertSplittableListAtIndex(splittableList, index);
6947 }
6948 editObjectAtIndex(index, callback) {
6949 return this.replaceObjectAtIndex(callback(this.objects[index]), index);
6950 }
6951 replaceObjectAtIndex(object, index) {
6952 return this.splice(index, 1, object);
6953 }
6954 removeObjectAtIndex(index) {
6955 return this.splice(index, 1);
6956 }
6957 getObjectAtIndex(index) {
6958 return this.objects[index];
6959 }
6960 getSplittableListInRange(range) {
6961 const [objects, leftIndex, rightIndex] = this.splitObjectsAtRange(range);
6962 return new this.constructor(objects.slice(leftIndex, rightIndex + 1));
6963 }
6964 selectSplittableList(test) {
6965 const objects = this.objects.filter(object => test(object));
6966 return new this.constructor(objects);
6967 }
6968 removeObjectsInRange(range) {
6969 const [objects, leftIndex, rightIndex] = this.splitObjectsAtRange(range);
6970 return new this.constructor(objects).splice(leftIndex, rightIndex - leftIndex + 1);
6971 }
6972 transformObjectsInRange(range, transform) {
6973 const [objects, leftIndex, rightIndex] = this.splitObjectsAtRange(range);
6974 const transformedObjects = objects.map((object, index) => leftIndex <= index && index <= rightIndex ? transform(object) : object);
6975 return new this.constructor(transformedObjects);
6976 }
6977 splitObjectsAtRange(range) {
6978 let rightOuterIndex;
6979 let [objects, leftInnerIndex, offset] = this.splitObjectAtPosition(startOfRange(range));
6980 [objects, rightOuterIndex] = new this.constructor(objects).splitObjectAtPosition(endOfRange(range) + offset);
6981 return [objects, leftInnerIndex, rightOuterIndex - 1];
6982 }
6983 getObjectAtPosition(position) {
6984 const {
6985 index
6986 } = this.findIndexAndOffsetAtPosition(position);
6987 return this.objects[index];
6988 }
6989 splitObjectAtPosition(position) {
6990 let splitIndex, splitOffset;
6991 const {
6992 index,
6993 offset
6994 } = this.findIndexAndOffsetAtPosition(position);
6995 const objects = this.objects.slice(0);
6996 if (index != null) {
6997 if (offset === 0) {
6998 splitIndex = index;
6999 splitOffset = 0;
7000 } else {
7001 const object = this.getObjectAtIndex(index);
7002 const [leftObject, rightObject] = object.splitAtOffset(offset);
7003 objects.splice(index, 1, leftObject, rightObject);
7004 splitIndex = index + 1;
7005 splitOffset = leftObject.getLength() - offset;
7006 }
7007 } else {
7008 splitIndex = objects.length;
7009 splitOffset = 0;
7010 }
7011 return [objects, splitIndex, splitOffset];
7012 }
7013 consolidate() {
7014 const objects = [];
7015 let pendingObject = this.objects[0];
7016 this.objects.slice(1).forEach(object => {
7017 var _pendingObject$canBeC, _pendingObject;
7018 if ((_pendingObject$canBeC = (_pendingObject = pendingObject).canBeConsolidatedWith) !== null && _pendingObject$canBeC !== void 0 && _pendingObject$canBeC.call(_pendingObject, object)) {
7019 pendingObject = pendingObject.consolidateWith(object);
7020 } else {
7021 objects.push(pendingObject);
7022 pendingObject = object;
7023 }
7024 });
7025 if (pendingObject) {
7026 objects.push(pendingObject);
7027 }
7028 return new this.constructor(objects);
7029 }
7030 consolidateFromIndexToIndex(startIndex, endIndex) {
7031 const objects = this.objects.slice(0);
7032 const objectsInRange = objects.slice(startIndex, endIndex + 1);
7033 const consolidatedInRange = new this.constructor(objectsInRange).consolidate().toArray();
7034 return this.splice(startIndex, objectsInRange.length, ...consolidatedInRange);
7035 }
7036 findIndexAndOffsetAtPosition(position) {
7037 let index;
7038 let currentPosition = 0;
7039 for (index = 0; index < this.objects.length; index++) {
7040 const object = this.objects[index];
7041 const nextPosition = currentPosition + object.getLength();
7042 if (currentPosition <= position && position < nextPosition) {
7043 return {
7044 index,
7045 offset: position - currentPosition
7046 };
7047 }
7048 currentPosition = nextPosition;
7049 }
7050 return {
7051 index: null,
7052 offset: null
7053 };
7054 }
7055 findPositionAtIndexAndOffset(index, offset) {
7056 let position = 0;
7057 for (let currentIndex = 0; currentIndex < this.objects.length; currentIndex++) {
7058 const object = this.objects[currentIndex];
7059 if (currentIndex < index) {
7060 position += object.getLength();
7061 } else if (currentIndex === index) {
7062 position += offset;
7063 break;
7064 }
7065 }
7066 return position;
7067 }
7068 getEndPosition() {
7069 if (this.endPosition == null) {
7070 this.endPosition = 0;
7071 this.objects.forEach(object => this.endPosition += object.getLength());
7072 }
7073 return this.endPosition;
7074 }
7075 toString() {
7076 return this.objects.join("");
7077 }
7078 toArray() {
7079 return this.objects.slice(0);
7080 }
7081 toJSON() {
7082 return this.toArray();
7083 }
7084 isEqualTo(splittableList) {
7085 return super.isEqualTo(...arguments) || objectArraysAreEqual(this.objects, splittableList === null || splittableList === void 0 ? void 0 : splittableList.objects);
7086 }
7087 contentsForInspection() {
7088 return {
7089 objects: "[".concat(this.objects.map(object => object.inspect()).join(", "), "]")
7090 };
7091 }
7092 }
7093 const objectArraysAreEqual = function (left) {
7094 let right = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
7095 if (left.length !== right.length) {
7096 return false;
7097 }
7098 let result = true;
7099 for (let index = 0; index < left.length; index++) {
7100 const object = left[index];
7101 if (result && !object.isEqualTo(right[index])) {
7102 result = false;
7103 }
7104 }
7105 return result;
7106 };
7107 const startOfRange = range => range[0];
7108 const endOfRange = range => range[1];
7109
7110 class Text extends TrixObject {
7111 static textForAttachmentWithAttributes(attachment, attributes) {
7112 const piece = new AttachmentPiece(attachment, attributes);
7113 return new this([piece]);
7114 }
7115 static textForStringWithAttributes(string, attributes) {
7116 const piece = new StringPiece(string, attributes);
7117 return new this([piece]);
7118 }
7119 static fromJSON(textJSON) {
7120 const pieces = Array.from(textJSON).map(pieceJSON => Piece.fromJSON(pieceJSON));
7121 return new this(pieces);
7122 }
7123 constructor() {
7124 let pieces = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
7125 super(...arguments);
7126 const notEmpty = pieces.filter(piece => !piece.isEmpty());
7127 this.pieceList = new SplittableList(notEmpty);
7128 }
7129 copy() {
7130 return this.copyWithPieceList(this.pieceList);
7131 }
7132 copyWithPieceList(pieceList) {
7133 return new this.constructor(pieceList.consolidate().toArray());
7134 }
7135 copyUsingObjectMap(objectMap) {
7136 const pieces = this.getPieces().map(piece => objectMap.find(piece) || piece);
7137 return new this.constructor(pieces);
7138 }
7139 appendText(text) {
7140 return this.insertTextAtPosition(text, this.getLength());
7141 }
7142 insertTextAtPosition(text, position) {
7143 return this.copyWithPieceList(this.pieceList.insertSplittableListAtPosition(text.pieceList, position));
7144 }
7145 removeTextAtRange(range) {
7146 return this.copyWithPieceList(this.pieceList.removeObjectsInRange(range));
7147 }
7148 replaceTextAtRange(text, range) {
7149 return this.removeTextAtRange(range).insertTextAtPosition(text, range[0]);
7150 }
7151 moveTextFromRangeToPosition(range, position) {
7152 if (range[0] <= position && position <= range[1]) return;
7153 const text = this.getTextAtRange(range);
7154 const length = text.getLength();
7155 if (range[0] < position) {
7156 position -= length;
7157 }
7158 return this.removeTextAtRange(range).insertTextAtPosition(text, position);
7159 }
7160 addAttributeAtRange(attribute, value, range) {
7161 const attributes = {};
7162 attributes[attribute] = value;
7163 return this.addAttributesAtRange(attributes, range);
7164 }
7165 addAttributesAtRange(attributes, range) {
7166 return this.copyWithPieceList(this.pieceList.transformObjectsInRange(range, piece => piece.copyWithAdditionalAttributes(attributes)));
7167 }
7168 removeAttributeAtRange(attribute, range) {
7169 return this.copyWithPieceList(this.pieceList.transformObjectsInRange(range, piece => piece.copyWithoutAttribute(attribute)));
7170 }
7171 setAttributesAtRange(attributes, range) {
7172 return this.copyWithPieceList(this.pieceList.transformObjectsInRange(range, piece => piece.copyWithAttributes(attributes)));
7173 }
7174 getAttributesAtPosition(position) {
7175 var _this$pieceList$getOb;
7176 return ((_this$pieceList$getOb = this.pieceList.getObjectAtPosition(position)) === null || _this$pieceList$getOb === void 0 ? void 0 : _this$pieceList$getOb.getAttributes()) || {};
7177 }
7178 getCommonAttributes() {
7179 const objects = Array.from(this.pieceList.toArray()).map(piece => piece.getAttributes());
7180 return Hash.fromCommonAttributesOfObjects(objects).toObject();
7181 }
7182 getCommonAttributesAtRange(range) {
7183 return this.getTextAtRange(range).getCommonAttributes() || {};
7184 }
7185 getExpandedRangeForAttributeAtOffset(attributeName, offset) {
7186 let right;
7187 let left = right = offset;
7188 const length = this.getLength();
7189 while (left > 0 && this.getCommonAttributesAtRange([left - 1, right])[attributeName]) {
7190 left--;
7191 }
7192 while (right < length && this.getCommonAttributesAtRange([offset, right + 1])[attributeName]) {
7193 right++;
7194 }
7195 return [left, right];
7196 }
7197 getTextAtRange(range) {
7198 return this.copyWithPieceList(this.pieceList.getSplittableListInRange(range));
7199 }
7200 getStringAtRange(range) {
7201 return this.pieceList.getSplittableListInRange(range).toString();
7202 }
7203 getStringAtPosition(position) {
7204 return this.getStringAtRange([position, position + 1]);
7205 }
7206 startsWithString(string) {
7207 return this.getStringAtRange([0, string.length]) === string;
7208 }
7209 endsWithString(string) {
7210 const length = this.getLength();
7211 return this.getStringAtRange([length - string.length, length]) === string;
7212 }
7213 getAttachmentPieces() {
7214 return this.pieceList.toArray().filter(piece => !!piece.attachment);
7215 }
7216 getAttachments() {
7217 return this.getAttachmentPieces().map(piece => piece.attachment);
7218 }
7219 getAttachmentAndPositionById(attachmentId) {
7220 let position = 0;
7221 for (const piece of this.pieceList.toArray()) {
7222 var _piece$attachment;
7223 if (((_piece$attachment = piece.attachment) === null || _piece$attachment === void 0 ? void 0 : _piece$attachment.id) === attachmentId) {
7224 return {
7225 attachment: piece.attachment,
7226 position
7227 };
7228 }
7229 position += piece.length;
7230 }
7231 return {
7232 attachment: null,
7233 position: null
7234 };
7235 }
7236 getAttachmentById(attachmentId) {
7237 const {
7238 attachment
7239 } = this.getAttachmentAndPositionById(attachmentId);
7240 return attachment;
7241 }
7242 getRangeOfAttachment(attachment) {
7243 const attachmentAndPosition = this.getAttachmentAndPositionById(attachment.id);
7244 const position = attachmentAndPosition.position;
7245 attachment = attachmentAndPosition.attachment;
7246 if (attachment) {
7247 return [position, position + 1];
7248 }
7249 }
7250 updateAttributesForAttachment(attributes, attachment) {
7251 const range = this.getRangeOfAttachment(attachment);
7252 if (range) {
7253 return this.addAttributesAtRange(attributes, range);
7254 } else {
7255 return this;
7256 }
7257 }
7258 getLength() {
7259 return this.pieceList.getEndPosition();
7260 }
7261 isEmpty() {
7262 return this.getLength() === 0;
7263 }
7264 isEqualTo(text) {
7265 var _text$pieceList;
7266 return super.isEqualTo(text) || (text === null || text === void 0 || (_text$pieceList = text.pieceList) === null || _text$pieceList === void 0 ? void 0 : _text$pieceList.isEqualTo(this.pieceList));
7267 }
7268 isBlockBreak() {
7269 return this.getLength() === 1 && this.pieceList.getObjectAtIndex(0).isBlockBreak();
7270 }
7271 eachPiece(callback) {
7272 return this.pieceList.eachObject(callback);
7273 }
7274 getPieces() {
7275 return this.pieceList.toArray();
7276 }
7277 getPieceAtPosition(position) {
7278 return this.pieceList.getObjectAtPosition(position);
7279 }
7280 contentsForInspection() {
7281 return {
7282 pieceList: this.pieceList.inspect()
7283 };
7284 }
7285 toSerializableText() {
7286 const pieceList = this.pieceList.selectSplittableList(piece => piece.isSerializable());
7287 return this.copyWithPieceList(pieceList);
7288 }
7289 toString() {
7290 return this.pieceList.toString();
7291 }
7292 toJSON() {
7293 return this.pieceList.toJSON();
7294 }
7295 toConsole() {
7296 return JSON.stringify(this.pieceList.toArray().map(piece => JSON.parse(piece.toConsole())));
7297 }
7298
7299 // BIDI
7300
7301 getDirection() {
7302 return getDirection(this.toString());
7303 }
7304 isRTL() {
7305 return this.getDirection() === "rtl";
7306 }
7307 }
7308
7309 class Block extends TrixObject {
7310 static fromJSON(blockJSON) {
7311 const text = Text.fromJSON(blockJSON.text);
7312 return new this(text, blockJSON.attributes, blockJSON.htmlAttributes);
7313 }
7314 constructor(text, attributes, htmlAttributes) {
7315 super(...arguments);
7316 this.text = applyBlockBreakToText(text || new Text());
7317 this.attributes = attributes || [];
7318 this.htmlAttributes = htmlAttributes || {};
7319 }
7320 isEmpty() {
7321 return this.text.isBlockBreak();
7322 }
7323 isEqualTo(block) {
7324 if (super.isEqualTo(block)) return true;
7325 return this.text.isEqualTo(block === null || block === void 0 ? void 0 : block.text) && arraysAreEqual(this.attributes, block === null || block === void 0 ? void 0 : block.attributes) && objectsAreEqual(this.htmlAttributes, block === null || block === void 0 ? void 0 : block.htmlAttributes);
7326 }
7327 copyWithText(text) {
7328 return new Block(text, this.attributes, this.htmlAttributes);
7329 }
7330 copyWithoutText() {
7331 return this.copyWithText(null);
7332 }
7333 copyWithAttributes(attributes) {
7334 return new Block(this.text, attributes, this.htmlAttributes);
7335 }
7336 copyWithoutAttributes() {
7337 return this.copyWithAttributes(null);
7338 }
7339 copyUsingObjectMap(objectMap) {
7340 const mappedText = objectMap.find(this.text);
7341 if (mappedText) {
7342 return this.copyWithText(mappedText);
7343 } else {
7344 return this.copyWithText(this.text.copyUsingObjectMap(objectMap));
7345 }
7346 }
7347 addAttribute(attribute) {
7348 const attributes = this.attributes.concat(expandAttribute(attribute));
7349 return this.copyWithAttributes(attributes);
7350 }
7351 addHTMLAttribute(attribute, value) {
7352 const htmlAttributes = Object.assign({}, this.htmlAttributes, {
7353 [attribute]: value
7354 });
7355 return new Block(this.text, this.attributes, htmlAttributes);
7356 }
7357 removeAttribute(attribute) {
7358 const {
7359 listAttribute
7360 } = getBlockConfig(attribute);
7361 const attributes = removeLastValue(removeLastValue(this.attributes, attribute), listAttribute);
7362 return this.copyWithAttributes(attributes);
7363 }
7364 removeLastAttribute() {
7365 return this.removeAttribute(this.getLastAttribute());
7366 }
7367 getLastAttribute() {
7368 return getLastElement(this.attributes);
7369 }
7370 getAttributes() {
7371 return this.attributes.slice(0);
7372 }
7373 getAttributeLevel() {
7374 return this.attributes.length;
7375 }
7376 getAttributeAtLevel(level) {
7377 return this.attributes[level - 1];
7378 }
7379 hasAttribute(attributeName) {
7380 return this.attributes.includes(attributeName);
7381 }
7382 hasAttributes() {
7383 return this.getAttributeLevel() > 0;
7384 }
7385 getLastNestableAttribute() {
7386 return getLastElement(this.getNestableAttributes());
7387 }
7388 getNestableAttributes() {
7389 return this.attributes.filter(attribute => getBlockConfig(attribute).nestable);
7390 }
7391 getNestingLevel() {
7392 return this.getNestableAttributes().length;
7393 }
7394 decreaseNestingLevel() {
7395 const attribute = this.getLastNestableAttribute();
7396 if (attribute) {
7397 return this.removeAttribute(attribute);
7398 } else {
7399 return this;
7400 }
7401 }
7402 increaseNestingLevel() {
7403 const attribute = this.getLastNestableAttribute();
7404 if (attribute) {
7405 const index = this.attributes.lastIndexOf(attribute);
7406 const attributes = spliceArray(this.attributes, index + 1, 0, ...expandAttribute(attribute));
7407 return this.copyWithAttributes(attributes);
7408 } else {
7409 return this;
7410 }
7411 }
7412 getListItemAttributes() {
7413 return this.attributes.filter(attribute => getBlockConfig(attribute).listAttribute);
7414 }
7415 isListItem() {
7416 var _getBlockConfig;
7417 return (_getBlockConfig = getBlockConfig(this.getLastAttribute())) === null || _getBlockConfig === void 0 ? void 0 : _getBlockConfig.listAttribute;
7418 }
7419 isTerminalBlock() {
7420 var _getBlockConfig2;
7421 return (_getBlockConfig2 = getBlockConfig(this.getLastAttribute())) === null || _getBlockConfig2 === void 0 ? void 0 : _getBlockConfig2.terminal;
7422 }
7423 breaksOnReturn() {
7424 var _getBlockConfig3;
7425 return (_getBlockConfig3 = getBlockConfig(this.getLastAttribute())) === null || _getBlockConfig3 === void 0 ? void 0 : _getBlockConfig3.breakOnReturn;
7426 }
7427 findLineBreakInDirectionFromPosition(direction, position) {
7428 const string = this.toString();
7429 let result;
7430 switch (direction) {
7431 case "forward":
7432 result = string.indexOf("\n", position);
7433 break;
7434 case "backward":
7435 result = string.slice(0, position).lastIndexOf("\n");
7436 }
7437 if (result !== -1) {
7438 return result;
7439 }
7440 }
7441 contentsForInspection() {
7442 return {
7443 text: this.text.inspect(),
7444 attributes: this.attributes
7445 };
7446 }
7447 toString() {
7448 return this.text.toString();
7449 }
7450 toJSON() {
7451 return {
7452 text: this.text,
7453 attributes: this.attributes,
7454 htmlAttributes: this.htmlAttributes
7455 };
7456 }
7457
7458 // BIDI
7459
7460 getDirection() {
7461 return this.text.getDirection();
7462 }
7463 isRTL() {
7464 return this.text.isRTL();
7465 }
7466
7467 // Splittable
7468
7469 getLength() {
7470 return this.text.getLength();
7471 }
7472 canBeConsolidatedWith(block) {
7473 return !this.hasAttributes() && !block.hasAttributes() && this.getDirection() === block.getDirection();
7474 }
7475 consolidateWith(block) {
7476 const newlineText = Text.textForStringWithAttributes("\n");
7477 const text = this.getTextWithoutBlockBreak().appendText(newlineText);
7478 return this.copyWithText(text.appendText(block.text));
7479 }
7480 splitAtOffset(offset) {
7481 let left, right;
7482 if (offset === 0) {
7483 left = null;
7484 right = this;
7485 } else if (offset === this.getLength()) {
7486 left = this;
7487 right = null;
7488 } else {
7489 left = this.copyWithText(this.text.getTextAtRange([0, offset]));
7490 right = this.copyWithText(this.text.getTextAtRange([offset, this.getLength()]));
7491 }
7492 return [left, right];
7493 }
7494 getBlockBreakPosition() {
7495 return this.text.getLength() - 1;
7496 }
7497 getTextWithoutBlockBreak() {
7498 if (textEndsInBlockBreak(this.text)) {
7499 return this.text.getTextAtRange([0, this.getBlockBreakPosition()]);
7500 } else {
7501 return this.text.copy();
7502 }
7503 }
7504
7505 // Grouping
7506
7507 canBeGrouped(depth) {
7508 return this.attributes[depth];
7509 }
7510 canBeGroupedWith(otherBlock, depth) {
7511 const otherAttributes = otherBlock.getAttributes();
7512 const otherAttribute = otherAttributes[depth];
7513 const attribute = this.attributes[depth];
7514 return attribute === otherAttribute && !(getBlockConfig(attribute).group === false && !getListAttributeNames().includes(otherAttributes[depth + 1])) && (this.getDirection() === otherBlock.getDirection() || otherBlock.isEmpty());
7515 }
7516 }
7517
7518 // Block breaks
7519
7520 const applyBlockBreakToText = function (text) {
7521 text = unmarkExistingInnerBlockBreaksInText(text);
7522 text = addBlockBreakToText(text);
7523 return text;
7524 };
7525 const unmarkExistingInnerBlockBreaksInText = function (text) {
7526 let modified = false;
7527 const pieces = text.getPieces();
7528 let innerPieces = pieces.slice(0, pieces.length - 1);
7529 const lastPiece = pieces[pieces.length - 1];
7530 if (!lastPiece) return text;
7531 innerPieces = innerPieces.map(piece => {
7532 if (piece.isBlockBreak()) {
7533 modified = true;
7534 return unmarkBlockBreakPiece(piece);
7535 } else {
7536 return piece;
7537 }
7538 });
7539 if (modified) {
7540 return new Text([...innerPieces, lastPiece]);
7541 } else {
7542 return text;
7543 }
7544 };
7545 const blockBreakText = Text.textForStringWithAttributes("\n", {
7546 blockBreak: true
7547 });
7548 const addBlockBreakToText = function (text) {
7549 if (textEndsInBlockBreak(text)) {
7550 return text;
7551 } else {
7552 return text.appendText(blockBreakText);
7553 }
7554 };
7555 const textEndsInBlockBreak = function (text) {
7556 const length = text.getLength();
7557 if (length === 0) {
7558 return false;
7559 }
7560 const endText = text.getTextAtRange([length - 1, length]);
7561 return endText.isBlockBreak();
7562 };
7563 const unmarkBlockBreakPiece = piece => piece.copyWithoutAttribute("blockBreak");
7564
7565 // Attributes
7566
7567 const expandAttribute = function (attribute) {
7568 const {
7569 listAttribute
7570 } = getBlockConfig(attribute);
7571 if (listAttribute) {
7572 return [listAttribute, attribute];
7573 } else {
7574 return [attribute];
7575 }
7576 };
7577
7578 // Array helpers
7579
7580 const getLastElement = array => array.slice(-1)[0];
7581 const removeLastValue = function (array, value) {
7582 const index = array.lastIndexOf(value);
7583 if (index === -1) {
7584 return array;
7585 } else {
7586 return spliceArray(array, index, 1);
7587 }
7588 };
7589
7590 class Document extends TrixObject {
7591 static fromJSON(documentJSON) {
7592 const blocks = Array.from(documentJSON).map(blockJSON => Block.fromJSON(blockJSON));
7593 return new this(blocks);
7594 }
7595 static fromString(string, textAttributes) {
7596 const text = Text.textForStringWithAttributes(string, textAttributes);
7597 return new this([new Block(text)]);
7598 }
7599 constructor() {
7600 let blocks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
7601 super(...arguments);
7602 if (blocks.length === 0) {
7603 blocks = [new Block()];
7604 }
7605 this.blockList = SplittableList.box(blocks);
7606 }
7607 isEmpty() {
7608 const block = this.getBlockAtIndex(0);
7609 return this.blockList.length === 1 && block.isEmpty() && !block.hasAttributes();
7610 }
7611 copy() {
7612 let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
7613 const blocks = options.consolidateBlocks ? this.blockList.consolidate().toArray() : this.blockList.toArray();
7614 return new this.constructor(blocks);
7615 }
7616 copyUsingObjectsFromDocument(sourceDocument) {
7617 const objectMap = new ObjectMap(sourceDocument.getObjects());
7618 return this.copyUsingObjectMap(objectMap);
7619 }
7620 copyUsingObjectMap(objectMap) {
7621 const blocks = this.getBlocks().map(block => {
7622 const mappedBlock = objectMap.find(block);
7623 return mappedBlock || block.copyUsingObjectMap(objectMap);
7624 });
7625 return new this.constructor(blocks);
7626 }
7627 copyWithBaseBlockAttributes() {
7628 let blockAttributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
7629 const blocks = this.getBlocks().map(block => {
7630 const attributes = blockAttributes.concat(block.getAttributes());
7631 return block.copyWithAttributes(attributes);
7632 });
7633 return new this.constructor(blocks);
7634 }
7635 replaceBlock(oldBlock, newBlock) {
7636 const index = this.blockList.indexOf(oldBlock);
7637 if (index === -1) {
7638 return this;
7639 }
7640 return new this.constructor(this.blockList.replaceObjectAtIndex(newBlock, index));
7641 }
7642 insertDocumentAtRange(document, range) {
7643 const {
7644 blockList
7645 } = document;
7646 range = normalizeRange(range);
7647 let [position] = range;
7648 const {
7649 index,
7650 offset
7651 } = this.locationFromPosition(position);
7652 let result = this;
7653 const block = this.getBlockAtPosition(position);
7654 if (rangeIsCollapsed(range) && block.isEmpty() && !block.hasAttributes()) {
7655 result = new this.constructor(result.blockList.removeObjectAtIndex(index));
7656 } else if (block.getBlockBreakPosition() === offset) {
7657 position++;
7658 }
7659 result = result.removeTextAtRange(range);
7660 return new this.constructor(result.blockList.insertSplittableListAtPosition(blockList, position));
7661 }
7662 mergeDocumentAtRange(document, range) {
7663 let formattedDocument, result;
7664 range = normalizeRange(range);
7665 const [startPosition] = range;
7666 const startLocation = this.locationFromPosition(startPosition);
7667 const blockAttributes = this.getBlockAtIndex(startLocation.index).getAttributes();
7668 const baseBlockAttributes = document.getBaseBlockAttributes();
7669 const trailingBlockAttributes = blockAttributes.slice(-baseBlockAttributes.length);
7670 if (arraysAreEqual(baseBlockAttributes, trailingBlockAttributes)) {
7671 const leadingBlockAttributes = blockAttributes.slice(0, -baseBlockAttributes.length);
7672 formattedDocument = document.copyWithBaseBlockAttributes(leadingBlockAttributes);
7673 } else {
7674 formattedDocument = document.copy({
7675 consolidateBlocks: true
7676 }).copyWithBaseBlockAttributes(blockAttributes);
7677 }
7678 const blockCount = formattedDocument.getBlockCount();
7679 const firstBlock = formattedDocument.getBlockAtIndex(0);
7680 if (arraysAreEqual(blockAttributes, firstBlock.getAttributes())) {
7681 const firstText = firstBlock.getTextWithoutBlockBreak();
7682 result = this.insertTextAtRange(firstText, range);
7683 if (blockCount > 1) {
7684 formattedDocument = new this.constructor(formattedDocument.getBlocks().slice(1));
7685 const position = startPosition + firstText.getLength();
7686 result = result.insertDocumentAtRange(formattedDocument, position);
7687 }
7688 } else {
7689 result = this.insertDocumentAtRange(formattedDocument, range);
7690 }
7691 return result;
7692 }
7693 insertTextAtRange(text, range) {
7694 range = normalizeRange(range);
7695 const [startPosition] = range;
7696 const {
7697 index,
7698 offset
7699 } = this.locationFromPosition(startPosition);
7700 const document = this.removeTextAtRange(range);
7701 return new this.constructor(document.blockList.editObjectAtIndex(index, block => block.copyWithText(block.text.insertTextAtPosition(text, offset))));
7702 }
7703 removeTextAtRange(range) {
7704 let blocks;
7705 range = normalizeRange(range);
7706 const [leftPosition, rightPosition] = range;
7707 if (rangeIsCollapsed(range)) {
7708 return this;
7709 }
7710 const [leftLocation, rightLocation] = Array.from(this.locationRangeFromRange(range));
7711 const leftIndex = leftLocation.index;
7712 const leftOffset = leftLocation.offset;
7713 const leftBlock = this.getBlockAtIndex(leftIndex);
7714 const rightIndex = rightLocation.index;
7715 const rightOffset = rightLocation.offset;
7716 const rightBlock = this.getBlockAtIndex(rightIndex);
7717 const removeRightNewline = rightPosition - leftPosition === 1 && leftBlock.getBlockBreakPosition() === leftOffset && rightBlock.getBlockBreakPosition() !== rightOffset && rightBlock.text.getStringAtPosition(rightOffset) === "\n";
7718 if (removeRightNewline) {
7719 blocks = this.blockList.editObjectAtIndex(rightIndex, block => block.copyWithText(block.text.removeTextAtRange([rightOffset, rightOffset + 1])));
7720 } else {
7721 let block;
7722 const leftText = leftBlock.text.getTextAtRange([0, leftOffset]);
7723 const rightText = rightBlock.text.getTextAtRange([rightOffset, rightBlock.getLength()]);
7724 const text = leftText.appendText(rightText);
7725 const removingLeftBlock = leftIndex !== rightIndex && leftOffset === 0;
7726 const useRightBlock = removingLeftBlock && leftBlock.getAttributeLevel() >= rightBlock.getAttributeLevel();
7727 if (useRightBlock) {
7728 block = rightBlock.copyWithText(text);
7729 } else {
7730 block = leftBlock.copyWithText(text);
7731 }
7732 const affectedBlockCount = rightIndex + 1 - leftIndex;
7733 blocks = this.blockList.splice(leftIndex, affectedBlockCount, block);
7734 }
7735 return new this.constructor(blocks);
7736 }
7737 moveTextFromRangeToPosition(range, position) {
7738 let text;
7739 range = normalizeRange(range);
7740 const [startPosition, endPosition] = range;
7741 if (startPosition <= position && position <= endPosition) {
7742 return this;
7743 }
7744 let document = this.getDocumentAtRange(range);
7745 let result = this.removeTextAtRange(range);
7746 const movingRightward = startPosition < position;
7747 if (movingRightward) {
7748 position -= document.getLength();
7749 }
7750 const [firstBlock, ...blocks] = document.getBlocks();
7751 if (blocks.length === 0) {
7752 text = firstBlock.getTextWithoutBlockBreak();
7753 if (movingRightward) {
7754 position += 1;
7755 }
7756 } else {
7757 text = firstBlock.text;
7758 }
7759 result = result.insertTextAtRange(text, position);
7760 if (blocks.length === 0) {
7761 return result;
7762 }
7763 document = new this.constructor(blocks);
7764 position += text.getLength();
7765 return result.insertDocumentAtRange(document, position);
7766 }
7767 addAttributeAtRange(attribute, value, range) {
7768 let {
7769 blockList
7770 } = this;
7771 this.eachBlockAtRange(range, (block, textRange, index) => blockList = blockList.editObjectAtIndex(index, function () {
7772 if (getBlockConfig(attribute)) {
7773 return block.addAttribute(attribute, value);
7774 } else {
7775 if (textRange[0] === textRange[1]) {
7776 return block;
7777 } else {
7778 return block.copyWithText(block.text.addAttributeAtRange(attribute, value, textRange));
7779 }
7780 }
7781 }));
7782 return new this.constructor(blockList);
7783 }
7784 addAttribute(attribute, value) {
7785 let {
7786 blockList
7787 } = this;
7788 this.eachBlock((block, index) => blockList = blockList.editObjectAtIndex(index, () => block.addAttribute(attribute, value)));
7789 return new this.constructor(blockList);
7790 }
7791 removeAttributeAtRange(attribute, range) {
7792 let {
7793 blockList
7794 } = this;
7795 this.eachBlockAtRange(range, function (block, textRange, index) {
7796 if (getBlockConfig(attribute)) {
7797 blockList = blockList.editObjectAtIndex(index, () => block.removeAttribute(attribute));
7798 } else if (textRange[0] !== textRange[1]) {
7799 blockList = blockList.editObjectAtIndex(index, () => block.copyWithText(block.text.removeAttributeAtRange(attribute, textRange)));
7800 }
7801 });
7802 return new this.constructor(blockList);
7803 }
7804 updateAttributesForAttachment(attributes, attachment) {
7805 const range = this.getRangeOfAttachment(attachment);
7806 const [startPosition] = Array.from(range);
7807 const {
7808 index
7809 } = this.locationFromPosition(startPosition);
7810 const text = this.getTextAtIndex(index);
7811 return new this.constructor(this.blockList.editObjectAtIndex(index, block => block.copyWithText(text.updateAttributesForAttachment(attributes, attachment))));
7812 }
7813 removeAttributeForAttachment(attribute, attachment) {
7814 const range = this.getRangeOfAttachment(attachment);
7815 return this.removeAttributeAtRange(attribute, range);
7816 }
7817 setHTMLAttributeAtPosition(position, name, value) {
7818 const block = this.getBlockAtPosition(position);
7819 const updatedBlock = block.addHTMLAttribute(name, value);
7820 return this.replaceBlock(block, updatedBlock);
7821 }
7822 insertBlockBreakAtRange(range) {
7823 let blocks;
7824 range = normalizeRange(range);
7825 const [startPosition] = range;
7826 const {
7827 offset
7828 } = this.locationFromPosition(startPosition);
7829 const document = this.removeTextAtRange(range);
7830 if (offset === 0) {
7831 blocks = [new Block()];
7832 }
7833 return new this.constructor(document.blockList.insertSplittableListAtPosition(new SplittableList(blocks), startPosition));
7834 }
7835 applyBlockAttributeAtRange(attributeName, value, range) {
7836 const expanded = this.expandRangeToLineBreaksAndSplitBlocks(range);
7837 let document = expanded.document;
7838 range = expanded.range;
7839 const blockConfig = getBlockConfig(attributeName);
7840 if (blockConfig.listAttribute) {
7841 document = document.removeLastListAttributeAtRange(range, {
7842 exceptAttributeName: attributeName
7843 });
7844 const converted = document.convertLineBreaksToBlockBreaksInRange(range);
7845 document = converted.document;
7846 range = converted.range;
7847 } else if (blockConfig.exclusive) {
7848 document = document.removeBlockAttributesAtRange(range);
7849 } else if (blockConfig.terminal) {
7850 document = document.removeLastTerminalAttributeAtRange(range);
7851 } else {
7852 document = document.consolidateBlocksAtRange(range);
7853 }
7854 return document.addAttributeAtRange(attributeName, value, range);
7855 }
7856 removeLastListAttributeAtRange(range) {
7857 let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7858 let {
7859 blockList
7860 } = this;
7861 this.eachBlockAtRange(range, function (block, textRange, index) {
7862 const lastAttributeName = block.getLastAttribute();
7863 if (!lastAttributeName) {
7864 return;
7865 }
7866 if (!getBlockConfig(lastAttributeName).listAttribute) {
7867 return;
7868 }
7869 if (lastAttributeName === options.exceptAttributeName) {
7870 return;
7871 }
7872 blockList = blockList.editObjectAtIndex(index, () => block.removeAttribute(lastAttributeName));
7873 });
7874 return new this.constructor(blockList);
7875 }
7876 removeLastTerminalAttributeAtRange(range) {
7877 let {
7878 blockList
7879 } = this;
7880 this.eachBlockAtRange(range, function (block, textRange, index) {
7881 const lastAttributeName = block.getLastAttribute();
7882 if (!lastAttributeName) {
7883 return;
7884 }
7885 if (!getBlockConfig(lastAttributeName).terminal) {
7886 return;
7887 }
7888 blockList = blockList.editObjectAtIndex(index, () => block.removeAttribute(lastAttributeName));
7889 });
7890 return new this.constructor(blockList);
7891 }
7892 removeBlockAttributesAtRange(range) {
7893 let {
7894 blockList
7895 } = this;
7896 this.eachBlockAtRange(range, function (block, textRange, index) {
7897 if (block.hasAttributes()) {
7898 blockList = blockList.editObjectAtIndex(index, () => block.copyWithoutAttributes());
7899 }
7900 });
7901 return new this.constructor(blockList);
7902 }
7903 expandRangeToLineBreaksAndSplitBlocks(range) {
7904 let position;
7905 range = normalizeRange(range);
7906 let [startPosition, endPosition] = range;
7907 const startLocation = this.locationFromPosition(startPosition);
7908 const endLocation = this.locationFromPosition(endPosition);
7909 let document = this;
7910 const startBlock = document.getBlockAtIndex(startLocation.index);
7911 startLocation.offset = startBlock.findLineBreakInDirectionFromPosition("backward", startLocation.offset);
7912 if (startLocation.offset != null) {
7913 position = document.positionFromLocation(startLocation);
7914 document = document.insertBlockBreakAtRange([position, position + 1]);
7915 endLocation.index += 1;
7916 endLocation.offset -= document.getBlockAtIndex(startLocation.index).getLength();
7917 startLocation.index += 1;
7918 }
7919 startLocation.offset = 0;
7920 if (endLocation.offset === 0 && endLocation.index > startLocation.index) {
7921 endLocation.index -= 1;
7922 endLocation.offset = document.getBlockAtIndex(endLocation.index).getBlockBreakPosition();
7923 } else {
7924 const endBlock = document.getBlockAtIndex(endLocation.index);
7925 if (endBlock.text.getStringAtRange([endLocation.offset - 1, endLocation.offset]) === "\n") {
7926 endLocation.offset -= 1;
7927 } else {
7928 endLocation.offset = endBlock.findLineBreakInDirectionFromPosition("forward", endLocation.offset);
7929 }
7930 if (endLocation.offset !== endBlock.getBlockBreakPosition()) {
7931 position = document.positionFromLocation(endLocation);
7932 document = document.insertBlockBreakAtRange([position, position + 1]);
7933 }
7934 }
7935 startPosition = document.positionFromLocation(startLocation);
7936 endPosition = document.positionFromLocation(endLocation);
7937 range = normalizeRange([startPosition, endPosition]);
7938 return {
7939 document,
7940 range
7941 };
7942 }
7943 convertLineBreaksToBlockBreaksInRange(range) {
7944 range = normalizeRange(range);
7945 let [position] = range;
7946 const string = this.getStringAtRange(range).slice(0, -1);
7947 let document = this;
7948 string.replace(/.*?\n/g, function (match) {
7949 position += match.length;
7950 document = document.insertBlockBreakAtRange([position - 1, position]);
7951 });
7952 return {
7953 document,
7954 range
7955 };
7956 }
7957 consolidateBlocksAtRange(range) {
7958 range = normalizeRange(range);
7959 const [startPosition, endPosition] = range;
7960 const startIndex = this.locationFromPosition(startPosition).index;
7961 const endIndex = this.locationFromPosition(endPosition).index;
7962 return new this.constructor(this.blockList.consolidateFromIndexToIndex(startIndex, endIndex));
7963 }
7964 getDocumentAtRange(range) {
7965 range = normalizeRange(range);
7966 const blocks = this.blockList.getSplittableListInRange(range).toArray();
7967 return new this.constructor(blocks);
7968 }
7969 getStringAtRange(range) {
7970 let endIndex;
7971 const array = range = normalizeRange(range),
7972 endPosition = array[array.length - 1];
7973 if (endPosition !== this.getLength()) {
7974 endIndex = -1;
7975 }
7976 return this.getDocumentAtRange(range).toString().slice(0, endIndex);
7977 }
7978 getBlockAtIndex(index) {
7979 return this.blockList.getObjectAtIndex(index);
7980 }
7981 getBlockAtPosition(position) {
7982 const {
7983 index
7984 } = this.locationFromPosition(position);
7985 return this.getBlockAtIndex(index);
7986 }
7987 getTextAtIndex(index) {
7988 var _this$getBlockAtIndex;
7989 return (_this$getBlockAtIndex = this.getBlockAtIndex(index)) === null || _this$getBlockAtIndex === void 0 ? void 0 : _this$getBlockAtIndex.text;
7990 }
7991 getTextAtPosition(position) {
7992 const {
7993 index
7994 } = this.locationFromPosition(position);
7995 return this.getTextAtIndex(index);
7996 }
7997 getPieceAtPosition(position) {
7998 const {
7999 index,
8000 offset
8001 } = this.locationFromPosition(position);
8002 return this.getTextAtIndex(index).getPieceAtPosition(offset);
8003 }
8004 getCharacterAtPosition(position) {
8005 const {
8006 index,
8007 offset
8008 } = this.locationFromPosition(position);
8009 return this.getTextAtIndex(index).getStringAtRange([offset, offset + 1]);
8010 }
8011 getLength() {
8012 return this.blockList.getEndPosition();
8013 }
8014 getBlocks() {
8015 return this.blockList.toArray();
8016 }
8017 getBlockCount() {
8018 return this.blockList.length;
8019 }
8020 getEditCount() {
8021 return this.editCount;
8022 }
8023 eachBlock(callback) {
8024 return this.blockList.eachObject(callback);
8025 }
8026 eachBlockAtRange(range, callback) {
8027 let block, textRange;
8028 range = normalizeRange(range);
8029 const [startPosition, endPosition] = range;
8030 const startLocation = this.locationFromPosition(startPosition);
8031 const endLocation = this.locationFromPosition(endPosition);
8032 if (startLocation.index === endLocation.index) {
8033 block = this.getBlockAtIndex(startLocation.index);
8034 textRange = [startLocation.offset, endLocation.offset];
8035 return callback(block, textRange, startLocation.index);
8036 } else {
8037 for (let index = startLocation.index; index <= endLocation.index; index++) {
8038 block = this.getBlockAtIndex(index);
8039 if (block) {
8040 switch (index) {
8041 case startLocation.index:
8042 textRange = [startLocation.offset, block.text.getLength()];
8043 break;
8044 case endLocation.index:
8045 textRange = [0, endLocation.offset];
8046 break;
8047 default:
8048 textRange = [0, block.text.getLength()];
8049 }
8050 callback(block, textRange, index);
8051 }
8052 }
8053 }
8054 }
8055 getCommonAttributesAtRange(range) {
8056 range = normalizeRange(range);
8057 const [startPosition] = range;
8058 if (rangeIsCollapsed(range)) {
8059 return this.getCommonAttributesAtPosition(startPosition);
8060 } else {
8061 const textAttributes = [];
8062 const blockAttributes = [];
8063 this.eachBlockAtRange(range, function (block, textRange) {
8064 if (textRange[0] !== textRange[1]) {
8065 textAttributes.push(block.text.getCommonAttributesAtRange(textRange));
8066 return blockAttributes.push(attributesForBlock(block));
8067 }
8068 });
8069 return Hash.fromCommonAttributesOfObjects(textAttributes).merge(Hash.fromCommonAttributesOfObjects(blockAttributes)).toObject();
8070 }
8071 }
8072 getCommonAttributesAtPosition(position) {
8073 let key, value;
8074 const {
8075 index,
8076 offset
8077 } = this.locationFromPosition(position);
8078 const block = this.getBlockAtIndex(index);
8079 if (!block) {
8080 return {};
8081 }
8082 const commonAttributes = attributesForBlock(block);
8083 const attributes = block.text.getAttributesAtPosition(offset);
8084 const attributesLeft = block.text.getAttributesAtPosition(offset - 1);
8085 const inheritableAttributes = Object.keys(text_attributes).filter(key => {
8086 return text_attributes[key].inheritable;
8087 });
8088 for (key in attributesLeft) {
8089 value = attributesLeft[key];
8090 if (value === attributes[key] || inheritableAttributes.includes(key)) {
8091 commonAttributes[key] = value;
8092 }
8093 }
8094 return commonAttributes;
8095 }
8096 getRangeOfCommonAttributeAtPosition(attributeName, position) {
8097 const {
8098 index,
8099 offset
8100 } = this.locationFromPosition(position);
8101 const text = this.getTextAtIndex(index);
8102 const [startOffset, endOffset] = Array.from(text.getExpandedRangeForAttributeAtOffset(attributeName, offset));
8103 const start = this.positionFromLocation({
8104 index,
8105 offset: startOffset
8106 });
8107 const end = this.positionFromLocation({
8108 index,
8109 offset: endOffset
8110 });
8111 return normalizeRange([start, end]);
8112 }
8113 getBaseBlockAttributes() {
8114 let baseBlockAttributes = this.getBlockAtIndex(0).getAttributes();
8115 for (let blockIndex = 1; blockIndex < this.getBlockCount(); blockIndex++) {
8116 const blockAttributes = this.getBlockAtIndex(blockIndex).getAttributes();
8117 const lastAttributeIndex = Math.min(baseBlockAttributes.length, blockAttributes.length);
8118 baseBlockAttributes = (() => {
8119 const result = [];
8120 for (let index = 0; index < lastAttributeIndex; index++) {
8121 if (blockAttributes[index] !== baseBlockAttributes[index]) {
8122 break;
8123 }
8124 result.push(blockAttributes[index]);
8125 }
8126 return result;
8127 })();
8128 }
8129 return baseBlockAttributes;
8130 }
8131 getAttachmentById(attachmentId) {
8132 for (const attachment of this.getAttachments()) {
8133 if (attachment.id === attachmentId) {
8134 return attachment;
8135 }
8136 }
8137 }
8138 getAttachmentPieces() {
8139 let attachmentPieces = [];
8140 this.blockList.eachObject(_ref => {
8141 let {
8142 text
8143 } = _ref;
8144 return attachmentPieces = attachmentPieces.concat(text.getAttachmentPieces());
8145 });
8146 return attachmentPieces;
8147 }
8148 getAttachments() {
8149 return this.getAttachmentPieces().map(piece => piece.attachment);
8150 }
8151 getRangeOfAttachment(attachment) {
8152 let position = 0;
8153 const iterable = this.blockList.toArray();
8154 for (let index = 0; index < iterable.length; index++) {
8155 const {
8156 text
8157 } = iterable[index];
8158 const textRange = text.getRangeOfAttachment(attachment);
8159 if (textRange) {
8160 return normalizeRange([position + textRange[0], position + textRange[1]]);
8161 }
8162 position += text.getLength();
8163 }
8164 }
8165 getLocationRangeOfAttachment(attachment) {
8166 const range = this.getRangeOfAttachment(attachment);
8167 return this.locationRangeFromRange(range);
8168 }
8169 getAttachmentPieceForAttachment(attachment) {
8170 for (const piece of this.getAttachmentPieces()) {
8171 if (piece.attachment === attachment) {
8172 return piece;
8173 }
8174 }
8175 }
8176 findRangesForBlockAttribute(attributeName) {
8177 let position = 0;
8178 const ranges = [];
8179 this.getBlocks().forEach(block => {
8180 const length = block.getLength();
8181 if (block.hasAttribute(attributeName)) {
8182 ranges.push([position, position + length]);
8183 }
8184 position += length;
8185 });
8186 return ranges;
8187 }
8188 findRangesForTextAttribute(attributeName) {
8189 let {
8190 withValue
8191 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
8192 let position = 0;
8193 let range = [];
8194 const ranges = [];
8195 const match = function (piece) {
8196 if (withValue) {
8197 return piece.getAttribute(attributeName) === withValue;
8198 } else {
8199 return piece.hasAttribute(attributeName);
8200 }
8201 };
8202 this.getPieces().forEach(piece => {
8203 const length = piece.getLength();
8204 if (match(piece)) {
8205 if (range[1] === position) {
8206 range[1] = position + length;
8207 } else {
8208 ranges.push(range = [position, position + length]);
8209 }
8210 }
8211 position += length;
8212 });
8213 return ranges;
8214 }
8215 locationFromPosition(position) {
8216 const location = this.blockList.findIndexAndOffsetAtPosition(Math.max(0, position));
8217 if (location.index != null) {
8218 return location;
8219 } else {
8220 const blocks = this.getBlocks();
8221 return {
8222 index: blocks.length - 1,
8223 offset: blocks[blocks.length - 1].getLength()
8224 };
8225 }
8226 }
8227 positionFromLocation(location) {
8228 return this.blockList.findPositionAtIndexAndOffset(location.index, location.offset);
8229 }
8230 locationRangeFromPosition(position) {
8231 return normalizeRange(this.locationFromPosition(position));
8232 }
8233 locationRangeFromRange(range) {
8234 range = normalizeRange(range);
8235 if (!range) return;
8236 const [startPosition, endPosition] = Array.from(range);
8237 const startLocation = this.locationFromPosition(startPosition);
8238 const endLocation = this.locationFromPosition(endPosition);
8239 return normalizeRange([startLocation, endLocation]);
8240 }
8241 rangeFromLocationRange(locationRange) {
8242 let rightPosition;
8243 locationRange = normalizeRange(locationRange);
8244 const leftPosition = this.positionFromLocation(locationRange[0]);
8245 if (!rangeIsCollapsed(locationRange)) {
8246 rightPosition = this.positionFromLocation(locationRange[1]);
8247 }
8248 return normalizeRange([leftPosition, rightPosition]);
8249 }
8250 isEqualTo(document) {
8251 return this.blockList.isEqualTo(document === null || document === void 0 ? void 0 : document.blockList);
8252 }
8253 getTexts() {
8254 return this.getBlocks().map(block => block.text);
8255 }
8256 getPieces() {
8257 const pieces = [];
8258 Array.from(this.getTexts()).forEach(text => {
8259 pieces.push(...Array.from(text.getPieces() || []));
8260 });
8261 return pieces;
8262 }
8263 getObjects() {
8264 return this.getBlocks().concat(this.getTexts()).concat(this.getPieces());
8265 }
8266 toSerializableDocument() {
8267 const blocks = [];
8268 this.blockList.eachObject(block => blocks.push(block.copyWithText(block.text.toSerializableText())));
8269 return new this.constructor(blocks);
8270 }
8271 toString() {
8272 return this.blockList.toString();
8273 }
8274 toJSON() {
8275 return this.blockList.toJSON();
8276 }
8277 toConsole() {
8278 return JSON.stringify(this.blockList.toArray().map(block => JSON.parse(block.text.toConsole())));
8279 }
8280 }
8281 const attributesForBlock = function (block) {
8282 const attributes = {};
8283 const attributeName = block.getLastAttribute();
8284 if (attributeName) {
8285 attributes[attributeName] = true;
8286 }
8287 return attributes;
8288 };
8289
8290 /* eslint-disable
8291 no-case-declarations,
8292 no-irregular-whitespace,
8293 */
8294 const pieceForString = function (string) {
8295 let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
8296 const type = "string";
8297 string = normalizeSpaces(string);
8298 return {
8299 string,
8300 attributes,
8301 type
8302 };
8303 };
8304 const pieceForAttachment = function (attachment) {
8305 let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
8306 const type = "attachment";
8307 return {
8308 attachment,
8309 attributes,
8310 type
8311 };
8312 };
8313 const blockForAttributes = function () {
8314 let attributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
8315 let htmlAttributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
8316 const text = [];
8317 return {
8318 text,
8319 attributes,
8320 htmlAttributes
8321 };
8322 };
8323 const parseTrixDataAttribute = (element, name) => {
8324 try {
8325 return JSON.parse(element.getAttribute("data-trix-".concat(name)));
8326 } catch (error) {
8327 return {};
8328 }
8329 };
8330 const getImageDimensions = element => {
8331 const width = element.getAttribute("width");
8332 const height = element.getAttribute("height");
8333 const dimensions = {};
8334 if (width) {
8335 dimensions.width = parseInt(width, 10);
8336 }
8337 if (height) {
8338 dimensions.height = parseInt(height, 10);
8339 }
8340 return dimensions;
8341 };
8342 class HTMLParser extends BasicObject {
8343 static parse(html, options) {
8344 const parser = new this(html, options);
8345 parser.parse();
8346 return parser;
8347 }
8348 constructor(html) {
8349 let {
8350 referenceElement
8351 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
8352 super(...arguments);
8353 this.html = html;
8354 this.referenceElement = referenceElement;
8355 this.blocks = [];
8356 this.blockElements = [];
8357 this.processedElements = [];
8358 }
8359 getDocument() {
8360 return Document.fromJSON(this.blocks);
8361 }
8362
8363 // HTML parsing
8364
8365 parse() {
8366 try {
8367 this.createHiddenContainer();
8368 HTMLSanitizer.setHTML(this.containerElement, this.html);
8369 const walker = walkTree(this.containerElement, {
8370 usingFilter: nodeFilter
8371 });
8372 while (walker.nextNode()) {
8373 this.processNode(walker.currentNode);
8374 }
8375 return this.translateBlockElementMarginsToNewlines();
8376 } finally {
8377 this.removeHiddenContainer();
8378 }
8379 }
8380 createHiddenContainer() {
8381 if (this.referenceElement) {
8382 this.containerElement = this.referenceElement.cloneNode(false);
8383 this.containerElement.removeAttribute("id");
8384 this.containerElement.setAttribute("data-trix-internal", "");
8385 this.containerElement.style.display = "none";
8386 return this.referenceElement.parentNode.insertBefore(this.containerElement, this.referenceElement.nextSibling);
8387 } else {
8388 this.containerElement = makeElement({
8389 tagName: "div",
8390 style: {
8391 display: "none"
8392 }
8393 });
8394 return document.body.appendChild(this.containerElement);
8395 }
8396 }
8397 removeHiddenContainer() {
8398 return removeNode(this.containerElement);
8399 }
8400 processNode(node) {
8401 switch (node.nodeType) {
8402 case Node.TEXT_NODE:
8403 if (!this.isInsignificantTextNode(node)) {
8404 this.appendBlockForTextNode(node);
8405 return this.processTextNode(node);
8406 }
8407 break;
8408 case Node.ELEMENT_NODE:
8409 this.appendBlockForElement(node);
8410 return this.processElement(node);
8411 }
8412 }
8413 appendBlockForTextNode(node) {
8414 const element = node.parentNode;
8415 if (element === this.currentBlockElement && this.isBlockElement(node.previousSibling)) {
8416 return this.appendStringWithAttributes("\n");
8417 } else if (element === this.containerElement || this.isBlockElement(element)) {
8418 var _this$currentBlock;
8419 const attributes = this.getBlockAttributes(element);
8420 const htmlAttributes = this.getBlockHTMLAttributes(element);
8421 if (!arraysAreEqual(attributes, (_this$currentBlock = this.currentBlock) === null || _this$currentBlock === void 0 ? void 0 : _this$currentBlock.attributes)) {
8422 this.currentBlock = this.appendBlockForAttributesWithElement(attributes, element, htmlAttributes);
8423 this.currentBlockElement = element;
8424 }
8425 }
8426 }
8427 appendBlockForElement(element) {
8428 const elementIsBlockElement = this.isBlockElement(element);
8429 const currentBlockContainsElement = elementContainsNode(this.currentBlockElement, element);
8430 if (elementIsBlockElement && !this.isBlockElement(element.firstChild)) {
8431 if (!this.isInsignificantTextNode(element.firstChild) || !this.isBlockElement(element.firstElementChild)) {
8432 const attributes = this.getBlockAttributes(element);
8433 const htmlAttributes = this.getBlockHTMLAttributes(element);
8434 if (element.firstChild) {
8435 if (!(currentBlockContainsElement && arraysAreEqual(attributes, this.currentBlock.attributes))) {
8436 this.currentBlock = this.appendBlockForAttributesWithElement(attributes, element, htmlAttributes);
8437 this.currentBlockElement = element;
8438 } else {
8439 return this.appendStringWithAttributes("\n");
8440 }
8441 }
8442 }
8443 } else if (this.currentBlockElement && !currentBlockContainsElement && !elementIsBlockElement) {
8444 const parentBlockElement = this.findParentBlockElement(element);
8445 if (parentBlockElement) {
8446 return this.appendBlockForElement(parentBlockElement);
8447 } else {
8448 this.currentBlock = this.appendEmptyBlock();
8449 this.currentBlockElement = null;
8450 }
8451 }
8452 }
8453 findParentBlockElement(element) {
8454 let {
8455 parentElement
8456 } = element;
8457 while (parentElement && parentElement !== this.containerElement) {
8458 if (this.isBlockElement(parentElement) && this.blockElements.includes(parentElement)) {
8459 return parentElement;
8460 } else {
8461 parentElement = parentElement.parentElement;
8462 }
8463 }
8464 return null;
8465 }
8466 processTextNode(node) {
8467 let string = node.data;
8468 if (!elementCanDisplayPreformattedText(node.parentNode)) {
8469 var _node$previousSibling;
8470 string = squishBreakableWhitespace(string);
8471 if (stringEndsWithWhitespace((_node$previousSibling = node.previousSibling) === null || _node$previousSibling === void 0 ? void 0 : _node$previousSibling.textContent)) {
8472 string = leftTrimBreakableWhitespace(string);
8473 }
8474 }
8475 return this.appendStringWithAttributes(string, this.getTextAttributes(node.parentNode));
8476 }
8477 processElement(element) {
8478 let attributes;
8479 if (nodeIsAttachmentElement(element)) {
8480 attributes = parseTrixDataAttribute(element, "attachment");
8481 if (Object.keys(attributes).length) {
8482 const textAttributes = this.getTextAttributes(element);
8483 this.appendAttachmentWithAttributes(attributes, textAttributes);
8484 // We have everything we need so avoid processing inner nodes
8485 element.innerHTML = "";
8486 }
8487 return this.processedElements.push(element);
8488 } else {
8489 switch (tagName(element)) {
8490 case "br":
8491 if (!this.isExtraBR(element) && !this.isBlockElement(element.nextSibling)) {
8492 this.appendStringWithAttributes("\n", this.getTextAttributes(element));
8493 }
8494 return this.processedElements.push(element);
8495 case "img":
8496 attributes = {
8497 url: element.getAttribute("src"),
8498 contentType: "image"
8499 };
8500 const object = getImageDimensions(element);
8501 for (const key in object) {
8502 const value = object[key];
8503 attributes[key] = value;
8504 }
8505 this.appendAttachmentWithAttributes(attributes, this.getTextAttributes(element));
8506 return this.processedElements.push(element);
8507 case "tr":
8508 if (this.needsTableSeparator(element)) {
8509 return this.appendStringWithAttributes(parser.tableRowSeparator);
8510 }
8511 break;
8512 case "td":
8513 if (this.needsTableSeparator(element)) {
8514 return this.appendStringWithAttributes(parser.tableCellSeparator);
8515 }
8516 break;
8517 }
8518 }
8519 }
8520
8521 // Document construction
8522
8523 appendBlockForAttributesWithElement(attributes, element) {
8524 let htmlAttributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
8525 this.blockElements.push(element);
8526 const block = blockForAttributes(attributes, htmlAttributes);
8527 this.blocks.push(block);
8528 return block;
8529 }
8530 appendEmptyBlock() {
8531 return this.appendBlockForAttributesWithElement([], null);
8532 }
8533 appendStringWithAttributes(string, attributes) {
8534 return this.appendPiece(pieceForString(string, attributes));
8535 }
8536 appendAttachmentWithAttributes(attachment, attributes) {
8537 return this.appendPiece(pieceForAttachment(attachment, attributes));
8538 }
8539 appendPiece(piece) {
8540 if (this.blocks.length === 0) {
8541 this.appendEmptyBlock();
8542 }
8543 return this.blocks[this.blocks.length - 1].text.push(piece);
8544 }
8545 appendStringToTextAtIndex(string, index) {
8546 const {
8547 text
8548 } = this.blocks[index];
8549 const piece = text[text.length - 1];
8550 if ((piece === null || piece === void 0 ? void 0 : piece.type) === "string") {
8551 piece.string += string;
8552 } else {
8553 return text.push(pieceForString(string));
8554 }
8555 }
8556 prependStringToTextAtIndex(string, index) {
8557 const {
8558 text
8559 } = this.blocks[index];
8560 const piece = text[0];
8561 if ((piece === null || piece === void 0 ? void 0 : piece.type) === "string") {
8562 piece.string = string + piece.string;
8563 } else {
8564 return text.unshift(pieceForString(string));
8565 }
8566 }
8567
8568 // Attribute parsing
8569
8570 getTextAttributes(element) {
8571 let value;
8572 const attributes = {};
8573 for (const attribute in text_attributes) {
8574 const configAttr = text_attributes[attribute];
8575 if (configAttr.tagName && findClosestElementFromNode(element, {
8576 matchingSelector: configAttr.tagName,
8577 untilNode: this.containerElement
8578 })) {
8579 attributes[attribute] = true;
8580 } else if (configAttr.parser) {
8581 value = configAttr.parser(element);
8582 if (value) {
8583 let attributeInheritedFromBlock = false;
8584 for (const blockElement of this.findBlockElementAncestors(element)) {
8585 if (configAttr.parser(blockElement) === value) {
8586 attributeInheritedFromBlock = true;
8587 break;
8588 }
8589 }
8590 if (!attributeInheritedFromBlock) {
8591 attributes[attribute] = value;
8592 }
8593 }
8594 } else if (configAttr.styleProperty) {
8595 value = element.style[configAttr.styleProperty];
8596 if (value) {
8597 attributes[attribute] = value;
8598 }
8599 }
8600 }
8601 if (nodeIsAttachmentElement(element)) {
8602 const object = parseTrixDataAttribute(element, "attributes");
8603 for (const key in object) {
8604 value = object[key];
8605 attributes[key] = value;
8606 }
8607 }
8608 return attributes;
8609 }
8610 getBlockAttributes(element) {
8611 const attributes$1 = [];
8612 while (element && element !== this.containerElement) {
8613 for (const attribute in attributes) {
8614 const attrConfig = attributes[attribute];
8615 if (attrConfig.parse !== false) {
8616 if (tagName(element) === attrConfig.tagName) {
8617 var _attrConfig$test;
8618 if ((_attrConfig$test = attrConfig.test) !== null && _attrConfig$test !== void 0 && _attrConfig$test.call(attrConfig, element) || !attrConfig.test) {
8619 attributes$1.push(attribute);
8620 if (attrConfig.listAttribute) {
8621 attributes$1.push(attrConfig.listAttribute);
8622 }
8623 }
8624 }
8625 }
8626 }
8627 element = element.parentNode;
8628 }
8629 return attributes$1.reverse();
8630 }
8631 getBlockHTMLAttributes(element) {
8632 const attributes$1 = {};
8633 const blockConfig = Object.values(attributes).find(settings => settings.tagName === tagName(element));
8634 const allowedAttributes = (blockConfig === null || blockConfig === void 0 ? void 0 : blockConfig.htmlAttributes) || [];
8635 allowedAttributes.forEach(attribute => {
8636 if (element.hasAttribute(attribute)) {
8637 attributes$1[attribute] = element.getAttribute(attribute);
8638 }
8639 });
8640 return attributes$1;
8641 }
8642 findBlockElementAncestors(element) {
8643 const ancestors = [];
8644 while (element && element !== this.containerElement) {
8645 const tag = tagName(element);
8646 if (getBlockTagNames().includes(tag)) {
8647 ancestors.push(element);
8648 }
8649 element = element.parentNode;
8650 }
8651 return ancestors;
8652 }
8653
8654 // Element inspection
8655
8656 isBlockElement(element) {
8657 if ((element === null || element === void 0 ? void 0 : element.nodeType) !== Node.ELEMENT_NODE) return;
8658 if (nodeIsAttachmentElement(element)) return;
8659 if (findClosestElementFromNode(element, {
8660 matchingSelector: "td",
8661 untilNode: this.containerElement
8662 })) return;
8663 return getBlockTagNames().includes(tagName(element)) || window.getComputedStyle(element).display === "block";
8664 }
8665 isInsignificantTextNode(node) {
8666 if ((node === null || node === void 0 ? void 0 : node.nodeType) !== Node.TEXT_NODE) return;
8667 if (!stringIsAllBreakableWhitespace(node.data)) return;
8668 const {
8669 parentNode,
8670 previousSibling,
8671 nextSibling
8672 } = node;
8673 if (nodeEndsWithNonWhitespace(parentNode.previousSibling) && !this.isBlockElement(parentNode.previousSibling)) return;
8674 if (elementCanDisplayPreformattedText(parentNode)) return;
8675 return !previousSibling || this.isBlockElement(previousSibling) || !nextSibling || this.isBlockElement(nextSibling);
8676 }
8677 isExtraBR(element) {
8678 return tagName(element) === "br" && this.isBlockElement(element.parentNode) && element.parentNode.lastChild === element;
8679 }
8680 needsTableSeparator(element) {
8681 if (parser.removeBlankTableCells) {
8682 var _element$previousSibl;
8683 const content = (_element$previousSibl = element.previousSibling) === null || _element$previousSibl === void 0 ? void 0 : _element$previousSibl.textContent;
8684 return content && /\S/.test(content);
8685 } else {
8686 return element.previousSibling;
8687 }
8688 }
8689
8690 // Margin translation
8691
8692 translateBlockElementMarginsToNewlines() {
8693 const defaultMargin = this.getMarginOfDefaultBlockElement();
8694 for (let index = 0; index < this.blocks.length; index++) {
8695 const margin = this.getMarginOfBlockElementAtIndex(index);
8696 if (margin) {
8697 if (margin.top > defaultMargin.top * 2) {
8698 this.prependStringToTextAtIndex("\n", index);
8699 }
8700 if (margin.bottom > defaultMargin.bottom * 2) {
8701 this.appendStringToTextAtIndex("\n", index);
8702 }
8703 }
8704 }
8705 }
8706 getMarginOfBlockElementAtIndex(index) {
8707 const element = this.blockElements[index];
8708 if (element) {
8709 if (element.textContent) {
8710 if (!getBlockTagNames().includes(tagName(element)) && !this.processedElements.includes(element)) {
8711 return getBlockElementMargin(element);
8712 }
8713 }
8714 }
8715 }
8716 getMarginOfDefaultBlockElement() {
8717 const element = makeElement(attributes.default.tagName);
8718 this.containerElement.appendChild(element);
8719 return getBlockElementMargin(element);
8720 }
8721 }
8722
8723 // Helpers
8724
8725 const elementCanDisplayPreformattedText = function (element) {
8726 const {
8727 whiteSpace
8728 } = window.getComputedStyle(element);
8729 return ["pre", "pre-wrap", "pre-line"].includes(whiteSpace);
8730 };
8731 const nodeEndsWithNonWhitespace = node => node && !stringEndsWithWhitespace(node.textContent);
8732 const getBlockElementMargin = function (element) {
8733 const style = window.getComputedStyle(element);
8734 if (style.display === "block") {
8735 return {
8736 top: parseInt(style.marginTop),
8737 bottom: parseInt(style.marginBottom)
8738 };
8739 }
8740 };
8741 const nodeFilter = function (node) {
8742 if (tagName(node) === "style") {
8743 return NodeFilter.FILTER_REJECT;
8744 } else {
8745 return NodeFilter.FILTER_ACCEPT;
8746 }
8747 };
8748
8749 // Whitespace
8750
8751 const leftTrimBreakableWhitespace = string => string.replace(new RegExp("^".concat(breakableWhitespacePattern.source, "+")), "");
8752 const stringIsAllBreakableWhitespace = string => new RegExp("^".concat(breakableWhitespacePattern.source, "*$")).test(string);
8753 const stringEndsWithWhitespace = string => /\s$/.test(string);
8754
8755 /* eslint-disable
8756 no-empty,
8757 */
8758 const unserializableElementSelector = "[data-trix-serialize=false]";
8759 const unserializableAttributeNames = ["contenteditable", "data-trix-id", "data-trix-store-key", "data-trix-mutable", "data-trix-placeholder", "tabindex"];
8760 const serializedAttributesAttribute = "data-trix-serialized-attributes";
8761 const serializedAttributesSelector = "[".concat(serializedAttributesAttribute, "]");
8762 const blockCommentPattern = new RegExp("<!--block-->", "g");
8763 const serializers = {
8764 "application/json": function (serializable) {
8765 let document;
8766 if (serializable instanceof Document) {
8767 document = serializable;
8768 } else if (serializable instanceof HTMLElement) {
8769 document = HTMLParser.parse(serializable.innerHTML).getDocument();
8770 } else {
8771 throw new Error("unserializable object");
8772 }
8773 return document.toSerializableDocument().toJSONString();
8774 },
8775 "text/html": function (serializable) {
8776 let element;
8777 if (serializable instanceof Document) {
8778 element = DocumentView.render(serializable);
8779 } else if (serializable instanceof HTMLElement) {
8780 element = serializable.cloneNode(true);
8781 } else {
8782 throw new Error("unserializable object");
8783 }
8784
8785 // Remove unserializable elements
8786 Array.from(element.querySelectorAll(unserializableElementSelector)).forEach(el => {
8787 removeNode(el);
8788 });
8789
8790 // Remove unserializable attributes
8791 unserializableAttributeNames.forEach(attribute => {
8792 Array.from(element.querySelectorAll("[".concat(attribute, "]"))).forEach(el => {
8793 el.removeAttribute(attribute);
8794 });
8795 });
8796
8797 // Rewrite elements with serialized attribute overrides
8798 Array.from(element.querySelectorAll(serializedAttributesSelector)).forEach(el => {
8799 try {
8800 const attributes = JSON.parse(el.getAttribute(serializedAttributesAttribute));
8801 el.removeAttribute(serializedAttributesAttribute);
8802 for (const name in attributes) {
8803 const value = attributes[name];
8804 el.setAttribute(name, value);
8805 }
8806 } catch (error) {}
8807 });
8808 return element.innerHTML.replace(blockCommentPattern, "");
8809 }
8810 };
8811 const deserializers = {
8812 "application/json": function (string) {
8813 return Document.fromJSONString(string);
8814 },
8815 "text/html": function (string) {
8816 return HTMLParser.parse(string).getDocument();
8817 }
8818 };
8819 const serializeToContentType = function (serializable, contentType) {
8820 const serializer = serializers[contentType];
8821 if (serializer) {
8822 return serializer(serializable);
8823 } else {
8824 throw new Error("unknown content type: ".concat(contentType));
8825 }
8826 };
8827 const deserializeFromContentType = function (string, contentType) {
8828 const deserializer = deserializers[contentType];
8829 if (deserializer) {
8830 return deserializer(string);
8831 } else {
8832 throw new Error("unknown content type: ".concat(contentType));
8833 }
8834 };
8835
8836 var core = /*#__PURE__*/Object.freeze({
8837 __proto__: null
8838 });
8839
8840 class ManagedAttachment extends BasicObject {
8841 constructor(attachmentManager, attachment) {
8842 super(...arguments);
8843 this.attachmentManager = attachmentManager;
8844 this.attachment = attachment;
8845 this.id = this.attachment.id;
8846 this.file = this.attachment.file;
8847 }
8848 remove() {
8849 return this.attachmentManager.requestRemovalOfAttachment(this.attachment);
8850 }
8851 }
8852 ManagedAttachment.proxyMethod("attachment.getAttribute");
8853 ManagedAttachment.proxyMethod("attachment.hasAttribute");
8854 ManagedAttachment.proxyMethod("attachment.setAttribute");
8855 ManagedAttachment.proxyMethod("attachment.getAttributes");
8856 ManagedAttachment.proxyMethod("attachment.setAttributes");
8857 ManagedAttachment.proxyMethod("attachment.isPending");
8858 ManagedAttachment.proxyMethod("attachment.isPreviewable");
8859 ManagedAttachment.proxyMethod("attachment.getURL");
8860 ManagedAttachment.proxyMethod("attachment.getHref");
8861 ManagedAttachment.proxyMethod("attachment.getFilename");
8862 ManagedAttachment.proxyMethod("attachment.getFilesize");
8863 ManagedAttachment.proxyMethod("attachment.getFormattedFilesize");
8864 ManagedAttachment.proxyMethod("attachment.getExtension");
8865 ManagedAttachment.proxyMethod("attachment.getContentType");
8866 ManagedAttachment.proxyMethod("attachment.getFile");
8867 ManagedAttachment.proxyMethod("attachment.setFile");
8868 ManagedAttachment.proxyMethod("attachment.releaseFile");
8869 ManagedAttachment.proxyMethod("attachment.getUploadProgress");
8870 ManagedAttachment.proxyMethod("attachment.setUploadProgress");
8871
8872 class AttachmentManager extends BasicObject {
8873 constructor() {
8874 let attachments = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
8875 super(...arguments);
8876 this.managedAttachments = {};
8877 Array.from(attachments).forEach(attachment => {
8878 this.manageAttachment(attachment);
8879 });
8880 }
8881 getAttachments() {
8882 const result = [];
8883 for (const id in this.managedAttachments) {
8884 const attachment = this.managedAttachments[id];
8885 result.push(attachment);
8886 }
8887 return result;
8888 }
8889 manageAttachment(attachment) {
8890 if (!this.managedAttachments[attachment.id]) {
8891 this.managedAttachments[attachment.id] = new ManagedAttachment(this, attachment);
8892 }
8893 return this.managedAttachments[attachment.id];
8894 }
8895 attachmentIsManaged(attachment) {
8896 return attachment.id in this.managedAttachments;
8897 }
8898 requestRemovalOfAttachment(attachment) {
8899 if (this.attachmentIsManaged(attachment)) {
8900 var _this$delegate, _this$delegate$attach;
8901 return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$attach = _this$delegate.attachmentManagerDidRequestRemovalOfAttachment) === null || _this$delegate$attach === void 0 ? void 0 : _this$delegate$attach.call(_this$delegate, attachment);
8902 }
8903 }
8904 unmanageAttachment(attachment) {
8905 const managedAttachment = this.managedAttachments[attachment.id];
8906 delete this.managedAttachments[attachment.id];
8907 return managedAttachment;
8908 }
8909 }
8910
8911 class LineBreakInsertion {
8912 constructor(composition) {
8913 this.composition = composition;
8914 this.document = this.composition.document;
8915 const selectedRange = this.composition.getSelectedRange();
8916 this.startPosition = selectedRange[0];
8917 this.endPosition = selectedRange[1];
8918 this.startLocation = this.document.locationFromPosition(this.startPosition);
8919 this.endLocation = this.document.locationFromPosition(this.endPosition);
8920 this.block = this.document.getBlockAtIndex(this.endLocation.index);
8921 this.breaksOnReturn = this.block.breaksOnReturn();
8922 this.previousCharacter = this.block.text.getStringAtPosition(this.endLocation.offset - 1);
8923 this.nextCharacter = this.block.text.getStringAtPosition(this.endLocation.offset);
8924 }
8925 shouldInsertBlockBreak() {
8926 if (this.block.hasAttributes() && this.block.isListItem() && !this.block.isEmpty()) {
8927 return this.startLocation.offset !== 0;
8928 } else {
8929 return this.breaksOnReturn && this.nextCharacter !== "\n";
8930 }
8931 }
8932 shouldBreakFormattedBlock() {
8933 return this.block.hasAttributes() && !this.block.isListItem() && (this.breaksOnReturn && this.nextCharacter === "\n" || this.previousCharacter === "\n");
8934 }
8935 shouldDecreaseListLevel() {
8936 return this.block.hasAttributes() && this.block.isListItem() && this.block.isEmpty();
8937 }
8938 shouldPrependListItem() {
8939 return this.block.isListItem() && this.startLocation.offset === 0 && !this.block.isEmpty();
8940 }
8941 shouldRemoveLastBlockAttribute() {
8942 return this.block.hasAttributes() && !this.block.isListItem() && this.block.isEmpty();
8943 }
8944 }
8945
8946 const PLACEHOLDER = " ";
8947 class Composition extends BasicObject {
8948 constructor() {
8949 super(...arguments);
8950 this.document = new Document();
8951 this.attachments = [];
8952 this.currentAttributes = {};
8953 this.revision = 0;
8954 }
8955 setDocument(document) {
8956 if (!document.isEqualTo(this.document)) {
8957 var _this$delegate, _this$delegate$compos;
8958 this.document = document;
8959 this.refreshAttachments();
8960 this.revision++;
8961 return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$compos = _this$delegate.compositionDidChangeDocument) === null || _this$delegate$compos === void 0 ? void 0 : _this$delegate$compos.call(_this$delegate, document);
8962 }
8963 }
8964
8965 // Snapshots
8966
8967 getSnapshot() {
8968 return {
8969 document: this.document,
8970 selectedRange: this.getSelectedRange()
8971 };
8972 }
8973 loadSnapshot(_ref) {
8974 var _this$delegate2, _this$delegate2$compo, _this$delegate3, _this$delegate3$compo;
8975 let {
8976 document,
8977 selectedRange
8978 } = _ref;
8979 (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || (_this$delegate2$compo = _this$delegate2.compositionWillLoadSnapshot) === null || _this$delegate2$compo === void 0 || _this$delegate2$compo.call(_this$delegate2);
8980 this.setDocument(document != null ? document : new Document());
8981 this.setSelection(selectedRange != null ? selectedRange : [0, 0]);
8982 return (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 || (_this$delegate3$compo = _this$delegate3.compositionDidLoadSnapshot) === null || _this$delegate3$compo === void 0 ? void 0 : _this$delegate3$compo.call(_this$delegate3);
8983 }
8984
8985 // Responder protocol
8986
8987 insertText(text) {
8988 let {
8989 updatePosition
8990 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
8991 updatePosition: true
8992 };
8993 const selectedRange = this.getSelectedRange();
8994 this.setDocument(this.document.insertTextAtRange(text, selectedRange));
8995 const startPosition = selectedRange[0];
8996 const endPosition = startPosition + text.getLength();
8997 if (updatePosition) {
8998 this.setSelection(endPosition);
8999 }
9000 return this.notifyDelegateOfInsertionAtRange([startPosition, endPosition]);
9001 }
9002 insertBlock() {
9003 let block = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Block();
9004 const document = new Document([block]);
9005 return this.insertDocument(document);
9006 }
9007 insertDocument() {
9008 let document = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Document();
9009 const selectedRange = this.getSelectedRange();
9010 this.setDocument(this.document.insertDocumentAtRange(document, selectedRange));
9011 const startPosition = selectedRange[0];
9012 const endPosition = startPosition + document.getLength();
9013 this.setSelection(endPosition);
9014 return this.notifyDelegateOfInsertionAtRange([startPosition, endPosition]);
9015 }
9016 insertString(string, options) {
9017 const attributes = this.getCurrentTextAttributes();
9018 const text = Text.textForStringWithAttributes(string, attributes);
9019 return this.insertText(text, options);
9020 }
9021 insertBlockBreak() {
9022 const selectedRange = this.getSelectedRange();
9023 this.setDocument(this.document.insertBlockBreakAtRange(selectedRange));
9024 const startPosition = selectedRange[0];
9025 const endPosition = startPosition + 1;
9026 this.setSelection(endPosition);
9027 return this.notifyDelegateOfInsertionAtRange([startPosition, endPosition]);
9028 }
9029 insertLineBreak() {
9030 const insertion = new LineBreakInsertion(this);
9031 if (insertion.shouldDecreaseListLevel()) {
9032 this.decreaseListLevel();
9033 return this.setSelection(insertion.startPosition);
9034 } else if (insertion.shouldPrependListItem()) {
9035 const document = new Document([insertion.block.copyWithoutText()]);
9036 return this.insertDocument(document);
9037 } else if (insertion.shouldInsertBlockBreak()) {
9038 return this.insertBlockBreak();
9039 } else if (insertion.shouldRemoveLastBlockAttribute()) {
9040 return this.removeLastBlockAttribute();
9041 } else if (insertion.shouldBreakFormattedBlock()) {
9042 return this.breakFormattedBlock(insertion);
9043 } else {
9044 return this.insertString("\n");
9045 }
9046 }
9047 insertHTML(html) {
9048 const document = HTMLParser.parse(html).getDocument();
9049 const selectedRange = this.getSelectedRange();
9050 this.setDocument(this.document.mergeDocumentAtRange(document, selectedRange));
9051 const startPosition = selectedRange[0];
9052 const endPosition = startPosition + document.getLength() - 1;
9053 this.setSelection(endPosition);
9054 return this.notifyDelegateOfInsertionAtRange([startPosition, endPosition]);
9055 }
9056 replaceHTML(html) {
9057 const document = HTMLParser.parse(html).getDocument().copyUsingObjectsFromDocument(this.document);
9058 const locationRange = this.getLocationRange({
9059 strict: false
9060 });
9061 const selectedRange = this.document.rangeFromLocationRange(locationRange);
9062 this.setDocument(document);
9063 return this.setSelection(selectedRange);
9064 }
9065 insertFile(file) {
9066 return this.insertFiles([file]);
9067 }
9068 insertFiles(files) {
9069 const attachments = [];
9070 Array.from(files).forEach(file => {
9071 var _this$delegate4;
9072 if ((_this$delegate4 = this.delegate) !== null && _this$delegate4 !== void 0 && _this$delegate4.compositionShouldAcceptFile(file)) {
9073 const attachment = Attachment.attachmentForFile(file);
9074 attachments.push(attachment);
9075 }
9076 });
9077 return this.insertAttachments(attachments);
9078 }
9079 insertAttachment(attachment) {
9080 return this.insertAttachments([attachment]);
9081 }
9082 insertAttachments(attachments$1) {
9083 let text = new Text();
9084 Array.from(attachments$1).forEach(attachment => {
9085 var _config$attachments$t;
9086 const type = attachment.getType();
9087 const presentation = (_config$attachments$t = attachments[type]) === null || _config$attachments$t === void 0 ? void 0 : _config$attachments$t.presentation;
9088 const attributes = this.getCurrentTextAttributes();
9089 if (presentation) {
9090 attributes.presentation = presentation;
9091 }
9092 const attachmentText = Text.textForAttachmentWithAttributes(attachment, attributes);
9093 text = text.appendText(attachmentText);
9094 });
9095 return this.insertText(text);
9096 }
9097 shouldManageDeletingInDirection(direction) {
9098 const locationRange = this.getLocationRange();
9099 if (rangeIsCollapsed(locationRange)) {
9100 if (direction === "backward" && locationRange[0].offset === 0) {
9101 return true;
9102 }
9103 if (this.shouldManageMovingCursorInDirection(direction)) {
9104 return true;
9105 }
9106 } else {
9107 if (locationRange[0].index !== locationRange[1].index) {
9108 return true;
9109 }
9110 }
9111 return false;
9112 }
9113 deleteInDirection(direction) {
9114 let {
9115 length
9116 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
9117 let attachment, deletingIntoPreviousBlock, selectionSpansBlocks;
9118 const locationRange = this.getLocationRange();
9119 let range = this.getSelectedRange();
9120 const selectionIsCollapsed = rangeIsCollapsed(range);
9121 if (selectionIsCollapsed) {
9122 deletingIntoPreviousBlock = direction === "backward" && locationRange[0].offset === 0;
9123 } else {
9124 selectionSpansBlocks = locationRange[0].index !== locationRange[1].index;
9125 }
9126 if (deletingIntoPreviousBlock) {
9127 if (this.canDecreaseBlockAttributeLevel()) {
9128 const block = this.getBlock();
9129 if (block.isListItem()) {
9130 this.decreaseListLevel();
9131 } else {
9132 this.decreaseBlockAttributeLevel();
9133 }
9134 this.setSelection(range[0]);
9135 if (block.isEmpty()) {
9136 return false;
9137 }
9138 }
9139 }
9140 if (selectionIsCollapsed) {
9141 range = this.getExpandedRangeInDirection(direction, {
9142 length
9143 });
9144 if (direction === "backward") {
9145 attachment = this.getAttachmentAtRange(range);
9146 }
9147 }
9148 if (attachment) {
9149 this.editAttachment(attachment);
9150 return false;
9151 } else {
9152 this.setDocument(this.document.removeTextAtRange(range));
9153 this.setSelection(range[0]);
9154 if (deletingIntoPreviousBlock || selectionSpansBlocks) {
9155 return false;
9156 }
9157 }
9158 }
9159 moveTextFromRange(range) {
9160 const [position] = Array.from(this.getSelectedRange());
9161 this.setDocument(this.document.moveTextFromRangeToPosition(range, position));
9162 return this.setSelection(position);
9163 }
9164 removeAttachment(attachment) {
9165 const range = this.document.getRangeOfAttachment(attachment);
9166 if (range) {
9167 this.stopEditingAttachment();
9168 this.setDocument(this.document.removeTextAtRange(range));
9169 return this.setSelection(range[0]);
9170 }
9171 }
9172 removeLastBlockAttribute() {
9173 const [startPosition, endPosition] = Array.from(this.getSelectedRange());
9174 const block = this.document.getBlockAtPosition(endPosition);
9175 this.removeCurrentAttribute(block.getLastAttribute());
9176 return this.setSelection(startPosition);
9177 }
9178 insertPlaceholder() {
9179 this.placeholderPosition = this.getPosition();
9180 return this.insertString(PLACEHOLDER);
9181 }
9182 selectPlaceholder() {
9183 if (this.placeholderPosition != null) {
9184 this.setSelectedRange([this.placeholderPosition, this.placeholderPosition + PLACEHOLDER.length]);
9185 return this.getSelectedRange();
9186 }
9187 }
9188 forgetPlaceholder() {
9189 this.placeholderPosition = null;
9190 }
9191
9192 // Current attributes
9193
9194 hasCurrentAttribute(attributeName) {
9195 const value = this.currentAttributes[attributeName];
9196 return value != null && value !== false;
9197 }
9198 toggleCurrentAttribute(attributeName) {
9199 const value = !this.currentAttributes[attributeName];
9200 if (value) {
9201 return this.setCurrentAttribute(attributeName, value);
9202 } else {
9203 return this.removeCurrentAttribute(attributeName);
9204 }
9205 }
9206 canSetCurrentAttribute(attributeName) {
9207 if (getBlockConfig(attributeName)) {
9208 return this.canSetCurrentBlockAttribute(attributeName);
9209 } else {
9210 return this.canSetCurrentTextAttribute(attributeName);
9211 }
9212 }
9213 canSetCurrentTextAttribute(attributeName) {
9214 const document = this.getSelectedDocument();
9215 if (!document) return;
9216 for (const attachment of Array.from(document.getAttachments())) {
9217 if (!attachment.hasContent()) {
9218 return false;
9219 }
9220 }
9221 return true;
9222 }
9223 canSetCurrentBlockAttribute(attributeName) {
9224 const block = this.getBlock();
9225 if (!block) return;
9226 return !block.isTerminalBlock();
9227 }
9228 setCurrentAttribute(attributeName, value) {
9229 if (getBlockConfig(attributeName)) {
9230 return this.setBlockAttribute(attributeName, value);
9231 } else {
9232 this.setTextAttribute(attributeName, value);
9233 this.currentAttributes[attributeName] = value;
9234 return this.notifyDelegateOfCurrentAttributesChange();
9235 }
9236 }
9237 setHTMLAtributeAtPosition(position, attributeName, value) {
9238 var _getBlockConfig;
9239 const block = this.document.getBlockAtPosition(position);
9240 const allowedHTMLAttributes = (_getBlockConfig = getBlockConfig(block.getLastAttribute())) === null || _getBlockConfig === void 0 ? void 0 : _getBlockConfig.htmlAttributes;
9241 if (block && allowedHTMLAttributes !== null && allowedHTMLAttributes !== void 0 && allowedHTMLAttributes.includes(attributeName)) {
9242 const newDocument = this.document.setHTMLAttributeAtPosition(position, attributeName, value);
9243 this.setDocument(newDocument);
9244 }
9245 }
9246 setTextAttribute(attributeName, value) {
9247 const selectedRange = this.getSelectedRange();
9248 if (!selectedRange) return;
9249 const [startPosition, endPosition] = Array.from(selectedRange);
9250 if (startPosition === endPosition) {
9251 if (attributeName === "href") {
9252 const text = Text.textForStringWithAttributes(value, {
9253 href: value
9254 });
9255 return this.insertText(text);
9256 }
9257 } else {
9258 return this.setDocument(this.document.addAttributeAtRange(attributeName, value, selectedRange));
9259 }
9260 }
9261 setBlockAttribute(attributeName, value) {
9262 const selectedRange = this.getSelectedRange();
9263 if (this.canSetCurrentAttribute(attributeName)) {
9264 this.setDocument(this.document.applyBlockAttributeAtRange(attributeName, value, selectedRange));
9265 return this.setSelection(selectedRange);
9266 }
9267 }
9268 removeCurrentAttribute(attributeName) {
9269 if (getBlockConfig(attributeName)) {
9270 this.removeBlockAttribute(attributeName);
9271 return this.updateCurrentAttributes();
9272 } else {
9273 this.removeTextAttribute(attributeName);
9274 delete this.currentAttributes[attributeName];
9275 return this.notifyDelegateOfCurrentAttributesChange();
9276 }
9277 }
9278 removeTextAttribute(attributeName) {
9279 const selectedRange = this.getSelectedRange();
9280 if (!selectedRange) return;
9281 return this.setDocument(this.document.removeAttributeAtRange(attributeName, selectedRange));
9282 }
9283 removeBlockAttribute(attributeName) {
9284 const selectedRange = this.getSelectedRange();
9285 if (!selectedRange) return;
9286 return this.setDocument(this.document.removeAttributeAtRange(attributeName, selectedRange));
9287 }
9288 canDecreaseNestingLevel() {
9289 var _this$getBlock;
9290 return ((_this$getBlock = this.getBlock()) === null || _this$getBlock === void 0 ? void 0 : _this$getBlock.getNestingLevel()) > 0;
9291 }
9292 canIncreaseNestingLevel() {
9293 var _getBlockConfig2;
9294 const block = this.getBlock();
9295 if (!block) return;
9296 if ((_getBlockConfig2 = getBlockConfig(block.getLastNestableAttribute())) !== null && _getBlockConfig2 !== void 0 && _getBlockConfig2.listAttribute) {
9297 const previousBlock = this.getPreviousBlock();
9298 if (previousBlock) {
9299 return arrayStartsWith(previousBlock.getListItemAttributes(), block.getListItemAttributes());
9300 }
9301 } else {
9302 return block.getNestingLevel() > 0;
9303 }
9304 }
9305 decreaseNestingLevel() {
9306 const block = this.getBlock();
9307 if (!block) return;
9308 return this.setDocument(this.document.replaceBlock(block, block.decreaseNestingLevel()));
9309 }
9310 increaseNestingLevel() {
9311 const block = this.getBlock();
9312 if (!block) return;
9313 return this.setDocument(this.document.replaceBlock(block, block.increaseNestingLevel()));
9314 }
9315 canDecreaseBlockAttributeLevel() {
9316 var _this$getBlock2;
9317 return ((_this$getBlock2 = this.getBlock()) === null || _this$getBlock2 === void 0 ? void 0 : _this$getBlock2.getAttributeLevel()) > 0;
9318 }
9319 decreaseBlockAttributeLevel() {
9320 var _this$getBlock3;
9321 const attribute = (_this$getBlock3 = this.getBlock()) === null || _this$getBlock3 === void 0 ? void 0 : _this$getBlock3.getLastAttribute();
9322 if (attribute) {
9323 return this.removeCurrentAttribute(attribute);
9324 }
9325 }
9326 decreaseListLevel() {
9327 let [startPosition] = Array.from(this.getSelectedRange());
9328 const {
9329 index
9330 } = this.document.locationFromPosition(startPosition);
9331 let endIndex = index;
9332 const attributeLevel = this.getBlock().getAttributeLevel();
9333 let block = this.document.getBlockAtIndex(endIndex + 1);
9334 while (block) {
9335 if (!block.isListItem() || block.getAttributeLevel() <= attributeLevel) {
9336 break;
9337 }
9338 endIndex++;
9339 block = this.document.getBlockAtIndex(endIndex + 1);
9340 }
9341 startPosition = this.document.positionFromLocation({
9342 index,
9343 offset: 0
9344 });
9345 const endPosition = this.document.positionFromLocation({
9346 index: endIndex,
9347 offset: 0
9348 });
9349 return this.setDocument(this.document.removeLastListAttributeAtRange([startPosition, endPosition]));
9350 }
9351 updateCurrentAttributes() {
9352 const selectedRange = this.getSelectedRange({
9353 ignoreLock: true
9354 });
9355 if (selectedRange) {
9356 const currentAttributes = this.document.getCommonAttributesAtRange(selectedRange);
9357 Array.from(getAllAttributeNames()).forEach(attributeName => {
9358 if (!currentAttributes[attributeName]) {
9359 if (!this.canSetCurrentAttribute(attributeName)) {
9360 currentAttributes[attributeName] = false;
9361 }
9362 }
9363 });
9364 if (!objectsAreEqual(currentAttributes, this.currentAttributes)) {
9365 this.currentAttributes = currentAttributes;
9366 return this.notifyDelegateOfCurrentAttributesChange();
9367 }
9368 }
9369 }
9370 getCurrentAttributes() {
9371 return extend.call({}, this.currentAttributes);
9372 }
9373 getCurrentTextAttributes() {
9374 const attributes = {};
9375 for (const key in this.currentAttributes) {
9376 const value = this.currentAttributes[key];
9377 if (value !== false) {
9378 if (getTextConfig(key)) {
9379 attributes[key] = value;
9380 }
9381 }
9382 }
9383 return attributes;
9384 }
9385
9386 // Selection freezing
9387
9388 freezeSelection() {
9389 return this.setCurrentAttribute("frozen", true);
9390 }
9391 thawSelection() {
9392 return this.removeCurrentAttribute("frozen");
9393 }
9394 hasFrozenSelection() {
9395 return this.hasCurrentAttribute("frozen");
9396 }
9397 setSelection(selectedRange) {
9398 var _this$delegate5;
9399 const locationRange = this.document.locationRangeFromRange(selectedRange);
9400 return (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 ? void 0 : _this$delegate5.compositionDidRequestChangingSelectionToLocationRange(locationRange);
9401 }
9402 getSelectedRange() {
9403 const locationRange = this.getLocationRange();
9404 if (locationRange) {
9405 return this.document.rangeFromLocationRange(locationRange);
9406 }
9407 }
9408 setSelectedRange(selectedRange) {
9409 const locationRange = this.document.locationRangeFromRange(selectedRange);
9410 return this.getSelectionManager().setLocationRange(locationRange);
9411 }
9412 getPosition() {
9413 const locationRange = this.getLocationRange();
9414 if (locationRange) {
9415 return this.document.positionFromLocation(locationRange[0]);
9416 }
9417 }
9418 getLocationRange(options) {
9419 if (this.targetLocationRange) {
9420 return this.targetLocationRange;
9421 } else {
9422 return this.getSelectionManager().getLocationRange(options) || normalizeRange({
9423 index: 0,
9424 offset: 0
9425 });
9426 }
9427 }
9428 withTargetLocationRange(locationRange, fn) {
9429 let result;
9430 this.targetLocationRange = locationRange;
9431 try {
9432 result = fn();
9433 } finally {
9434 this.targetLocationRange = null;
9435 }
9436 return result;
9437 }
9438 withTargetRange(range, fn) {
9439 const locationRange = this.document.locationRangeFromRange(range);
9440 return this.withTargetLocationRange(locationRange, fn);
9441 }
9442 withTargetDOMRange(domRange, fn) {
9443 const locationRange = this.createLocationRangeFromDOMRange(domRange, {
9444 strict: false
9445 });
9446 return this.withTargetLocationRange(locationRange, fn);
9447 }
9448 getExpandedRangeInDirection(direction) {
9449 let {
9450 length
9451 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
9452 let [startPosition, endPosition] = Array.from(this.getSelectedRange());
9453 if (direction === "backward") {
9454 if (length) {
9455 startPosition -= length;
9456 } else {
9457 startPosition = this.translateUTF16PositionFromOffset(startPosition, -1);
9458 }
9459 } else {
9460 if (length) {
9461 endPosition += length;
9462 } else {
9463 endPosition = this.translateUTF16PositionFromOffset(endPosition, 1);
9464 }
9465 }
9466 return normalizeRange([startPosition, endPosition]);
9467 }
9468 shouldManageMovingCursorInDirection(direction) {
9469 if (this.editingAttachment) {
9470 return true;
9471 }
9472 const range = this.getExpandedRangeInDirection(direction);
9473 return this.getAttachmentAtRange(range) != null;
9474 }
9475 moveCursorInDirection(direction) {
9476 let canEditAttachment, range;
9477 if (this.editingAttachment) {
9478 range = this.document.getRangeOfAttachment(this.editingAttachment);
9479 } else {
9480 const selectedRange = this.getSelectedRange();
9481 range = this.getExpandedRangeInDirection(direction);
9482 canEditAttachment = !rangesAreEqual(selectedRange, range);
9483 }
9484 if (direction === "backward") {
9485 this.setSelectedRange(range[0]);
9486 } else {
9487 this.setSelectedRange(range[1]);
9488 }
9489 if (canEditAttachment) {
9490 const attachment = this.getAttachmentAtRange(range);
9491 if (attachment) {
9492 return this.editAttachment(attachment);
9493 }
9494 }
9495 }
9496 expandSelectionInDirection(direction) {
9497 let {
9498 length
9499 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
9500 const range = this.getExpandedRangeInDirection(direction, {
9501 length
9502 });
9503 return this.setSelectedRange(range);
9504 }
9505 expandSelectionForEditing() {
9506 if (this.hasCurrentAttribute("href")) {
9507 return this.expandSelectionAroundCommonAttribute("href");
9508 }
9509 }
9510 expandSelectionAroundCommonAttribute(attributeName) {
9511 const position = this.getPosition();
9512 const range = this.document.getRangeOfCommonAttributeAtPosition(attributeName, position);
9513 return this.setSelectedRange(range);
9514 }
9515 selectionContainsAttachments() {
9516 var _this$getSelectedAtta;
9517 return ((_this$getSelectedAtta = this.getSelectedAttachments()) === null || _this$getSelectedAtta === void 0 ? void 0 : _this$getSelectedAtta.length) > 0;
9518 }
9519 selectionIsInCursorTarget() {
9520 return this.editingAttachment || this.positionIsCursorTarget(this.getPosition());
9521 }
9522 positionIsCursorTarget(position) {
9523 const location = this.document.locationFromPosition(position);
9524 if (location) {
9525 return this.locationIsCursorTarget(location);
9526 }
9527 }
9528 positionIsBlockBreak(position) {
9529 var _this$document$getPie;
9530 return (_this$document$getPie = this.document.getPieceAtPosition(position)) === null || _this$document$getPie === void 0 ? void 0 : _this$document$getPie.isBlockBreak();
9531 }
9532 getSelectedDocument() {
9533 const selectedRange = this.getSelectedRange();
9534 if (selectedRange) {
9535 return this.document.getDocumentAtRange(selectedRange);
9536 }
9537 }
9538 getSelectedAttachments() {
9539 var _this$getSelectedDocu;
9540 return (_this$getSelectedDocu = this.getSelectedDocument()) === null || _this$getSelectedDocu === void 0 ? void 0 : _this$getSelectedDocu.getAttachments();
9541 }
9542
9543 // Attachments
9544
9545 getAttachments() {
9546 return this.attachments.slice(0);
9547 }
9548 refreshAttachments() {
9549 const attachments = this.document.getAttachments();
9550 const {
9551 added,
9552 removed
9553 } = summarizeArrayChange(this.attachments, attachments);
9554 this.attachments = attachments;
9555 Array.from(removed).forEach(attachment => {
9556 var _this$delegate6, _this$delegate6$compo;
9557 attachment.delegate = null;
9558 (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 || (_this$delegate6$compo = _this$delegate6.compositionDidRemoveAttachment) === null || _this$delegate6$compo === void 0 || _this$delegate6$compo.call(_this$delegate6, attachment);
9559 });
9560 return (() => {
9561 const result = [];
9562 Array.from(added).forEach(attachment => {
9563 var _this$delegate7, _this$delegate7$compo;
9564 attachment.delegate = this;
9565 result.push((_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 || (_this$delegate7$compo = _this$delegate7.compositionDidAddAttachment) === null || _this$delegate7$compo === void 0 ? void 0 : _this$delegate7$compo.call(_this$delegate7, attachment));
9566 });
9567 return result;
9568 })();
9569 }
9570
9571 // Attachment delegate
9572
9573 attachmentDidChangeAttributes(attachment) {
9574 var _this$delegate8, _this$delegate8$compo;
9575 this.revision++;
9576 return (_this$delegate8 = this.delegate) === null || _this$delegate8 === void 0 || (_this$delegate8$compo = _this$delegate8.compositionDidEditAttachment) === null || _this$delegate8$compo === void 0 ? void 0 : _this$delegate8$compo.call(_this$delegate8, attachment);
9577 }
9578 attachmentDidChangePreviewURL(attachment) {
9579 var _this$delegate9, _this$delegate9$compo;
9580 this.revision++;
9581 return (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 || (_this$delegate9$compo = _this$delegate9.compositionDidChangeAttachmentPreviewURL) === null || _this$delegate9$compo === void 0 ? void 0 : _this$delegate9$compo.call(_this$delegate9, attachment);
9582 }
9583
9584 // Attachment editing
9585
9586 editAttachment(attachment, options) {
9587 var _this$delegate10, _this$delegate10$comp;
9588 if (attachment === this.editingAttachment) return;
9589 this.stopEditingAttachment();
9590 this.editingAttachment = attachment;
9591 return (_this$delegate10 = this.delegate) === null || _this$delegate10 === void 0 || (_this$delegate10$comp = _this$delegate10.compositionDidStartEditingAttachment) === null || _this$delegate10$comp === void 0 ? void 0 : _this$delegate10$comp.call(_this$delegate10, this.editingAttachment, options);
9592 }
9593 stopEditingAttachment() {
9594 var _this$delegate11, _this$delegate11$comp;
9595 if (!this.editingAttachment) return;
9596 (_this$delegate11 = this.delegate) === null || _this$delegate11 === void 0 || (_this$delegate11$comp = _this$delegate11.compositionDidStopEditingAttachment) === null || _this$delegate11$comp === void 0 || _this$delegate11$comp.call(_this$delegate11, this.editingAttachment);
9597 this.editingAttachment = null;
9598 }
9599 updateAttributesForAttachment(attributes, attachment) {
9600 return this.setDocument(this.document.updateAttributesForAttachment(attributes, attachment));
9601 }
9602 removeAttributeForAttachment(attribute, attachment) {
9603 return this.setDocument(this.document.removeAttributeForAttachment(attribute, attachment));
9604 }
9605
9606 // Private
9607
9608 breakFormattedBlock(insertion) {
9609 let {
9610 document
9611 } = insertion;
9612 const {
9613 block
9614 } = insertion;
9615 let position = insertion.startPosition;
9616 let range = [position - 1, position];
9617 if (block.getBlockBreakPosition() === insertion.startLocation.offset) {
9618 if (block.breaksOnReturn() && insertion.nextCharacter === "\n") {
9619 position += 1;
9620 } else {
9621 document = document.removeTextAtRange(range);
9622 }
9623 range = [position, position];
9624 } else if (insertion.nextCharacter === "\n") {
9625 if (insertion.previousCharacter === "\n") {
9626 range = [position - 1, position + 1];
9627 } else {
9628 range = [position, position + 1];
9629 position += 1;
9630 }
9631 } else if (insertion.startLocation.offset - 1 !== 0) {
9632 position += 1;
9633 }
9634 const newDocument = new Document([block.removeLastAttribute().copyWithoutText()]);
9635 this.setDocument(document.insertDocumentAtRange(newDocument, range));
9636 return this.setSelection(position);
9637 }
9638 getPreviousBlock() {
9639 const locationRange = this.getLocationRange();
9640 if (locationRange) {
9641 const {
9642 index
9643 } = locationRange[0];
9644 if (index > 0) {
9645 return this.document.getBlockAtIndex(index - 1);
9646 }
9647 }
9648 }
9649 getBlock() {
9650 const locationRange = this.getLocationRange();
9651 if (locationRange) {
9652 return this.document.getBlockAtIndex(locationRange[0].index);
9653 }
9654 }
9655 getAttachmentAtRange(range) {
9656 const document = this.document.getDocumentAtRange(range);
9657 if (document.toString() === "".concat(OBJECT_REPLACEMENT_CHARACTER, "\n")) {
9658 return document.getAttachments()[0];
9659 }
9660 }
9661 notifyDelegateOfCurrentAttributesChange() {
9662 var _this$delegate12, _this$delegate12$comp;
9663 return (_this$delegate12 = this.delegate) === null || _this$delegate12 === void 0 || (_this$delegate12$comp = _this$delegate12.compositionDidChangeCurrentAttributes) === null || _this$delegate12$comp === void 0 ? void 0 : _this$delegate12$comp.call(_this$delegate12, this.currentAttributes);
9664 }
9665 notifyDelegateOfInsertionAtRange(range) {
9666 var _this$delegate13, _this$delegate13$comp;
9667 return (_this$delegate13 = this.delegate) === null || _this$delegate13 === void 0 || (_this$delegate13$comp = _this$delegate13.compositionDidPerformInsertionAtRange) === null || _this$delegate13$comp === void 0 ? void 0 : _this$delegate13$comp.call(_this$delegate13, range);
9668 }
9669 translateUTF16PositionFromOffset(position, offset) {
9670 const utf16string = this.document.toUTF16String();
9671 const utf16position = utf16string.offsetFromUCS2Offset(position);
9672 return utf16string.offsetToUCS2Offset(utf16position + offset);
9673 }
9674 }
9675 Composition.proxyMethod("getSelectionManager().getPointRange");
9676 Composition.proxyMethod("getSelectionManager().setLocationRangeFromPointRange");
9677 Composition.proxyMethod("getSelectionManager().createLocationRangeFromDOMRange");
9678 Composition.proxyMethod("getSelectionManager().locationIsCursorTarget");
9679 Composition.proxyMethod("getSelectionManager().selectionIsExpanded");
9680 Composition.proxyMethod("delegate?.getSelectionManager");
9681
9682 class UndoManager extends BasicObject {
9683 constructor(composition) {
9684 super(...arguments);
9685 this.composition = composition;
9686 this.undoEntries = [];
9687 this.redoEntries = [];
9688 }
9689 recordUndoEntry(description) {
9690 let {
9691 context,
9692 consolidatable
9693 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
9694 const previousEntry = this.undoEntries.slice(-1)[0];
9695 if (!consolidatable || !entryHasDescriptionAndContext(previousEntry, description, context)) {
9696 const undoEntry = this.createEntry({
9697 description,
9698 context
9699 });
9700 this.undoEntries.push(undoEntry);
9701 this.redoEntries = [];
9702 }
9703 }
9704 undo() {
9705 const undoEntry = this.undoEntries.pop();
9706 if (undoEntry) {
9707 const redoEntry = this.createEntry(undoEntry);
9708 this.redoEntries.push(redoEntry);
9709 return this.composition.loadSnapshot(undoEntry.snapshot);
9710 }
9711 }
9712 redo() {
9713 const redoEntry = this.redoEntries.pop();
9714 if (redoEntry) {
9715 const undoEntry = this.createEntry(redoEntry);
9716 this.undoEntries.push(undoEntry);
9717 return this.composition.loadSnapshot(redoEntry.snapshot);
9718 }
9719 }
9720 canUndo() {
9721 return this.undoEntries.length > 0;
9722 }
9723 canRedo() {
9724 return this.redoEntries.length > 0;
9725 }
9726
9727 // Private
9728
9729 createEntry() {
9730 let {
9731 description,
9732 context
9733 } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
9734 return {
9735 description: description === null || description === void 0 ? void 0 : description.toString(),
9736 context: JSON.stringify(context),
9737 snapshot: this.composition.getSnapshot()
9738 };
9739 }
9740 }
9741 const entryHasDescriptionAndContext = (entry, description, context) => (entry === null || entry === void 0 ? void 0 : entry.description) === (description === null || description === void 0 ? void 0 : description.toString()) && (entry === null || entry === void 0 ? void 0 : entry.context) === JSON.stringify(context);
9742
9743 const BLOCK_ATTRIBUTE_NAME = "attachmentGallery";
9744 const TEXT_ATTRIBUTE_NAME = "presentation";
9745 const TEXT_ATTRIBUTE_VALUE = "gallery";
9746 class Filter {
9747 constructor(snapshot) {
9748 this.document = snapshot.document;
9749 this.selectedRange = snapshot.selectedRange;
9750 }
9751 perform() {
9752 this.removeBlockAttribute();
9753 return this.applyBlockAttribute();
9754 }
9755 getSnapshot() {
9756 return {
9757 document: this.document,
9758 selectedRange: this.selectedRange
9759 };
9760 }
9761
9762 // Private
9763
9764 removeBlockAttribute() {
9765 return this.findRangesOfBlocks().map(range => this.document = this.document.removeAttributeAtRange(BLOCK_ATTRIBUTE_NAME, range));
9766 }
9767 applyBlockAttribute() {
9768 let offset = 0;
9769 this.findRangesOfPieces().forEach(range => {
9770 if (range[1] - range[0] > 1) {
9771 range[0] += offset;
9772 range[1] += offset;
9773 if (this.document.getCharacterAtPosition(range[1]) !== "\n") {
9774 this.document = this.document.insertBlockBreakAtRange(range[1]);
9775 if (range[1] < this.selectedRange[1]) {
9776 this.moveSelectedRangeForward();
9777 }
9778 range[1]++;
9779 offset++;
9780 }
9781 if (range[0] !== 0) {
9782 if (this.document.getCharacterAtPosition(range[0] - 1) !== "\n") {
9783 this.document = this.document.insertBlockBreakAtRange(range[0]);
9784 if (range[0] < this.selectedRange[0]) {
9785 this.moveSelectedRangeForward();
9786 }
9787 range[0]++;
9788 offset++;
9789 }
9790 }
9791 this.document = this.document.applyBlockAttributeAtRange(BLOCK_ATTRIBUTE_NAME, true, range);
9792 }
9793 });
9794 }
9795 findRangesOfBlocks() {
9796 return this.document.findRangesForBlockAttribute(BLOCK_ATTRIBUTE_NAME);
9797 }
9798 findRangesOfPieces() {
9799 return this.document.findRangesForTextAttribute(TEXT_ATTRIBUTE_NAME, {
9800 withValue: TEXT_ATTRIBUTE_VALUE
9801 });
9802 }
9803 moveSelectedRangeForward() {
9804 this.selectedRange[0] += 1;
9805 this.selectedRange[1] += 1;
9806 }
9807 }
9808
9809 const attachmentGalleryFilter = function (snapshot) {
9810 const filter = new Filter(snapshot);
9811 filter.perform();
9812 return filter.getSnapshot();
9813 };
9814
9815 const DEFAULT_FILTERS = [attachmentGalleryFilter];
9816 class Editor {
9817 constructor(composition, selectionManager, element) {
9818 this.insertFiles = this.insertFiles.bind(this);
9819 this.composition = composition;
9820 this.selectionManager = selectionManager;
9821 this.element = element;
9822 this.undoManager = new UndoManager(this.composition);
9823 this.filters = DEFAULT_FILTERS.slice(0);
9824 }
9825 loadDocument(document) {
9826 return this.loadSnapshot({
9827 document,
9828 selectedRange: [0, 0]
9829 });
9830 }
9831 loadHTML() {
9832 let html = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
9833 const document = HTMLParser.parse(html, {
9834 referenceElement: this.element
9835 }).getDocument();
9836 return this.loadDocument(document);
9837 }
9838 loadJSON(_ref) {
9839 let {
9840 document,
9841 selectedRange
9842 } = _ref;
9843 document = Document.fromJSON(document);
9844 return this.loadSnapshot({
9845 document,
9846 selectedRange
9847 });
9848 }
9849 loadSnapshot(snapshot) {
9850 this.undoManager = new UndoManager(this.composition);
9851 return this.composition.loadSnapshot(snapshot);
9852 }
9853 getDocument() {
9854 return this.composition.document;
9855 }
9856 getSelectedDocument() {
9857 return this.composition.getSelectedDocument();
9858 }
9859 getSnapshot() {
9860 return this.composition.getSnapshot();
9861 }
9862 toJSON() {
9863 return this.getSnapshot();
9864 }
9865
9866 // Document manipulation
9867
9868 deleteInDirection(direction) {
9869 return this.composition.deleteInDirection(direction);
9870 }
9871 insertAttachment(attachment) {
9872 return this.composition.insertAttachment(attachment);
9873 }
9874 insertAttachments(attachments) {
9875 return this.composition.insertAttachments(attachments);
9876 }
9877 insertDocument(document) {
9878 return this.composition.insertDocument(document);
9879 }
9880 insertFile(file) {
9881 return this.composition.insertFile(file);
9882 }
9883 insertFiles(files) {
9884 return this.composition.insertFiles(files);
9885 }
9886 insertHTML(html) {
9887 return this.composition.insertHTML(html);
9888 }
9889 insertString(string) {
9890 return this.composition.insertString(string);
9891 }
9892 insertText(text) {
9893 return this.composition.insertText(text);
9894 }
9895 insertLineBreak() {
9896 return this.composition.insertLineBreak();
9897 }
9898
9899 // Selection
9900
9901 getSelectedRange() {
9902 return this.composition.getSelectedRange();
9903 }
9904 getPosition() {
9905 return this.composition.getPosition();
9906 }
9907 getClientRectAtPosition(position) {
9908 const locationRange = this.getDocument().locationRangeFromRange([position, position + 1]);
9909 return this.selectionManager.getClientRectAtLocationRange(locationRange);
9910 }
9911 expandSelectionInDirection(direction) {
9912 return this.composition.expandSelectionInDirection(direction);
9913 }
9914 moveCursorInDirection(direction) {
9915 return this.composition.moveCursorInDirection(direction);
9916 }
9917 setSelectedRange(selectedRange) {
9918 return this.composition.setSelectedRange(selectedRange);
9919 }
9920
9921 // Attributes
9922
9923 activateAttribute(name) {
9924 let value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
9925 return this.composition.setCurrentAttribute(name, value);
9926 }
9927 attributeIsActive(name) {
9928 return this.composition.hasCurrentAttribute(name);
9929 }
9930 canActivateAttribute(name) {
9931 return this.composition.canSetCurrentAttribute(name);
9932 }
9933 deactivateAttribute(name) {
9934 return this.composition.removeCurrentAttribute(name);
9935 }
9936
9937 // HTML attributes
9938 setHTMLAtributeAtPosition(position, name, value) {
9939 this.composition.setHTMLAtributeAtPosition(position, name, value);
9940 }
9941
9942 // Nesting level
9943
9944 canDecreaseNestingLevel() {
9945 return this.composition.canDecreaseNestingLevel();
9946 }
9947 canIncreaseNestingLevel() {
9948 return this.composition.canIncreaseNestingLevel();
9949 }
9950 decreaseNestingLevel() {
9951 if (this.canDecreaseNestingLevel()) {
9952 return this.composition.decreaseNestingLevel();
9953 }
9954 }
9955 increaseNestingLevel() {
9956 if (this.canIncreaseNestingLevel()) {
9957 return this.composition.increaseNestingLevel();
9958 }
9959 }
9960
9961 // Undo/redo
9962
9963 canRedo() {
9964 return this.undoManager.canRedo();
9965 }
9966 canUndo() {
9967 return this.undoManager.canUndo();
9968 }
9969 recordUndoEntry(description) {
9970 let {
9971 context,
9972 consolidatable
9973 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
9974 return this.undoManager.recordUndoEntry(description, {
9975 context,
9976 consolidatable
9977 });
9978 }
9979 redo() {
9980 if (this.canRedo()) {
9981 return this.undoManager.redo();
9982 }
9983 }
9984 undo() {
9985 if (this.canUndo()) {
9986 return this.undoManager.undo();
9987 }
9988 }
9989 }
9990
9991 /* eslint-disable
9992 no-var,
9993 prefer-const,
9994 */
9995 class LocationMapper {
9996 constructor(element) {
9997 this.element = element;
9998 }
9999 findLocationFromContainerAndOffset(container, offset) {
10000 let {
10001 strict
10002 } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
10003 strict: true
10004 };
10005 let childIndex = 0;
10006 let foundBlock = false;
10007 const location = {
10008 index: 0,
10009 offset: 0
10010 };
10011 const attachmentElement = this.findAttachmentElementParentForNode(container);
10012 if (attachmentElement) {
10013 container = attachmentElement.parentNode;
10014 offset = findChildIndexOfNode(attachmentElement);
10015 }
10016 const walker = walkTree(this.element, {
10017 usingFilter: rejectAttachmentContents
10018 });
10019 while (walker.nextNode()) {
10020 const node = walker.currentNode;
10021 if (node === container && nodeIsTextNode(container)) {
10022 if (!nodeIsCursorTarget(node)) {
10023 location.offset += offset;
10024 }
10025 break;
10026 } else {
10027 if (node.parentNode === container) {
10028 if (childIndex++ === offset) {
10029 break;
10030 }
10031 } else if (!elementContainsNode(container, node)) {
10032 if (childIndex > 0) {
10033 break;
10034 }
10035 }
10036 if (nodeIsBlockStart(node, {
10037 strict
10038 })) {
10039 if (foundBlock) {
10040 location.index++;
10041 }
10042 location.offset = 0;
10043 foundBlock = true;
10044 } else {
10045 location.offset += nodeLength(node);
10046 }
10047 }
10048 }
10049 return location;
10050 }
10051 findContainerAndOffsetFromLocation(location) {
10052 let container, offset;
10053 if (location.index === 0 && location.offset === 0) {
10054 container = this.element;
10055 offset = 0;
10056 while (container.firstChild) {
10057 container = container.firstChild;
10058 if (nodeIsBlockContainer(container)) {
10059 offset = 1;
10060 break;
10061 }
10062 }
10063 return [container, offset];
10064 }
10065 let [node, nodeOffset] = this.findNodeAndOffsetFromLocation(location);
10066 if (!node) return;
10067 if (nodeIsTextNode(node)) {
10068 if (nodeLength(node) === 0) {
10069 container = node.parentNode.parentNode;
10070 offset = findChildIndexOfNode(node.parentNode);
10071 if (nodeIsCursorTarget(node, {
10072 name: "right"
10073 })) {
10074 offset++;
10075 }
10076 } else {
10077 container = node;
10078 offset = location.offset - nodeOffset;
10079 }
10080 } else {
10081 container = node.parentNode;
10082 if (!nodeIsBlockStart(node.previousSibling)) {
10083 if (!nodeIsBlockContainer(container)) {
10084 while (node === container.lastChild) {
10085 node = container;
10086 container = container.parentNode;
10087 if (nodeIsBlockContainer(container)) {
10088 break;
10089 }
10090 }
10091 }
10092 }
10093 offset = findChildIndexOfNode(node);
10094 if (location.offset !== 0) {
10095 offset++;
10096 }
10097 }
10098 return [container, offset];
10099 }
10100 findNodeAndOffsetFromLocation(location) {
10101 let node, nodeOffset;
10102 let offset = 0;
10103 for (const currentNode of this.getSignificantNodesForIndex(location.index)) {
10104 const length = nodeLength(currentNode);
10105 if (location.offset <= offset + length) {
10106 if (nodeIsTextNode(currentNode)) {
10107 node = currentNode;
10108 nodeOffset = offset;
10109 if (location.offset === nodeOffset && nodeIsCursorTarget(node)) {
10110 break;
10111 }
10112 } else if (!node) {
10113 node = currentNode;
10114 nodeOffset = offset;
10115 }
10116 }
10117 offset += length;
10118 if (offset > location.offset) {
10119 break;
10120 }
10121 }
10122 return [node, nodeOffset];
10123 }
10124
10125 // Private
10126
10127 findAttachmentElementParentForNode(node) {
10128 while (node && node !== this.element) {
10129 if (nodeIsAttachmentElement(node)) {
10130 return node;
10131 }
10132 node = node.parentNode;
10133 }
10134 }
10135 getSignificantNodesForIndex(index) {
10136 const nodes = [];
10137 const walker = walkTree(this.element, {
10138 usingFilter: acceptSignificantNodes
10139 });
10140 let recordingNodes = false;
10141 while (walker.nextNode()) {
10142 const node = walker.currentNode;
10143 if (nodeIsBlockStartComment(node)) {
10144 var blockIndex;
10145 if (blockIndex != null) {
10146 blockIndex++;
10147 } else {
10148 blockIndex = 0;
10149 }
10150 if (blockIndex === index) {
10151 recordingNodes = true;
10152 } else if (recordingNodes) {
10153 break;
10154 }
10155 } else if (recordingNodes) {
10156 nodes.push(node);
10157 }
10158 }
10159 return nodes;
10160 }
10161 }
10162 const nodeLength = function (node) {
10163 if (node.nodeType === Node.TEXT_NODE) {
10164 if (nodeIsCursorTarget(node)) {
10165 return 0;
10166 } else {
10167 const string = node.textContent;
10168 return string.length;
10169 }
10170 } else if (tagName(node) === "br" || nodeIsAttachmentElement(node)) {
10171 return 1;
10172 } else {
10173 return 0;
10174 }
10175 };
10176 const acceptSignificantNodes = function (node) {
10177 if (rejectEmptyTextNodes(node) === NodeFilter.FILTER_ACCEPT) {
10178 return rejectAttachmentContents(node);
10179 } else {
10180 return NodeFilter.FILTER_REJECT;
10181 }
10182 };
10183 const rejectEmptyTextNodes = function (node) {
10184 if (nodeIsEmptyTextNode(node)) {
10185 return NodeFilter.FILTER_REJECT;
10186 } else {
10187 return NodeFilter.FILTER_ACCEPT;
10188 }
10189 };
10190 const rejectAttachmentContents = function (node) {
10191 if (nodeIsAttachmentElement(node.parentNode)) {
10192 return NodeFilter.FILTER_REJECT;
10193 } else {
10194 return NodeFilter.FILTER_ACCEPT;
10195 }
10196 };
10197
10198 /* eslint-disable
10199 id-length,
10200 no-empty,
10201 */
10202 class PointMapper {
10203 createDOMRangeFromPoint(_ref) {
10204 let {
10205 x,
10206 y
10207 } = _ref;
10208 let domRange;
10209 if (document.caretPositionFromPoint) {
10210 const {
10211 offsetNode,
10212 offset
10213 } = document.caretPositionFromPoint(x, y);
10214 domRange = document.createRange();
10215 domRange.setStart(offsetNode, offset);
10216 return domRange;
10217 } else if (document.caretRangeFromPoint) {
10218 return document.caretRangeFromPoint(x, y);
10219 } else if (document.body.createTextRange) {
10220 const originalDOMRange = getDOMRange();
10221 try {
10222 // IE 11 throws "Unspecified error" when using moveToPoint
10223 // during a drag-and-drop operation.
10224 const textRange = document.body.createTextRange();
10225 textRange.moveToPoint(x, y);
10226 textRange.select();
10227 } catch (error) {}
10228 domRange = getDOMRange();
10229 setDOMRange(originalDOMRange);
10230 return domRange;
10231 }
10232 }
10233 getClientRectsForDOMRange(domRange) {
10234 const array = Array.from(domRange.getClientRects());
10235 const start = array[0];
10236 const end = array[array.length - 1];
10237 return [start, end];
10238 }
10239 }
10240
10241 /* eslint-disable
10242 */
10243 class SelectionManager extends BasicObject {
10244 constructor(element) {
10245 super(...arguments);
10246 this.didMouseDown = this.didMouseDown.bind(this);
10247 this.selectionDidChange = this.selectionDidChange.bind(this);
10248 this.element = element;
10249 this.locationMapper = new LocationMapper(this.element);
10250 this.pointMapper = new PointMapper();
10251 this.lockCount = 0;
10252 handleEvent("mousedown", {
10253 onElement: this.element,
10254 withCallback: this.didMouseDown
10255 });
10256 }
10257 getLocationRange() {
10258 let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
10259 if (options.strict === false) {
10260 return this.createLocationRangeFromDOMRange(getDOMRange());
10261 } else if (options.ignoreLock) {
10262 return this.currentLocationRange;
10263 } else if (this.lockedLocationRange) {
10264 return this.lockedLocationRange;
10265 } else {
10266 return this.currentLocationRange;
10267 }
10268 }
10269 setLocationRange(locationRange) {
10270 if (this.lockedLocationRange) return;
10271 locationRange = normalizeRange(locationRange);
10272 const domRange = this.createDOMRangeFromLocationRange(locationRange);
10273 if (domRange) {
10274 setDOMRange(domRange);
10275 this.updateCurrentLocationRange(locationRange);
10276 }
10277 }
10278 setLocationRangeFromPointRange(pointRange) {
10279 pointRange = normalizeRange(pointRange);
10280 const startLocation = this.getLocationAtPoint(pointRange[0]);
10281 const endLocation = this.getLocationAtPoint(pointRange[1]);
10282 this.setLocationRange([startLocation, endLocation]);
10283 }
10284 getClientRectAtLocationRange(locationRange) {
10285 const domRange = this.createDOMRangeFromLocationRange(locationRange);
10286 if (domRange) {
10287 return this.getClientRectsForDOMRange(domRange)[1];
10288 }
10289 }
10290 locationIsCursorTarget(location) {
10291 const node = Array.from(this.findNodeAndOffsetFromLocation(location))[0];
10292 return nodeIsCursorTarget(node);
10293 }
10294 lock() {
10295 if (this.lockCount++ === 0) {
10296 this.updateCurrentLocationRange();
10297 this.lockedLocationRange = this.getLocationRange();
10298 }
10299 }
10300 unlock() {
10301 if (--this.lockCount === 0) {
10302 const {
10303 lockedLocationRange
10304 } = this;
10305 this.lockedLocationRange = null;
10306 if (lockedLocationRange != null) {
10307 return this.setLocationRange(lockedLocationRange);
10308 }
10309 }
10310 }
10311 clearSelection() {
10312 var _getDOMSelection;
10313 return (_getDOMSelection = getDOMSelection()) === null || _getDOMSelection === void 0 ? void 0 : _getDOMSelection.removeAllRanges();
10314 }
10315 selectionIsCollapsed() {
10316 var _getDOMRange;
10317 return ((_getDOMRange = getDOMRange()) === null || _getDOMRange === void 0 ? void 0 : _getDOMRange.collapsed) === true;
10318 }
10319 selectionIsExpanded() {
10320 return !this.selectionIsCollapsed();
10321 }
10322 createLocationRangeFromDOMRange(domRange, options) {
10323 if (domRange == null || !this.domRangeWithinElement(domRange)) return;
10324 const start = this.findLocationFromContainerAndOffset(domRange.startContainer, domRange.startOffset, options);
10325 if (!start) return;
10326 const end = domRange.collapsed ? undefined : this.findLocationFromContainerAndOffset(domRange.endContainer, domRange.endOffset, options);
10327 return normalizeRange([start, end]);
10328 }
10329 didMouseDown() {
10330 return this.pauseTemporarily();
10331 }
10332 pauseTemporarily() {
10333 let resumeHandlers;
10334 this.paused = true;
10335 const resume = () => {
10336 this.paused = false;
10337 clearTimeout(resumeTimeout);
10338 Array.from(resumeHandlers).forEach(handler => {
10339 handler.destroy();
10340 });
10341 if (elementContainsNode(document, this.element)) {
10342 return this.selectionDidChange();
10343 }
10344 };
10345 const resumeTimeout = setTimeout(resume, 200);
10346 resumeHandlers = ["mousemove", "keydown"].map(eventName => handleEvent(eventName, {
10347 onElement: document,
10348 withCallback: resume
10349 }));
10350 }
10351 selectionDidChange() {
10352 if (!this.paused && !innerElementIsActive(this.element)) {
10353 return this.updateCurrentLocationRange();
10354 }
10355 }
10356 updateCurrentLocationRange(locationRange) {
10357 if (locationRange != null ? locationRange : locationRange = this.createLocationRangeFromDOMRange(getDOMRange())) {
10358 if (!rangesAreEqual(locationRange, this.currentLocationRange)) {
10359 var _this$delegate, _this$delegate$locati;
10360 this.currentLocationRange = locationRange;
10361 return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$locati = _this$delegate.locationRangeDidChange) === null || _this$delegate$locati === void 0 ? void 0 : _this$delegate$locati.call(_this$delegate, this.currentLocationRange.slice(0));
10362 }
10363 }
10364 }
10365 createDOMRangeFromLocationRange(locationRange) {
10366 const rangeStart = this.findContainerAndOffsetFromLocation(locationRange[0]);
10367 const rangeEnd = rangeIsCollapsed(locationRange) ? rangeStart : this.findContainerAndOffsetFromLocation(locationRange[1]) || rangeStart;
10368 if (rangeStart != null && rangeEnd != null) {
10369 const domRange = document.createRange();
10370 domRange.setStart(...Array.from(rangeStart || []));
10371 domRange.setEnd(...Array.from(rangeEnd || []));
10372 return domRange;
10373 }
10374 }
10375 getLocationAtPoint(point) {
10376 const domRange = this.createDOMRangeFromPoint(point);
10377 if (domRange) {
10378 var _this$createLocationR;
10379 return (_this$createLocationR = this.createLocationRangeFromDOMRange(domRange)) === null || _this$createLocationR === void 0 ? void 0 : _this$createLocationR[0];
10380 }
10381 }
10382 domRangeWithinElement(domRange) {
10383 if (domRange.collapsed) {
10384 return elementContainsNode(this.element, domRange.startContainer);
10385 } else {
10386 return elementContainsNode(this.element, domRange.startContainer) && elementContainsNode(this.element, domRange.endContainer);
10387 }
10388 }
10389 }
10390 SelectionManager.proxyMethod("locationMapper.findLocationFromContainerAndOffset");
10391 SelectionManager.proxyMethod("locationMapper.findContainerAndOffsetFromLocation");
10392 SelectionManager.proxyMethod("locationMapper.findNodeAndOffsetFromLocation");
10393 SelectionManager.proxyMethod("pointMapper.createDOMRangeFromPoint");
10394 SelectionManager.proxyMethod("pointMapper.getClientRectsForDOMRange");
10395
10396 var models = /*#__PURE__*/Object.freeze({
10397 __proto__: null,
10398 Attachment: Attachment,
10399 AttachmentManager: AttachmentManager,
10400 AttachmentPiece: AttachmentPiece,
10401 Block: Block,
10402 Composition: Composition,
10403 Document: Document,
10404 Editor: Editor,
10405 HTMLParser: HTMLParser,
10406 HTMLSanitizer: HTMLSanitizer,
10407 LineBreakInsertion: LineBreakInsertion,
10408 LocationMapper: LocationMapper,
10409 ManagedAttachment: ManagedAttachment,
10410 Piece: Piece,
10411 PointMapper: PointMapper,
10412 SelectionManager: SelectionManager,
10413 SplittableList: SplittableList,
10414 StringPiece: StringPiece,
10415 Text: Text,
10416 UndoManager: UndoManager
10417 });
10418
10419 var views = /*#__PURE__*/Object.freeze({
10420 __proto__: null,
10421 ObjectView: ObjectView,
10422 AttachmentView: AttachmentView,
10423 BlockView: BlockView,
10424 DocumentView: DocumentView,
10425 PieceView: PieceView,
10426 PreviewableAttachmentView: PreviewableAttachmentView,
10427 TextView: TextView
10428 });
10429
10430 const {
10431 lang,
10432 css,
10433 keyNames: keyNames$1
10434 } = config;
10435 const undoable = function (fn) {
10436 return function () {
10437 const commands = fn.apply(this, arguments);
10438 commands.do();
10439 if (!this.undos) {
10440 this.undos = [];
10441 }
10442 this.undos.push(commands.undo);
10443 };
10444 };
10445 class AttachmentEditorController extends BasicObject {
10446 constructor(attachmentPiece, _element, container) {
10447 let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
10448 super(...arguments);
10449 // Installing and uninstalling
10450 _defineProperty(this, "makeElementMutable", undoable(() => {
10451 return {
10452 do: () => {
10453 this.element.dataset.trixMutable = true;
10454 },
10455 undo: () => delete this.element.dataset.trixMutable
10456 };
10457 }));
10458 _defineProperty(this, "addToolbar", undoable(() => {
10459 // <div class="#{css.attachmentMetadataContainer}" data-trix-mutable="true">
10460 // <div class="trix-button-row">
10461 // <span class="trix-button-group trix-button-group--actions">
10462 // <button type="button" class="trix-button trix-button--remove" title="#{lang.remove}" data-trix-action="remove">#{lang.remove}</button>
10463 // </span>
10464 // </div>
10465 // </div>
10466 const element = makeElement({
10467 tagName: "div",
10468 className: css.attachmentToolbar,
10469 data: {
10470 trixMutable: true
10471 },
10472 childNodes: makeElement({
10473 tagName: "div",
10474 className: "trix-button-row",
10475 childNodes: makeElement({
10476 tagName: "span",
10477 className: "trix-button-group trix-button-group--actions",
10478 childNodes: makeElement({
10479 tagName: "button",
10480 className: "trix-button trix-button--remove",
10481 textContent: lang.remove,
10482 attributes: {
10483 title: lang.remove
10484 },
10485 data: {
10486 trixAction: "remove"
10487 }
10488 })
10489 })
10490 })
10491 });
10492 if (this.attachment.isPreviewable()) {
10493 // <div class="#{css.attachmentMetadataContainer}">
10494 // <span class="#{css.attachmentMetadata}">
10495 // <span class="#{css.attachmentName}" title="#{name}">#{name}</span>
10496 // <span class="#{css.attachmentSize}">#{size}</span>
10497 // </span>
10498 // </div>
10499 element.appendChild(makeElement({
10500 tagName: "div",
10501 className: css.attachmentMetadataContainer,
10502 childNodes: makeElement({
10503 tagName: "span",
10504 className: css.attachmentMetadata,
10505 childNodes: [makeElement({
10506 tagName: "span",
10507 className: css.attachmentName,
10508 textContent: this.attachment.getFilename(),
10509 attributes: {
10510 title: this.attachment.getFilename()
10511 }
10512 }), makeElement({
10513 tagName: "span",
10514 className: css.attachmentSize,
10515 textContent: this.attachment.getFormattedFilesize()
10516 })]
10517 })
10518 }));
10519 }
10520 handleEvent("click", {
10521 onElement: element,
10522 withCallback: this.didClickToolbar
10523 });
10524 handleEvent("click", {
10525 onElement: element,
10526 matchingSelector: "[data-trix-action]",
10527 withCallback: this.didClickActionButton
10528 });
10529 triggerEvent("trix-attachment-before-toolbar", {
10530 onElement: this.element,
10531 attributes: {
10532 toolbar: element,
10533 attachment: this.attachment
10534 }
10535 });
10536 return {
10537 do: () => this.element.appendChild(element),
10538 undo: () => removeNode(element)
10539 };
10540 }));
10541 _defineProperty(this, "installCaptionEditor", undoable(() => {
10542 const textarea = makeElement({
10543 tagName: "textarea",
10544 className: css.attachmentCaptionEditor,
10545 attributes: {
10546 placeholder: lang.captionPlaceholder
10547 },
10548 data: {
10549 trixMutable: true
10550 }
10551 });
10552 textarea.value = this.attachmentPiece.getCaption();
10553 const textareaClone = textarea.cloneNode();
10554 textareaClone.classList.add("trix-autoresize-clone");
10555 textareaClone.tabIndex = -1;
10556 const autoresize = function () {
10557 textareaClone.value = textarea.value;
10558 textarea.style.height = textareaClone.scrollHeight + "px";
10559 };
10560 handleEvent("input", {
10561 onElement: textarea,
10562 withCallback: autoresize
10563 });
10564 handleEvent("input", {
10565 onElement: textarea,
10566 withCallback: this.didInputCaption
10567 });
10568 handleEvent("keydown", {
10569 onElement: textarea,
10570 withCallback: this.didKeyDownCaption
10571 });
10572 handleEvent("change", {
10573 onElement: textarea,
10574 withCallback: this.didChangeCaption
10575 });
10576 handleEvent("blur", {
10577 onElement: textarea,
10578 withCallback: this.didBlurCaption
10579 });
10580 const figcaption = this.element.querySelector("figcaption");
10581 const editingFigcaption = figcaption.cloneNode();
10582 return {
10583 do: () => {
10584 figcaption.style.display = "none";
10585 editingFigcaption.appendChild(textarea);
10586 editingFigcaption.appendChild(textareaClone);
10587 editingFigcaption.classList.add("".concat(css.attachmentCaption, "--editing"));
10588 figcaption.parentElement.insertBefore(editingFigcaption, figcaption);
10589 autoresize();
10590 if (this.options.editCaption) {
10591 return defer(() => textarea.focus());
10592 }
10593 },
10594 undo() {
10595 removeNode(editingFigcaption);
10596 figcaption.style.display = null;
10597 }
10598 };
10599 }));
10600 this.didClickToolbar = this.didClickToolbar.bind(this);
10601 this.didClickActionButton = this.didClickActionButton.bind(this);
10602 this.didKeyDownCaption = this.didKeyDownCaption.bind(this);
10603 this.didInputCaption = this.didInputCaption.bind(this);
10604 this.didChangeCaption = this.didChangeCaption.bind(this);
10605 this.didBlurCaption = this.didBlurCaption.bind(this);
10606 this.attachmentPiece = attachmentPiece;
10607 this.element = _element;
10608 this.container = container;
10609 this.options = options;
10610 this.attachment = this.attachmentPiece.attachment;
10611 if (tagName(this.element) === "a") {
10612 this.element = this.element.firstChild;
10613 }
10614 this.install();
10615 }
10616 install() {
10617 this.makeElementMutable();
10618 this.addToolbar();
10619 if (this.attachment.isPreviewable()) {
10620 this.installCaptionEditor();
10621 }
10622 }
10623 uninstall() {
10624 var _this$delegate;
10625 let undo = this.undos.pop();
10626 this.savePendingCaption();
10627 while (undo) {
10628 undo();
10629 undo = this.undos.pop();
10630 }
10631 (_this$delegate = this.delegate) === null || _this$delegate === void 0 || _this$delegate.didUninstallAttachmentEditor(this);
10632 }
10633
10634 // Private
10635
10636 savePendingCaption() {
10637 if (this.pendingCaption != null) {
10638 const caption = this.pendingCaption;
10639 this.pendingCaption = null;
10640 if (caption) {
10641 var _this$delegate2, _this$delegate2$attac;
10642 (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || (_this$delegate2$attac = _this$delegate2.attachmentEditorDidRequestUpdatingAttributesForAttachment) === null || _this$delegate2$attac === void 0 || _this$delegate2$attac.call(_this$delegate2, {
10643 caption
10644 }, this.attachment);
10645 } else {
10646 var _this$delegate3, _this$delegate3$attac;
10647 (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 || (_this$delegate3$attac = _this$delegate3.attachmentEditorDidRequestRemovingAttributeForAttachment) === null || _this$delegate3$attac === void 0 || _this$delegate3$attac.call(_this$delegate3, "caption", this.attachment);
10648 }
10649 }
10650 }
10651 // Event handlers
10652
10653 didClickToolbar(event) {
10654 event.preventDefault();
10655 return event.stopPropagation();
10656 }
10657 didClickActionButton(event) {
10658 var _this$delegate4;
10659 const action = event.target.getAttribute("data-trix-action");
10660 switch (action) {
10661 case "remove":
10662 return (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 ? void 0 : _this$delegate4.attachmentEditorDidRequestRemovalOfAttachment(this.attachment);
10663 }
10664 }
10665 didKeyDownCaption(event) {
10666 if (keyNames$1[event.keyCode] === "return") {
10667 var _this$delegate5, _this$delegate5$attac;
10668 event.preventDefault();
10669 this.savePendingCaption();
10670 return (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || (_this$delegate5$attac = _this$delegate5.attachmentEditorDidRequestDeselectingAttachment) === null || _this$delegate5$attac === void 0 ? void 0 : _this$delegate5$attac.call(_this$delegate5, this.attachment);
10671 }
10672 }
10673 didInputCaption(event) {
10674 this.pendingCaption = event.target.value.replace(/\s/g, " ").trim();
10675 }
10676 didChangeCaption(event) {
10677 return this.savePendingCaption();
10678 }
10679 didBlurCaption(event) {
10680 return this.savePendingCaption();
10681 }
10682 }
10683
10684 class CompositionController extends BasicObject {
10685 constructor(element, composition) {
10686 super(...arguments);
10687 this.didFocus = this.didFocus.bind(this);
10688 this.didBlur = this.didBlur.bind(this);
10689 this.didClickAttachment = this.didClickAttachment.bind(this);
10690 this.element = element;
10691 this.composition = composition;
10692 this.documentView = new DocumentView(this.composition.document, {
10693 element: this.element
10694 });
10695 handleEvent("focus", {
10696 onElement: this.element,
10697 withCallback: this.didFocus
10698 });
10699 handleEvent("blur", {
10700 onElement: this.element,
10701 withCallback: this.didBlur
10702 });
10703 handleEvent("click", {
10704 onElement: this.element,
10705 matchingSelector: "a[contenteditable=false]",
10706 preventDefault: true
10707 });
10708 handleEvent("mousedown", {
10709 onElement: this.element,
10710 matchingSelector: attachmentSelector,
10711 withCallback: this.didClickAttachment
10712 });
10713 handleEvent("click", {
10714 onElement: this.element,
10715 matchingSelector: "a".concat(attachmentSelector),
10716 preventDefault: true
10717 });
10718 }
10719 didFocus(event) {
10720 var _this$blurPromise;
10721 const perform = () => {
10722 if (!this.focused) {
10723 var _this$delegate, _this$delegate$compos;
10724 this.focused = true;
10725 return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$compos = _this$delegate.compositionControllerDidFocus) === null || _this$delegate$compos === void 0 ? void 0 : _this$delegate$compos.call(_this$delegate);
10726 }
10727 };
10728 return ((_this$blurPromise = this.blurPromise) === null || _this$blurPromise === void 0 ? void 0 : _this$blurPromise.then(perform)) || perform();
10729 }
10730 didBlur(event) {
10731 this.blurPromise = new Promise(resolve => {
10732 return defer(() => {
10733 if (!innerElementIsActive(this.element)) {
10734 var _this$delegate2, _this$delegate2$compo;
10735 this.focused = null;
10736 (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || (_this$delegate2$compo = _this$delegate2.compositionControllerDidBlur) === null || _this$delegate2$compo === void 0 || _this$delegate2$compo.call(_this$delegate2);
10737 }
10738 this.blurPromise = null;
10739 return resolve();
10740 });
10741 });
10742 }
10743 didClickAttachment(event, target) {
10744 var _this$delegate3, _this$delegate3$compo;
10745 const attachment = this.findAttachmentForElement(target);
10746 const editCaption = !!findClosestElementFromNode(event.target, {
10747 matchingSelector: "figcaption"
10748 });
10749 return (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 || (_this$delegate3$compo = _this$delegate3.compositionControllerDidSelectAttachment) === null || _this$delegate3$compo === void 0 ? void 0 : _this$delegate3$compo.call(_this$delegate3, attachment, {
10750 editCaption
10751 });
10752 }
10753 getSerializableElement() {
10754 if (this.isEditingAttachment()) {
10755 return this.documentView.shadowElement;
10756 } else {
10757 return this.element;
10758 }
10759 }
10760 render() {
10761 var _this$delegate6, _this$delegate6$compo;
10762 if (this.revision !== this.composition.revision) {
10763 this.documentView.setDocument(this.composition.document);
10764 this.documentView.render();
10765 this.revision = this.composition.revision;
10766 }
10767 if (this.canSyncDocumentView() && !this.documentView.isSynced()) {
10768 var _this$delegate4, _this$delegate4$compo, _this$delegate5, _this$delegate5$compo;
10769 (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 || (_this$delegate4$compo = _this$delegate4.compositionControllerWillSyncDocumentView) === null || _this$delegate4$compo === void 0 || _this$delegate4$compo.call(_this$delegate4);
10770 this.documentView.sync();
10771 (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || (_this$delegate5$compo = _this$delegate5.compositionControllerDidSyncDocumentView) === null || _this$delegate5$compo === void 0 || _this$delegate5$compo.call(_this$delegate5);
10772 }
10773 return (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 || (_this$delegate6$compo = _this$delegate6.compositionControllerDidRender) === null || _this$delegate6$compo === void 0 ? void 0 : _this$delegate6$compo.call(_this$delegate6);
10774 }
10775 rerenderViewForObject(object) {
10776 this.invalidateViewForObject(object);
10777 return this.render();
10778 }
10779 invalidateViewForObject(object) {
10780 return this.documentView.invalidateViewForObject(object);
10781 }
10782 isViewCachingEnabled() {
10783 return this.documentView.isViewCachingEnabled();
10784 }
10785 enableViewCaching() {
10786 return this.documentView.enableViewCaching();
10787 }
10788 disableViewCaching() {
10789 return this.documentView.disableViewCaching();
10790 }
10791 refreshViewCache() {
10792 return this.documentView.garbageCollectCachedViews();
10793 }
10794
10795 // Attachment editor management
10796
10797 isEditingAttachment() {
10798 return !!this.attachmentEditor;
10799 }
10800 installAttachmentEditorForAttachment(attachment, options) {
10801 var _this$attachmentEdito;
10802 if (((_this$attachmentEdito = this.attachmentEditor) === null || _this$attachmentEdito === void 0 ? void 0 : _this$attachmentEdito.attachment) === attachment) return;
10803 const element = this.documentView.findElementForObject(attachment);
10804 if (!element) return;
10805 this.uninstallAttachmentEditor();
10806 const attachmentPiece = this.composition.document.getAttachmentPieceForAttachment(attachment);
10807 this.attachmentEditor = new AttachmentEditorController(attachmentPiece, element, this.element, options);
10808 this.attachmentEditor.delegate = this;
10809 }
10810 uninstallAttachmentEditor() {
10811 var _this$attachmentEdito2;
10812 return (_this$attachmentEdito2 = this.attachmentEditor) === null || _this$attachmentEdito2 === void 0 ? void 0 : _this$attachmentEdito2.uninstall();
10813 }
10814
10815 // Attachment controller delegate
10816
10817 didUninstallAttachmentEditor() {
10818 this.attachmentEditor = null;
10819 return this.render();
10820 }
10821 attachmentEditorDidRequestUpdatingAttributesForAttachment(attributes, attachment) {
10822 var _this$delegate7, _this$delegate7$compo;
10823 (_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 || (_this$delegate7$compo = _this$delegate7.compositionControllerWillUpdateAttachment) === null || _this$delegate7$compo === void 0 || _this$delegate7$compo.call(_this$delegate7, attachment);
10824 return this.composition.updateAttributesForAttachment(attributes, attachment);
10825 }
10826 attachmentEditorDidRequestRemovingAttributeForAttachment(attribute, attachment) {
10827 var _this$delegate8, _this$delegate8$compo;
10828 (_this$delegate8 = this.delegate) === null || _this$delegate8 === void 0 || (_this$delegate8$compo = _this$delegate8.compositionControllerWillUpdateAttachment) === null || _this$delegate8$compo === void 0 || _this$delegate8$compo.call(_this$delegate8, attachment);
10829 return this.composition.removeAttributeForAttachment(attribute, attachment);
10830 }
10831 attachmentEditorDidRequestRemovalOfAttachment(attachment) {
10832 var _this$delegate9, _this$delegate9$compo;
10833 return (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 || (_this$delegate9$compo = _this$delegate9.compositionControllerDidRequestRemovalOfAttachment) === null || _this$delegate9$compo === void 0 ? void 0 : _this$delegate9$compo.call(_this$delegate9, attachment);
10834 }
10835 attachmentEditorDidRequestDeselectingAttachment(attachment) {
10836 var _this$delegate10, _this$delegate10$comp;
10837 return (_this$delegate10 = this.delegate) === null || _this$delegate10 === void 0 || (_this$delegate10$comp = _this$delegate10.compositionControllerDidRequestDeselectingAttachment) === null || _this$delegate10$comp === void 0 ? void 0 : _this$delegate10$comp.call(_this$delegate10, attachment);
10838 }
10839
10840 // Private
10841
10842 canSyncDocumentView() {
10843 return !this.isEditingAttachment();
10844 }
10845 findAttachmentForElement(element) {
10846 return this.composition.document.getAttachmentById(parseInt(element.dataset.trixId, 10));
10847 }
10848 }
10849
10850 class Controller extends BasicObject {}
10851
10852 const mutableAttributeName = "data-trix-mutable";
10853 const mutableSelector = "[".concat(mutableAttributeName, "]");
10854 const options = {
10855 attributes: true,
10856 childList: true,
10857 characterData: true,
10858 characterDataOldValue: true,
10859 subtree: true
10860 };
10861 class MutationObserver extends BasicObject {
10862 constructor(element) {
10863 super(element);
10864 this.didMutate = this.didMutate.bind(this);
10865 this.element = element;
10866 this.observer = new window.MutationObserver(this.didMutate);
10867 this.start();
10868 }
10869 start() {
10870 this.reset();
10871 return this.observer.observe(this.element, options);
10872 }
10873 stop() {
10874 return this.observer.disconnect();
10875 }
10876 didMutate(mutations) {
10877 this.mutations.push(...Array.from(this.findSignificantMutations(mutations) || []));
10878 if (this.mutations.length) {
10879 var _this$delegate, _this$delegate$elemen;
10880 (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$elemen = _this$delegate.elementDidMutate) === null || _this$delegate$elemen === void 0 || _this$delegate$elemen.call(_this$delegate, this.getMutationSummary());
10881 return this.reset();
10882 }
10883 }
10884
10885 // Private
10886
10887 reset() {
10888 this.mutations = [];
10889 }
10890 findSignificantMutations(mutations) {
10891 return mutations.filter(mutation => {
10892 return this.mutationIsSignificant(mutation);
10893 });
10894 }
10895 mutationIsSignificant(mutation) {
10896 if (this.nodeIsMutable(mutation.target)) {
10897 return false;
10898 }
10899 for (const node of Array.from(this.nodesModifiedByMutation(mutation))) {
10900 if (this.nodeIsSignificant(node)) return true;
10901 }
10902 return false;
10903 }
10904 nodeIsSignificant(node) {
10905 return node !== this.element && !this.nodeIsMutable(node) && !nodeIsEmptyTextNode(node);
10906 }
10907 nodeIsMutable(node) {
10908 return findClosestElementFromNode(node, {
10909 matchingSelector: mutableSelector
10910 });
10911 }
10912 nodesModifiedByMutation(mutation) {
10913 const nodes = [];
10914 switch (mutation.type) {
10915 case "attributes":
10916 if (mutation.attributeName !== mutableAttributeName) {
10917 nodes.push(mutation.target);
10918 }
10919 break;
10920 case "characterData":
10921 // Changes to text nodes should consider the parent element
10922 nodes.push(mutation.target.parentNode);
10923 nodes.push(mutation.target);
10924 break;
10925 case "childList":
10926 // Consider each added or removed node
10927 nodes.push(...Array.from(mutation.addedNodes || []));
10928 nodes.push(...Array.from(mutation.removedNodes || []));
10929 break;
10930 }
10931 return nodes;
10932 }
10933 getMutationSummary() {
10934 return this.getTextMutationSummary();
10935 }
10936 getTextMutationSummary() {
10937 const {
10938 additions,
10939 deletions
10940 } = this.getTextChangesFromCharacterData();
10941 const textChanges = this.getTextChangesFromChildList();
10942 Array.from(textChanges.additions).forEach(addition => {
10943 if (!Array.from(additions).includes(addition)) {
10944 additions.push(addition);
10945 }
10946 });
10947 deletions.push(...Array.from(textChanges.deletions || []));
10948 const summary = {};
10949 const added = additions.join("");
10950 if (added) {
10951 summary.textAdded = added;
10952 }
10953 const deleted = deletions.join("");
10954 if (deleted) {
10955 summary.textDeleted = deleted;
10956 }
10957 return summary;
10958 }
10959 getMutationsByType(type) {
10960 return Array.from(this.mutations).filter(mutation => mutation.type === type);
10961 }
10962 getTextChangesFromChildList() {
10963 let textAdded, textRemoved;
10964 const addedNodes = [];
10965 const removedNodes = [];
10966 Array.from(this.getMutationsByType("childList")).forEach(mutation => {
10967 addedNodes.push(...Array.from(mutation.addedNodes || []));
10968 removedNodes.push(...Array.from(mutation.removedNodes || []));
10969 });
10970 const singleBlockCommentRemoved = addedNodes.length === 0 && removedNodes.length === 1 && nodeIsBlockStartComment(removedNodes[0]);
10971 if (singleBlockCommentRemoved) {
10972 textAdded = [];
10973 textRemoved = ["\n"];
10974 } else {
10975 textAdded = getTextForNodes(addedNodes);
10976 textRemoved = getTextForNodes(removedNodes);
10977 }
10978 const additions = textAdded.filter((text, index) => text !== textRemoved[index]).map(normalizeSpaces);
10979 const deletions = textRemoved.filter((text, index) => text !== textAdded[index]).map(normalizeSpaces);
10980 return {
10981 additions,
10982 deletions
10983 };
10984 }
10985 getTextChangesFromCharacterData() {
10986 let added, removed;
10987 const characterMutations = this.getMutationsByType("characterData");
10988 if (characterMutations.length) {
10989 const startMutation = characterMutations[0],
10990 endMutation = characterMutations[characterMutations.length - 1];
10991 const oldString = normalizeSpaces(startMutation.oldValue);
10992 const newString = normalizeSpaces(endMutation.target.data);
10993 const summarized = summarizeStringChange(oldString, newString);
10994 added = summarized.added;
10995 removed = summarized.removed;
10996 }
10997 return {
10998 additions: added ? [added] : [],
10999 deletions: removed ? [removed] : []
11000 };
11001 }
11002 }
11003 const getTextForNodes = function () {
11004 let nodes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
11005 const text = [];
11006 for (const node of Array.from(nodes)) {
11007 switch (node.nodeType) {
11008 case Node.TEXT_NODE:
11009 text.push(node.data);
11010 break;
11011 case Node.ELEMENT_NODE:
11012 if (tagName(node) === "br") {
11013 text.push("\n");
11014 } else {
11015 text.push(...Array.from(getTextForNodes(node.childNodes) || []));
11016 }
11017 break;
11018 }
11019 }
11020 return text;
11021 };
11022
11023 /* eslint-disable
11024 no-empty,
11025 */
11026 class FileVerificationOperation extends Operation {
11027 constructor(file) {
11028 super(...arguments);
11029 this.file = file;
11030 }
11031 perform(callback) {
11032 const reader = new FileReader();
11033 reader.onerror = () => callback(false);
11034 reader.onload = () => {
11035 reader.onerror = null;
11036 try {
11037 reader.abort();
11038 } catch (error) {}
11039 return callback(true, this.file);
11040 };
11041 return reader.readAsArrayBuffer(this.file);
11042 }
11043 }
11044
11045 // Each software keyboard on Android emits its own set of events and some of them can be buggy.
11046 // This class detects when some buggy events are being emitted and lets know the input controller
11047 // that they should be ignored.
11048 class FlakyAndroidKeyboardDetector {
11049 constructor(element) {
11050 this.element = element;
11051 }
11052 shouldIgnore(event) {
11053 if (!browser$1.samsungAndroid) return false;
11054 this.previousEvent = this.event;
11055 this.event = event;
11056 this.checkSamsungKeyboardBuggyModeStart();
11057 this.checkSamsungKeyboardBuggyModeEnd();
11058 return this.buggyMode;
11059 }
11060
11061 // private
11062
11063 // The Samsung keyboard on Android can enter a buggy state in which it emits a flurry of confused events that,
11064 // if processed, corrupts the editor. The buggy mode always starts with an insertText event, right after a
11065 // keydown event with for an "Unidentified" key, with the same text as the editor element, except for a few
11066 // extra whitespace, or exotic utf8, characters.
11067 checkSamsungKeyboardBuggyModeStart() {
11068 if (this.insertingLongTextAfterUnidentifiedChar() && differsInWhitespace(this.element.innerText, this.event.data)) {
11069 this.buggyMode = true;
11070 this.event.preventDefault();
11071 }
11072 }
11073
11074 // The flurry of buggy events are always insertText. If we see any other type, it means it's over.
11075 checkSamsungKeyboardBuggyModeEnd() {
11076 if (this.buggyMode && this.event.inputType !== "insertText") {
11077 this.buggyMode = false;
11078 }
11079 }
11080 insertingLongTextAfterUnidentifiedChar() {
11081 var _this$event$data;
11082 return this.isBeforeInputInsertText() && this.previousEventWasUnidentifiedKeydown() && ((_this$event$data = this.event.data) === null || _this$event$data === void 0 ? void 0 : _this$event$data.length) > 50;
11083 }
11084 isBeforeInputInsertText() {
11085 return this.event.type === "beforeinput" && this.event.inputType === "insertText";
11086 }
11087 previousEventWasUnidentifiedKeydown() {
11088 var _this$previousEvent, _this$previousEvent2;
11089 return ((_this$previousEvent = this.previousEvent) === null || _this$previousEvent === void 0 ? void 0 : _this$previousEvent.type) === "keydown" && ((_this$previousEvent2 = this.previousEvent) === null || _this$previousEvent2 === void 0 ? void 0 : _this$previousEvent2.key) === "Unidentified";
11090 }
11091 }
11092 const differsInWhitespace = (text1, text2) => {
11093 return normalize(text1) === normalize(text2);
11094 };
11095 const whiteSpaceNormalizerRegexp = new RegExp("(".concat(OBJECT_REPLACEMENT_CHARACTER, "|").concat(ZERO_WIDTH_SPACE, "|").concat(NON_BREAKING_SPACE, "|\\s)+"), "g");
11096 const normalize = text => text.replace(whiteSpaceNormalizerRegexp, " ").trim();
11097
11098 class InputController extends BasicObject {
11099 constructor(element) {
11100 super(...arguments);
11101 this.element = element;
11102 this.mutationObserver = new MutationObserver(this.element);
11103 this.mutationObserver.delegate = this;
11104 this.flakyKeyboardDetector = new FlakyAndroidKeyboardDetector(this.element);
11105 for (const eventName in this.constructor.events) {
11106 handleEvent(eventName, {
11107 onElement: this.element,
11108 withCallback: this.handlerFor(eventName)
11109 });
11110 }
11111 }
11112 elementDidMutate(mutationSummary) {}
11113 editorWillSyncDocumentView() {
11114 return this.mutationObserver.stop();
11115 }
11116 editorDidSyncDocumentView() {
11117 return this.mutationObserver.start();
11118 }
11119 requestRender() {
11120 var _this$delegate, _this$delegate$inputC;
11121 return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$inputC = _this$delegate.inputControllerDidRequestRender) === null || _this$delegate$inputC === void 0 ? void 0 : _this$delegate$inputC.call(_this$delegate);
11122 }
11123 requestReparse() {
11124 var _this$delegate2, _this$delegate2$input;
11125 (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || (_this$delegate2$input = _this$delegate2.inputControllerDidRequestReparse) === null || _this$delegate2$input === void 0 || _this$delegate2$input.call(_this$delegate2);
11126 return this.requestRender();
11127 }
11128 attachFiles(files) {
11129 const operations = Array.from(files).map(file => new FileVerificationOperation(file));
11130 return Promise.all(operations).then(files => {
11131 this.handleInput(function () {
11132 var _this$delegate3, _this$responder;
11133 (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 || _this$delegate3.inputControllerWillAttachFiles();
11134 (_this$responder = this.responder) === null || _this$responder === void 0 || _this$responder.insertFiles(files);
11135 return this.requestRender();
11136 });
11137 });
11138 }
11139
11140 // Private
11141
11142 handlerFor(eventName) {
11143 return event => {
11144 if (!event.defaultPrevented) {
11145 this.handleInput(() => {
11146 if (!innerElementIsActive(this.element)) {
11147 if (this.flakyKeyboardDetector.shouldIgnore(event)) return;
11148 this.eventName = eventName;
11149 this.constructor.events[eventName].call(this, event);
11150 }
11151 });
11152 }
11153 };
11154 }
11155 handleInput(callback) {
11156 try {
11157 var _this$delegate4;
11158 (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 || _this$delegate4.inputControllerWillHandleInput();
11159 callback.call(this);
11160 } finally {
11161 var _this$delegate5;
11162 (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || _this$delegate5.inputControllerDidHandleInput();
11163 }
11164 }
11165 createLinkHTML(href, text) {
11166 const link = document.createElement("a");
11167 link.href = href;
11168 link.textContent = text ? text : href;
11169 return link.outerHTML;
11170 }
11171 }
11172 _defineProperty(InputController, "events", {});
11173
11174 var _$codePointAt, _;
11175 const {
11176 browser,
11177 keyNames
11178 } = config;
11179 let pastedFileCount = 0;
11180 class Level0InputController extends InputController {
11181 constructor() {
11182 super(...arguments);
11183 this.resetInputSummary();
11184 }
11185 setInputSummary() {
11186 let summary = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
11187 this.inputSummary.eventName = this.eventName;
11188 for (const key in summary) {
11189 const value = summary[key];
11190 this.inputSummary[key] = value;
11191 }
11192 return this.inputSummary;
11193 }
11194 resetInputSummary() {
11195 this.inputSummary = {};
11196 }
11197 reset() {
11198 this.resetInputSummary();
11199 return selectionChangeObserver.reset();
11200 }
11201
11202 // Mutation observer delegate
11203
11204 elementDidMutate(mutationSummary) {
11205 if (this.isComposing()) {
11206 var _this$delegate, _this$delegate$inputC;
11207 return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$inputC = _this$delegate.inputControllerDidAllowUnhandledInput) === null || _this$delegate$inputC === void 0 ? void 0 : _this$delegate$inputC.call(_this$delegate);
11208 } else {
11209 return this.handleInput(function () {
11210 if (this.mutationIsSignificant(mutationSummary)) {
11211 if (this.mutationIsExpected(mutationSummary)) {
11212 this.requestRender();
11213 } else {
11214 this.requestReparse();
11215 }
11216 }
11217 return this.reset();
11218 });
11219 }
11220 }
11221 mutationIsExpected(_ref) {
11222 let {
11223 textAdded,
11224 textDeleted
11225 } = _ref;
11226 if (this.inputSummary.preferDocument) {
11227 return true;
11228 }
11229 const mutationAdditionMatchesSummary = textAdded != null ? textAdded === this.inputSummary.textAdded : !this.inputSummary.textAdded;
11230 const mutationDeletionMatchesSummary = textDeleted != null ? this.inputSummary.didDelete : !this.inputSummary.didDelete;
11231 const unexpectedNewlineAddition = ["\n", " \n"].includes(textAdded) && !mutationAdditionMatchesSummary;
11232 const unexpectedNewlineDeletion = textDeleted === "\n" && !mutationDeletionMatchesSummary;
11233 const singleUnexpectedNewline = unexpectedNewlineAddition && !unexpectedNewlineDeletion || unexpectedNewlineDeletion && !unexpectedNewlineAddition;
11234 if (singleUnexpectedNewline) {
11235 const range = this.getSelectedRange();
11236 if (range) {
11237 var _this$responder;
11238 const offset = unexpectedNewlineAddition ? textAdded.replace(/\n$/, "").length || -1 : (textAdded === null || textAdded === void 0 ? void 0 : textAdded.length) || 1;
11239 if ((_this$responder = this.responder) !== null && _this$responder !== void 0 && _this$responder.positionIsBlockBreak(range[1] + offset)) {
11240 return true;
11241 }
11242 }
11243 }
11244 return mutationAdditionMatchesSummary && mutationDeletionMatchesSummary;
11245 }
11246 mutationIsSignificant(mutationSummary) {
11247 var _this$compositionInpu;
11248 const textChanged = Object.keys(mutationSummary).length > 0;
11249 const composedEmptyString = ((_this$compositionInpu = this.compositionInput) === null || _this$compositionInpu === void 0 ? void 0 : _this$compositionInpu.getEndData()) === "";
11250 return textChanged || !composedEmptyString;
11251 }
11252
11253 // Private
11254
11255 getCompositionInput() {
11256 if (this.isComposing()) {
11257 return this.compositionInput;
11258 } else {
11259 this.compositionInput = new CompositionInput(this);
11260 }
11261 }
11262 isComposing() {
11263 return this.compositionInput && !this.compositionInput.isEnded();
11264 }
11265 deleteInDirection(direction, event) {
11266 var _this$responder2;
11267 if (((_this$responder2 = this.responder) === null || _this$responder2 === void 0 ? void 0 : _this$responder2.deleteInDirection(direction)) === false) {
11268 if (event) {
11269 event.preventDefault();
11270 return this.requestRender();
11271 }
11272 } else {
11273 return this.setInputSummary({
11274 didDelete: true
11275 });
11276 }
11277 }
11278 serializeSelectionToDataTransfer(dataTransfer) {
11279 var _this$responder3;
11280 if (!dataTransferIsWritable(dataTransfer)) return;
11281 const document = (_this$responder3 = this.responder) === null || _this$responder3 === void 0 ? void 0 : _this$responder3.getSelectedDocument().toSerializableDocument();
11282 dataTransfer.setData("application/x-trix-document", JSON.stringify(document));
11283 dataTransfer.setData("text/html", DocumentView.render(document).innerHTML);
11284 dataTransfer.setData("text/plain", document.toString().replace(/\n$/, ""));
11285 return true;
11286 }
11287 canAcceptDataTransfer(dataTransfer) {
11288 const types = {};
11289 Array.from((dataTransfer === null || dataTransfer === void 0 ? void 0 : dataTransfer.types) || []).forEach(type => {
11290 types[type] = true;
11291 });
11292 return types.Files || types["application/x-trix-document"] || types["text/html"] || types["text/plain"];
11293 }
11294 getPastedHTMLUsingHiddenElement(callback) {
11295 const selectedRange = this.getSelectedRange();
11296 const style = {
11297 position: "absolute",
11298 left: "".concat(window.pageXOffset, "px"),
11299 top: "".concat(window.pageYOffset, "px"),
11300 opacity: 0
11301 };
11302 const element = makeElement({
11303 style,
11304 tagName: "div",
11305 editable: true
11306 });
11307 document.body.appendChild(element);
11308 element.focus();
11309 return requestAnimationFrame(() => {
11310 const html = element.innerHTML;
11311 removeNode(element);
11312 this.setSelectedRange(selectedRange);
11313 return callback(html);
11314 });
11315 }
11316 }
11317 _defineProperty(Level0InputController, "events", {
11318 keydown(event) {
11319 if (!this.isComposing()) {
11320 this.resetInputSummary();
11321 }
11322 this.inputSummary.didInput = true;
11323 const keyName = keyNames[event.keyCode];
11324 if (keyName) {
11325 var _context2;
11326 let context = this.keys;
11327 ["ctrl", "alt", "shift", "meta"].forEach(modifier => {
11328 if (event["".concat(modifier, "Key")]) {
11329 var _context;
11330 if (modifier === "ctrl") {
11331 modifier = "control";
11332 }
11333 context = (_context = context) === null || _context === void 0 ? void 0 : _context[modifier];
11334 }
11335 });
11336 if (((_context2 = context) === null || _context2 === void 0 ? void 0 : _context2[keyName]) != null) {
11337 this.setInputSummary({
11338 keyName
11339 });
11340 selectionChangeObserver.reset();
11341 context[keyName].call(this, event);
11342 }
11343 }
11344 if (keyEventIsKeyboardCommand(event)) {
11345 const character = String.fromCharCode(event.keyCode).toLowerCase();
11346 if (character) {
11347 var _this$delegate3;
11348 const keys = ["alt", "shift"].map(modifier => {
11349 if (event["".concat(modifier, "Key")]) {
11350 return modifier;
11351 }
11352 }).filter(key => key);
11353 keys.push(character);
11354 if ((_this$delegate3 = this.delegate) !== null && _this$delegate3 !== void 0 && _this$delegate3.inputControllerDidReceiveKeyboardCommand(keys)) {
11355 event.preventDefault();
11356 }
11357 }
11358 }
11359 },
11360 keypress(event) {
11361 if (this.inputSummary.eventName != null) return;
11362 if (event.metaKey) return;
11363 if (event.ctrlKey && !event.altKey) return;
11364 const string = stringFromKeyEvent(event);
11365 if (string) {
11366 var _this$delegate4, _this$responder9;
11367 (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 || _this$delegate4.inputControllerWillPerformTyping();
11368 (_this$responder9 = this.responder) === null || _this$responder9 === void 0 || _this$responder9.insertString(string);
11369 return this.setInputSummary({
11370 textAdded: string,
11371 didDelete: this.selectionIsExpanded()
11372 });
11373 }
11374 },
11375 textInput(event) {
11376 // Handle autocapitalization
11377 const {
11378 data
11379 } = event;
11380 const {
11381 textAdded
11382 } = this.inputSummary;
11383 if (textAdded && textAdded !== data && textAdded.toUpperCase() === data) {
11384 var _this$responder10;
11385 const range = this.getSelectedRange();
11386 this.setSelectedRange([range[0], range[1] + textAdded.length]);
11387 (_this$responder10 = this.responder) === null || _this$responder10 === void 0 || _this$responder10.insertString(data);
11388 this.setInputSummary({
11389 textAdded: data
11390 });
11391 return this.setSelectedRange(range);
11392 }
11393 },
11394 dragenter(event) {
11395 event.preventDefault();
11396 },
11397 dragstart(event) {
11398 var _this$delegate5, _this$delegate5$input;
11399 this.serializeSelectionToDataTransfer(event.dataTransfer);
11400 this.draggedRange = this.getSelectedRange();
11401 return (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || (_this$delegate5$input = _this$delegate5.inputControllerDidStartDrag) === null || _this$delegate5$input === void 0 ? void 0 : _this$delegate5$input.call(_this$delegate5);
11402 },
11403 dragover(event) {
11404 if (this.draggedRange || this.canAcceptDataTransfer(event.dataTransfer)) {
11405 event.preventDefault();
11406 const draggingPoint = {
11407 x: event.clientX,
11408 y: event.clientY
11409 };
11410 if (!objectsAreEqual(draggingPoint, this.draggingPoint)) {
11411 var _this$delegate6, _this$delegate6$input;
11412 this.draggingPoint = draggingPoint;
11413 return (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 || (_this$delegate6$input = _this$delegate6.inputControllerDidReceiveDragOverPoint) === null || _this$delegate6$input === void 0 ? void 0 : _this$delegate6$input.call(_this$delegate6, this.draggingPoint);
11414 }
11415 }
11416 },
11417 dragend(event) {
11418 var _this$delegate7, _this$delegate7$input;
11419 (_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 || (_this$delegate7$input = _this$delegate7.inputControllerDidCancelDrag) === null || _this$delegate7$input === void 0 || _this$delegate7$input.call(_this$delegate7);
11420 this.draggedRange = null;
11421 this.draggingPoint = null;
11422 },
11423 drop(event) {
11424 var _event$dataTransfer, _this$responder11;
11425 event.preventDefault();
11426 const files = (_event$dataTransfer = event.dataTransfer) === null || _event$dataTransfer === void 0 ? void 0 : _event$dataTransfer.files;
11427 const documentJSON = event.dataTransfer.getData("application/x-trix-document");
11428 const point = {
11429 x: event.clientX,
11430 y: event.clientY
11431 };
11432 (_this$responder11 = this.responder) === null || _this$responder11 === void 0 || _this$responder11.setLocationRangeFromPointRange(point);
11433 if (files !== null && files !== void 0 && files.length) {
11434 this.attachFiles(files);
11435 } else if (this.draggedRange) {
11436 var _this$delegate8, _this$responder12;
11437 (_this$delegate8 = this.delegate) === null || _this$delegate8 === void 0 || _this$delegate8.inputControllerWillMoveText();
11438 (_this$responder12 = this.responder) === null || _this$responder12 === void 0 || _this$responder12.moveTextFromRange(this.draggedRange);
11439 this.draggedRange = null;
11440 this.requestRender();
11441 } else if (documentJSON) {
11442 var _this$responder13;
11443 const document = Document.fromJSONString(documentJSON);
11444 (_this$responder13 = this.responder) === null || _this$responder13 === void 0 || _this$responder13.insertDocument(document);
11445 this.requestRender();
11446 }
11447 this.draggedRange = null;
11448 this.draggingPoint = null;
11449 },
11450 cut(event) {
11451 var _this$responder14;
11452 if ((_this$responder14 = this.responder) !== null && _this$responder14 !== void 0 && _this$responder14.selectionIsExpanded()) {
11453 var _this$delegate9;
11454 if (this.serializeSelectionToDataTransfer(event.clipboardData)) {
11455 event.preventDefault();
11456 }
11457 (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 || _this$delegate9.inputControllerWillCutText();
11458 this.deleteInDirection("backward");
11459 if (event.defaultPrevented) {
11460 return this.requestRender();
11461 }
11462 }
11463 },
11464 copy(event) {
11465 var _this$responder15;
11466 if ((_this$responder15 = this.responder) !== null && _this$responder15 !== void 0 && _this$responder15.selectionIsExpanded()) {
11467 if (this.serializeSelectionToDataTransfer(event.clipboardData)) {
11468 event.preventDefault();
11469 }
11470 }
11471 },
11472 paste(event) {
11473 const clipboard = event.clipboardData || event.testClipboardData;
11474 const paste = {
11475 clipboard
11476 };
11477 if (!clipboard || pasteEventIsCrippledSafariHTMLPaste(event)) {
11478 this.getPastedHTMLUsingHiddenElement(html => {
11479 var _this$delegate10, _this$responder16, _this$delegate11;
11480 paste.type = "text/html";
11481 paste.html = html;
11482 (_this$delegate10 = this.delegate) === null || _this$delegate10 === void 0 || _this$delegate10.inputControllerWillPaste(paste);
11483 (_this$responder16 = this.responder) === null || _this$responder16 === void 0 || _this$responder16.insertHTML(paste.html);
11484 this.requestRender();
11485 return (_this$delegate11 = this.delegate) === null || _this$delegate11 === void 0 ? void 0 : _this$delegate11.inputControllerDidPaste(paste);
11486 });
11487 return;
11488 }
11489 const href = clipboard.getData("URL");
11490 const html = clipboard.getData("text/html");
11491 const name = clipboard.getData("public.url-name");
11492 if (href) {
11493 var _this$delegate12, _this$responder17, _this$delegate13;
11494 let string;
11495 paste.type = "text/html";
11496 if (name) {
11497 string = squishBreakableWhitespace(name).trim();
11498 } else {
11499 string = href;
11500 }
11501 paste.html = this.createLinkHTML(href, string);
11502 (_this$delegate12 = this.delegate) === null || _this$delegate12 === void 0 || _this$delegate12.inputControllerWillPaste(paste);
11503 this.setInputSummary({
11504 textAdded: string,
11505 didDelete: this.selectionIsExpanded()
11506 });
11507 (_this$responder17 = this.responder) === null || _this$responder17 === void 0 || _this$responder17.insertHTML(paste.html);
11508 this.requestRender();
11509 (_this$delegate13 = this.delegate) === null || _this$delegate13 === void 0 || _this$delegate13.inputControllerDidPaste(paste);
11510 } else if (dataTransferIsPlainText(clipboard)) {
11511 var _this$delegate14, _this$responder18, _this$delegate15;
11512 paste.type = "text/plain";
11513 paste.string = clipboard.getData("text/plain");
11514 (_this$delegate14 = this.delegate) === null || _this$delegate14 === void 0 || _this$delegate14.inputControllerWillPaste(paste);
11515 this.setInputSummary({
11516 textAdded: paste.string,
11517 didDelete: this.selectionIsExpanded()
11518 });
11519 (_this$responder18 = this.responder) === null || _this$responder18 === void 0 || _this$responder18.insertString(paste.string);
11520 this.requestRender();
11521 (_this$delegate15 = this.delegate) === null || _this$delegate15 === void 0 || _this$delegate15.inputControllerDidPaste(paste);
11522 } else if (html) {
11523 var _this$delegate16, _this$responder19, _this$delegate17;
11524 paste.type = "text/html";
11525 paste.html = html;
11526 (_this$delegate16 = this.delegate) === null || _this$delegate16 === void 0 || _this$delegate16.inputControllerWillPaste(paste);
11527 (_this$responder19 = this.responder) === null || _this$responder19 === void 0 || _this$responder19.insertHTML(paste.html);
11528 this.requestRender();
11529 (_this$delegate17 = this.delegate) === null || _this$delegate17 === void 0 || _this$delegate17.inputControllerDidPaste(paste);
11530 } else if (Array.from(clipboard.types).includes("Files")) {
11531 var _clipboard$items, _clipboard$items$getA;
11532 const file = (_clipboard$items = clipboard.items) === null || _clipboard$items === void 0 || (_clipboard$items = _clipboard$items[0]) === null || _clipboard$items === void 0 || (_clipboard$items$getA = _clipboard$items.getAsFile) === null || _clipboard$items$getA === void 0 ? void 0 : _clipboard$items$getA.call(_clipboard$items);
11533 if (file) {
11534 var _this$delegate18, _this$responder20, _this$delegate19;
11535 const extension = extensionForFile(file);
11536 if (!file.name && extension) {
11537 file.name = "pasted-file-".concat(++pastedFileCount, ".").concat(extension);
11538 }
11539 paste.type = "File";
11540 paste.file = file;
11541 (_this$delegate18 = this.delegate) === null || _this$delegate18 === void 0 || _this$delegate18.inputControllerWillAttachFiles();
11542 (_this$responder20 = this.responder) === null || _this$responder20 === void 0 || _this$responder20.insertFile(paste.file);
11543 this.requestRender();
11544 (_this$delegate19 = this.delegate) === null || _this$delegate19 === void 0 || _this$delegate19.inputControllerDidPaste(paste);
11545 }
11546 }
11547 event.preventDefault();
11548 },
11549 compositionstart(event) {
11550 return this.getCompositionInput().start(event.data);
11551 },
11552 compositionupdate(event) {
11553 return this.getCompositionInput().update(event.data);
11554 },
11555 compositionend(event) {
11556 return this.getCompositionInput().end(event.data);
11557 },
11558 beforeinput(event) {
11559 this.inputSummary.didInput = true;
11560 },
11561 input(event) {
11562 this.inputSummary.didInput = true;
11563 return event.stopPropagation();
11564 }
11565 });
11566 _defineProperty(Level0InputController, "keys", {
11567 backspace(event) {
11568 var _this$delegate20;
11569 (_this$delegate20 = this.delegate) === null || _this$delegate20 === void 0 || _this$delegate20.inputControllerWillPerformTyping();
11570 return this.deleteInDirection("backward", event);
11571 },
11572 delete(event) {
11573 var _this$delegate21;
11574 (_this$delegate21 = this.delegate) === null || _this$delegate21 === void 0 || _this$delegate21.inputControllerWillPerformTyping();
11575 return this.deleteInDirection("forward", event);
11576 },
11577 return(event) {
11578 var _this$delegate22, _this$responder21;
11579 this.setInputSummary({
11580 preferDocument: true
11581 });
11582 (_this$delegate22 = this.delegate) === null || _this$delegate22 === void 0 || _this$delegate22.inputControllerWillPerformTyping();
11583 return (_this$responder21 = this.responder) === null || _this$responder21 === void 0 ? void 0 : _this$responder21.insertLineBreak();
11584 },
11585 tab(event) {
11586 var _this$responder22;
11587 if ((_this$responder22 = this.responder) !== null && _this$responder22 !== void 0 && _this$responder22.canIncreaseNestingLevel()) {
11588 var _this$responder23;
11589 (_this$responder23 = this.responder) === null || _this$responder23 === void 0 || _this$responder23.increaseNestingLevel();
11590 this.requestRender();
11591 event.preventDefault();
11592 }
11593 },
11594 left(event) {
11595 if (this.selectionIsInCursorTarget()) {
11596 var _this$responder24;
11597 event.preventDefault();
11598 return (_this$responder24 = this.responder) === null || _this$responder24 === void 0 ? void 0 : _this$responder24.moveCursorInDirection("backward");
11599 }
11600 },
11601 right(event) {
11602 if (this.selectionIsInCursorTarget()) {
11603 var _this$responder25;
11604 event.preventDefault();
11605 return (_this$responder25 = this.responder) === null || _this$responder25 === void 0 ? void 0 : _this$responder25.moveCursorInDirection("forward");
11606 }
11607 },
11608 control: {
11609 d(event) {
11610 var _this$delegate23;
11611 (_this$delegate23 = this.delegate) === null || _this$delegate23 === void 0 || _this$delegate23.inputControllerWillPerformTyping();
11612 return this.deleteInDirection("forward", event);
11613 },
11614 h(event) {
11615 var _this$delegate24;
11616 (_this$delegate24 = this.delegate) === null || _this$delegate24 === void 0 || _this$delegate24.inputControllerWillPerformTyping();
11617 return this.deleteInDirection("backward", event);
11618 },
11619 o(event) {
11620 var _this$delegate25, _this$responder26;
11621 event.preventDefault();
11622 (_this$delegate25 = this.delegate) === null || _this$delegate25 === void 0 || _this$delegate25.inputControllerWillPerformTyping();
11623 (_this$responder26 = this.responder) === null || _this$responder26 === void 0 || _this$responder26.insertString("\n", {
11624 updatePosition: false
11625 });
11626 return this.requestRender();
11627 }
11628 },
11629 shift: {
11630 return(event) {
11631 var _this$delegate26, _this$responder27;
11632 (_this$delegate26 = this.delegate) === null || _this$delegate26 === void 0 || _this$delegate26.inputControllerWillPerformTyping();
11633 (_this$responder27 = this.responder) === null || _this$responder27 === void 0 || _this$responder27.insertString("\n");
11634 this.requestRender();
11635 event.preventDefault();
11636 },
11637 tab(event) {
11638 var _this$responder28;
11639 if ((_this$responder28 = this.responder) !== null && _this$responder28 !== void 0 && _this$responder28.canDecreaseNestingLevel()) {
11640 var _this$responder29;
11641 (_this$responder29 = this.responder) === null || _this$responder29 === void 0 || _this$responder29.decreaseNestingLevel();
11642 this.requestRender();
11643 event.preventDefault();
11644 }
11645 },
11646 left(event) {
11647 if (this.selectionIsInCursorTarget()) {
11648 event.preventDefault();
11649 return this.expandSelectionInDirection("backward");
11650 }
11651 },
11652 right(event) {
11653 if (this.selectionIsInCursorTarget()) {
11654 event.preventDefault();
11655 return this.expandSelectionInDirection("forward");
11656 }
11657 }
11658 },
11659 alt: {
11660 backspace(event) {
11661 var _this$delegate27;
11662 this.setInputSummary({
11663 preferDocument: false
11664 });
11665 return (_this$delegate27 = this.delegate) === null || _this$delegate27 === void 0 ? void 0 : _this$delegate27.inputControllerWillPerformTyping();
11666 }
11667 },
11668 meta: {
11669 backspace(event) {
11670 var _this$delegate28;
11671 this.setInputSummary({
11672 preferDocument: false
11673 });
11674 return (_this$delegate28 = this.delegate) === null || _this$delegate28 === void 0 ? void 0 : _this$delegate28.inputControllerWillPerformTyping();
11675 }
11676 }
11677 });
11678 Level0InputController.proxyMethod("responder?.getSelectedRange");
11679 Level0InputController.proxyMethod("responder?.setSelectedRange");
11680 Level0InputController.proxyMethod("responder?.expandSelectionInDirection");
11681 Level0InputController.proxyMethod("responder?.selectionIsInCursorTarget");
11682 Level0InputController.proxyMethod("responder?.selectionIsExpanded");
11683 const extensionForFile = file => {
11684 var _file$type;
11685 return (_file$type = file.type) === null || _file$type === void 0 || (_file$type = _file$type.match(/\/(\w+)$/)) === null || _file$type === void 0 ? void 0 : _file$type[1];
11686 };
11687 const hasStringCodePointAt = !!((_$codePointAt = (_ = " ").codePointAt) !== null && _$codePointAt !== void 0 && _$codePointAt.call(_, 0));
11688 const stringFromKeyEvent = function (event) {
11689 if (event.key && hasStringCodePointAt && event.key.codePointAt(0) === event.keyCode) {
11690 return event.key;
11691 } else {
11692 let code;
11693 if (event.which === null) {
11694 code = event.keyCode;
11695 } else if (event.which !== 0 && event.charCode !== 0) {
11696 code = event.charCode;
11697 }
11698 if (code != null && keyNames[code] !== "escape") {
11699 return UTF16String.fromCodepoints([code]).toString();
11700 }
11701 }
11702 };
11703 const pasteEventIsCrippledSafariHTMLPaste = function (event) {
11704 const paste = event.clipboardData;
11705 if (paste) {
11706 if (paste.types.includes("text/html")) {
11707 // Answer is yes if there's any possibility of Paste and Match Style in Safari,
11708 // which is nearly impossible to detect confidently: https://bugs.webkit.org/show_bug.cgi?id=174165
11709 for (const type of paste.types) {
11710 const hasPasteboardFlavor = /^CorePasteboardFlavorType/.test(type);
11711 const hasReadableDynamicData = /^dyn\./.test(type) && paste.getData(type);
11712 const mightBePasteAndMatchStyle = hasPasteboardFlavor || hasReadableDynamicData;
11713 if (mightBePasteAndMatchStyle) {
11714 return true;
11715 }
11716 }
11717 return false;
11718 } else {
11719 const isExternalHTMLPaste = paste.types.includes("com.apple.webarchive");
11720 const isExternalRichTextPaste = paste.types.includes("com.apple.flat-rtfd");
11721 return isExternalHTMLPaste || isExternalRichTextPaste;
11722 }
11723 }
11724 };
11725 class CompositionInput extends BasicObject {
11726 constructor(inputController) {
11727 super(...arguments);
11728 this.inputController = inputController;
11729 this.responder = this.inputController.responder;
11730 this.delegate = this.inputController.delegate;
11731 this.inputSummary = this.inputController.inputSummary;
11732 this.data = {};
11733 }
11734 start(data) {
11735 this.data.start = data;
11736 if (this.isSignificant()) {
11737 var _this$responder5;
11738 if (this.inputSummary.eventName === "keypress" && this.inputSummary.textAdded) {
11739 var _this$responder4;
11740 (_this$responder4 = this.responder) === null || _this$responder4 === void 0 || _this$responder4.deleteInDirection("left");
11741 }
11742 if (!this.selectionIsExpanded()) {
11743 this.insertPlaceholder();
11744 this.requestRender();
11745 }
11746 this.range = (_this$responder5 = this.responder) === null || _this$responder5 === void 0 ? void 0 : _this$responder5.getSelectedRange();
11747 }
11748 }
11749 update(data) {
11750 this.data.update = data;
11751 if (this.isSignificant()) {
11752 const range = this.selectPlaceholder();
11753 if (range) {
11754 this.forgetPlaceholder();
11755 this.range = range;
11756 }
11757 }
11758 }
11759 end(data) {
11760 this.data.end = data;
11761 if (this.isSignificant()) {
11762 this.forgetPlaceholder();
11763 if (this.canApplyToDocument()) {
11764 var _this$delegate2, _this$responder6, _this$responder7, _this$responder8;
11765 this.setInputSummary({
11766 preferDocument: true,
11767 didInput: false
11768 });
11769 (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || _this$delegate2.inputControllerWillPerformTyping();
11770 (_this$responder6 = this.responder) === null || _this$responder6 === void 0 || _this$responder6.setSelectedRange(this.range);
11771 (_this$responder7 = this.responder) === null || _this$responder7 === void 0 || _this$responder7.insertString(this.data.end);
11772 return (_this$responder8 = this.responder) === null || _this$responder8 === void 0 ? void 0 : _this$responder8.setSelectedRange(this.range[0] + this.data.end.length);
11773 } else if (this.data.start != null || this.data.update != null) {
11774 this.requestReparse();
11775 return this.inputController.reset();
11776 }
11777 } else {
11778 return this.inputController.reset();
11779 }
11780 }
11781 getEndData() {
11782 return this.data.end;
11783 }
11784 isEnded() {
11785 return this.getEndData() != null;
11786 }
11787 isSignificant() {
11788 if (browser.composesExistingText) {
11789 return this.inputSummary.didInput;
11790 } else {
11791 return true;
11792 }
11793 }
11794
11795 // Private
11796
11797 canApplyToDocument() {
11798 var _this$data$start, _this$data$end;
11799 return ((_this$data$start = this.data.start) === null || _this$data$start === void 0 ? void 0 : _this$data$start.length) === 0 && ((_this$data$end = this.data.end) === null || _this$data$end === void 0 ? void 0 : _this$data$end.length) > 0 && this.range;
11800 }
11801 }
11802 CompositionInput.proxyMethod("inputController.setInputSummary");
11803 CompositionInput.proxyMethod("inputController.requestRender");
11804 CompositionInput.proxyMethod("inputController.requestReparse");
11805 CompositionInput.proxyMethod("responder?.selectionIsExpanded");
11806 CompositionInput.proxyMethod("responder?.insertPlaceholder");
11807 CompositionInput.proxyMethod("responder?.selectPlaceholder");
11808 CompositionInput.proxyMethod("responder?.forgetPlaceholder");
11809
11810 class Level2InputController extends InputController {
11811 constructor() {
11812 super(...arguments);
11813 this.render = this.render.bind(this);
11814 }
11815 elementDidMutate() {
11816 if (this.scheduledRender) {
11817 if (this.composing) {
11818 var _this$delegate, _this$delegate$inputC;
11819 return (_this$delegate = this.delegate) === null || _this$delegate === void 0 || (_this$delegate$inputC = _this$delegate.inputControllerDidAllowUnhandledInput) === null || _this$delegate$inputC === void 0 ? void 0 : _this$delegate$inputC.call(_this$delegate);
11820 }
11821 } else {
11822 return this.reparse();
11823 }
11824 }
11825 scheduleRender() {
11826 return this.scheduledRender ? this.scheduledRender : this.scheduledRender = requestAnimationFrame(this.render);
11827 }
11828 render() {
11829 var _this$afterRender;
11830 cancelAnimationFrame(this.scheduledRender);
11831 this.scheduledRender = null;
11832 if (!this.composing) {
11833 var _this$delegate2;
11834 (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 || _this$delegate2.render();
11835 }
11836 (_this$afterRender = this.afterRender) === null || _this$afterRender === void 0 || _this$afterRender.call(this);
11837 this.afterRender = null;
11838 }
11839 reparse() {
11840 var _this$delegate3;
11841 return (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 ? void 0 : _this$delegate3.reparse();
11842 }
11843
11844 // Responder helpers
11845
11846 insertString() {
11847 var _this$delegate4;
11848 let string = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
11849 let options = arguments.length > 1 ? arguments[1] : undefined;
11850 (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 || _this$delegate4.inputControllerWillPerformTyping();
11851 return this.withTargetDOMRange(function () {
11852 var _this$responder;
11853 return (_this$responder = this.responder) === null || _this$responder === void 0 ? void 0 : _this$responder.insertString(string, options);
11854 });
11855 }
11856 toggleAttributeIfSupported(attributeName) {
11857 if (getAllAttributeNames().includes(attributeName)) {
11858 var _this$delegate5;
11859 (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || _this$delegate5.inputControllerWillPerformFormatting(attributeName);
11860 return this.withTargetDOMRange(function () {
11861 var _this$responder2;
11862 return (_this$responder2 = this.responder) === null || _this$responder2 === void 0 ? void 0 : _this$responder2.toggleCurrentAttribute(attributeName);
11863 });
11864 }
11865 }
11866 activateAttributeIfSupported(attributeName, value) {
11867 if (getAllAttributeNames().includes(attributeName)) {
11868 var _this$delegate6;
11869 (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 || _this$delegate6.inputControllerWillPerformFormatting(attributeName);
11870 return this.withTargetDOMRange(function () {
11871 var _this$responder3;
11872 return (_this$responder3 = this.responder) === null || _this$responder3 === void 0 ? void 0 : _this$responder3.setCurrentAttribute(attributeName, value);
11873 });
11874 }
11875 }
11876 deleteInDirection(direction) {
11877 let {
11878 recordUndoEntry
11879 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
11880 recordUndoEntry: true
11881 };
11882 if (recordUndoEntry) {
11883 var _this$delegate7;
11884 (_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 || _this$delegate7.inputControllerWillPerformTyping();
11885 }
11886 const perform = () => {
11887 var _this$responder4;
11888 return (_this$responder4 = this.responder) === null || _this$responder4 === void 0 ? void 0 : _this$responder4.deleteInDirection(direction);
11889 };
11890 const domRange = this.getTargetDOMRange({
11891 minLength: this.composing ? 1 : 2
11892 });
11893 if (domRange) {
11894 return this.withTargetDOMRange(domRange, perform);
11895 } else {
11896 return perform();
11897 }
11898 }
11899
11900 // Selection helpers
11901
11902 withTargetDOMRange(domRange, fn) {
11903 if (typeof domRange === "function") {
11904 fn = domRange;
11905 domRange = this.getTargetDOMRange();
11906 }
11907 if (domRange) {
11908 var _this$responder5;
11909 return (_this$responder5 = this.responder) === null || _this$responder5 === void 0 ? void 0 : _this$responder5.withTargetDOMRange(domRange, fn.bind(this));
11910 } else {
11911 selectionChangeObserver.reset();
11912 return fn.call(this);
11913 }
11914 }
11915 getTargetDOMRange() {
11916 var _this$event$getTarget, _this$event;
11917 let {
11918 minLength
11919 } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
11920 minLength: 0
11921 };
11922 const targetRanges = (_this$event$getTarget = (_this$event = this.event).getTargetRanges) === null || _this$event$getTarget === void 0 ? void 0 : _this$event$getTarget.call(_this$event);
11923 if (targetRanges) {
11924 if (targetRanges.length) {
11925 const domRange = staticRangeToRange(targetRanges[0]);
11926 if (minLength === 0 || domRange.toString().length >= minLength) {
11927 return domRange;
11928 }
11929 }
11930 }
11931 }
11932 withEvent(event, fn) {
11933 let result;
11934 this.event = event;
11935 try {
11936 result = fn.call(this);
11937 } finally {
11938 this.event = null;
11939 }
11940 return result;
11941 }
11942 }
11943 _defineProperty(Level2InputController, "events", {
11944 keydown(event) {
11945 if (keyEventIsKeyboardCommand(event)) {
11946 var _this$delegate8;
11947 const command = keyboardCommandFromKeyEvent(event);
11948 if ((_this$delegate8 = this.delegate) !== null && _this$delegate8 !== void 0 && _this$delegate8.inputControllerDidReceiveKeyboardCommand(command)) {
11949 event.preventDefault();
11950 }
11951 } else {
11952 let name = event.key;
11953 if (event.altKey) {
11954 name += "+Alt";
11955 }
11956 if (event.shiftKey) {
11957 name += "+Shift";
11958 }
11959 const handler = this.constructor.keys[name];
11960 if (handler) {
11961 return this.withEvent(event, handler);
11962 }
11963 }
11964 },
11965 // Handle paste event to work around beforeinput.insertFromPaste browser bugs.
11966 // Safe to remove each condition once fixed upstream.
11967 paste(event) {
11968 var _event$clipboardData;
11969 // https://bugs.webkit.org/show_bug.cgi?id=194921
11970 let paste;
11971 const href = (_event$clipboardData = event.clipboardData) === null || _event$clipboardData === void 0 ? void 0 : _event$clipboardData.getData("URL");
11972 if (pasteEventHasFilesOnly(event)) {
11973 event.preventDefault();
11974 return this.attachFiles(event.clipboardData.files);
11975
11976 // https://bugs.chromium.org/p/chromium/issues/detail?id=934448
11977 } else if (pasteEventHasPlainTextOnly(event)) {
11978 var _this$delegate9, _this$responder6, _this$delegate10;
11979 event.preventDefault();
11980 paste = {
11981 type: "text/plain",
11982 string: event.clipboardData.getData("text/plain")
11983 };
11984 (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 || _this$delegate9.inputControllerWillPaste(paste);
11985 (_this$responder6 = this.responder) === null || _this$responder6 === void 0 || _this$responder6.insertString(paste.string);
11986 this.render();
11987 return (_this$delegate10 = this.delegate) === null || _this$delegate10 === void 0 ? void 0 : _this$delegate10.inputControllerDidPaste(paste);
11988
11989 // https://bugs.webkit.org/show_bug.cgi?id=196702
11990 } else if (href) {
11991 var _this$delegate11, _this$responder7, _this$delegate12;
11992 event.preventDefault();
11993 paste = {
11994 type: "text/html",
11995 html: this.createLinkHTML(href)
11996 };
11997 (_this$delegate11 = this.delegate) === null || _this$delegate11 === void 0 || _this$delegate11.inputControllerWillPaste(paste);
11998 (_this$responder7 = this.responder) === null || _this$responder7 === void 0 || _this$responder7.insertHTML(paste.html);
11999 this.render();
12000 return (_this$delegate12 = this.delegate) === null || _this$delegate12 === void 0 ? void 0 : _this$delegate12.inputControllerDidPaste(paste);
12001 }
12002 },
12003 beforeinput(event) {
12004 const handler = this.constructor.inputTypes[event.inputType];
12005 const immmediateRender = shouldRenderInmmediatelyToDealWithIOSDictation(event);
12006 if (handler) {
12007 this.withEvent(event, handler);
12008 if (!immmediateRender) {
12009 this.scheduleRender();
12010 }
12011 }
12012 if (immmediateRender) {
12013 this.render();
12014 }
12015 },
12016 input(event) {
12017 selectionChangeObserver.reset();
12018 },
12019 dragstart(event) {
12020 var _this$responder8;
12021 if ((_this$responder8 = this.responder) !== null && _this$responder8 !== void 0 && _this$responder8.selectionContainsAttachments()) {
12022 var _this$responder9;
12023 event.dataTransfer.setData("application/x-trix-dragging", true);
12024 this.dragging = {
12025 range: (_this$responder9 = this.responder) === null || _this$responder9 === void 0 ? void 0 : _this$responder9.getSelectedRange(),
12026 point: pointFromEvent(event)
12027 };
12028 }
12029 },
12030 dragenter(event) {
12031 if (dragEventHasFiles(event)) {
12032 event.preventDefault();
12033 }
12034 },
12035 dragover(event) {
12036 if (this.dragging) {
12037 event.preventDefault();
12038 const point = pointFromEvent(event);
12039 if (!objectsAreEqual(point, this.dragging.point)) {
12040 var _this$responder10;
12041 this.dragging.point = point;
12042 return (_this$responder10 = this.responder) === null || _this$responder10 === void 0 ? void 0 : _this$responder10.setLocationRangeFromPointRange(point);
12043 }
12044 } else if (dragEventHasFiles(event)) {
12045 event.preventDefault();
12046 }
12047 },
12048 drop(event) {
12049 if (this.dragging) {
12050 var _this$delegate13, _this$responder11;
12051 event.preventDefault();
12052 (_this$delegate13 = this.delegate) === null || _this$delegate13 === void 0 || _this$delegate13.inputControllerWillMoveText();
12053 (_this$responder11 = this.responder) === null || _this$responder11 === void 0 || _this$responder11.moveTextFromRange(this.dragging.range);
12054 this.dragging = null;
12055 return this.scheduleRender();
12056 } else if (dragEventHasFiles(event)) {
12057 var _this$responder12;
12058 event.preventDefault();
12059 const point = pointFromEvent(event);
12060 (_this$responder12 = this.responder) === null || _this$responder12 === void 0 || _this$responder12.setLocationRangeFromPointRange(point);
12061 return this.attachFiles(event.dataTransfer.files);
12062 }
12063 },
12064 dragend() {
12065 if (this.dragging) {
12066 var _this$responder13;
12067 (_this$responder13 = this.responder) === null || _this$responder13 === void 0 || _this$responder13.setSelectedRange(this.dragging.range);
12068 this.dragging = null;
12069 }
12070 },
12071 compositionend(event) {
12072 if (this.composing) {
12073 this.composing = false;
12074 if (!browser$1.recentAndroid) this.scheduleRender();
12075 }
12076 }
12077 });
12078 _defineProperty(Level2InputController, "keys", {
12079 ArrowLeft() {
12080 var _this$responder14;
12081 if ((_this$responder14 = this.responder) !== null && _this$responder14 !== void 0 && _this$responder14.shouldManageMovingCursorInDirection("backward")) {
12082 var _this$responder15;
12083 this.event.preventDefault();
12084 return (_this$responder15 = this.responder) === null || _this$responder15 === void 0 ? void 0 : _this$responder15.moveCursorInDirection("backward");
12085 }
12086 },
12087 ArrowRight() {
12088 var _this$responder16;
12089 if ((_this$responder16 = this.responder) !== null && _this$responder16 !== void 0 && _this$responder16.shouldManageMovingCursorInDirection("forward")) {
12090 var _this$responder17;
12091 this.event.preventDefault();
12092 return (_this$responder17 = this.responder) === null || _this$responder17 === void 0 ? void 0 : _this$responder17.moveCursorInDirection("forward");
12093 }
12094 },
12095 Backspace() {
12096 var _this$responder18;
12097 if ((_this$responder18 = this.responder) !== null && _this$responder18 !== void 0 && _this$responder18.shouldManageDeletingInDirection("backward")) {
12098 var _this$delegate14, _this$responder19;
12099 this.event.preventDefault();
12100 (_this$delegate14 = this.delegate) === null || _this$delegate14 === void 0 || _this$delegate14.inputControllerWillPerformTyping();
12101 (_this$responder19 = this.responder) === null || _this$responder19 === void 0 || _this$responder19.deleteInDirection("backward");
12102 return this.render();
12103 }
12104 },
12105 Tab() {
12106 var _this$responder20;
12107 if ((_this$responder20 = this.responder) !== null && _this$responder20 !== void 0 && _this$responder20.canIncreaseNestingLevel()) {
12108 var _this$responder21;
12109 this.event.preventDefault();
12110 (_this$responder21 = this.responder) === null || _this$responder21 === void 0 || _this$responder21.increaseNestingLevel();
12111 return this.render();
12112 }
12113 },
12114 "Tab+Shift"() {
12115 var _this$responder22;
12116 if ((_this$responder22 = this.responder) !== null && _this$responder22 !== void 0 && _this$responder22.canDecreaseNestingLevel()) {
12117 var _this$responder23;
12118 this.event.preventDefault();
12119 (_this$responder23 = this.responder) === null || _this$responder23 === void 0 || _this$responder23.decreaseNestingLevel();
12120 return this.render();
12121 }
12122 }
12123 });
12124 _defineProperty(Level2InputController, "inputTypes", {
12125 deleteByComposition() {
12126 return this.deleteInDirection("backward", {
12127 recordUndoEntry: false
12128 });
12129 },
12130 deleteByCut() {
12131 return this.deleteInDirection("backward");
12132 },
12133 deleteByDrag() {
12134 this.event.preventDefault();
12135 return this.withTargetDOMRange(function () {
12136 var _this$responder24;
12137 this.deleteByDragRange = (_this$responder24 = this.responder) === null || _this$responder24 === void 0 ? void 0 : _this$responder24.getSelectedRange();
12138 });
12139 },
12140 deleteCompositionText() {
12141 return this.deleteInDirection("backward", {
12142 recordUndoEntry: false
12143 });
12144 },
12145 deleteContent() {
12146 return this.deleteInDirection("backward");
12147 },
12148 deleteContentBackward() {
12149 return this.deleteInDirection("backward");
12150 },
12151 deleteContentForward() {
12152 return this.deleteInDirection("forward");
12153 },
12154 deleteEntireSoftLine() {
12155 return this.deleteInDirection("forward");
12156 },
12157 deleteHardLineBackward() {
12158 return this.deleteInDirection("backward");
12159 },
12160 deleteHardLineForward() {
12161 return this.deleteInDirection("forward");
12162 },
12163 deleteSoftLineBackward() {
12164 return this.deleteInDirection("backward");
12165 },
12166 deleteSoftLineForward() {
12167 return this.deleteInDirection("forward");
12168 },
12169 deleteWordBackward() {
12170 return this.deleteInDirection("backward");
12171 },
12172 deleteWordForward() {
12173 return this.deleteInDirection("forward");
12174 },
12175 formatBackColor() {
12176 return this.activateAttributeIfSupported("backgroundColor", this.event.data);
12177 },
12178 formatBold() {
12179 return this.toggleAttributeIfSupported("bold");
12180 },
12181 formatFontColor() {
12182 return this.activateAttributeIfSupported("color", this.event.data);
12183 },
12184 formatFontName() {
12185 return this.activateAttributeIfSupported("font", this.event.data);
12186 },
12187 formatIndent() {
12188 var _this$responder25;
12189 if ((_this$responder25 = this.responder) !== null && _this$responder25 !== void 0 && _this$responder25.canIncreaseNestingLevel()) {
12190 return this.withTargetDOMRange(function () {
12191 var _this$responder26;
12192 return (_this$responder26 = this.responder) === null || _this$responder26 === void 0 ? void 0 : _this$responder26.increaseNestingLevel();
12193 });
12194 }
12195 },
12196 formatItalic() {
12197 return this.toggleAttributeIfSupported("italic");
12198 },
12199 formatJustifyCenter() {
12200 return this.toggleAttributeIfSupported("justifyCenter");
12201 },
12202 formatJustifyFull() {
12203 return this.toggleAttributeIfSupported("justifyFull");
12204 },
12205 formatJustifyLeft() {
12206 return this.toggleAttributeIfSupported("justifyLeft");
12207 },
12208 formatJustifyRight() {
12209 return this.toggleAttributeIfSupported("justifyRight");
12210 },
12211 formatOutdent() {
12212 var _this$responder27;
12213 if ((_this$responder27 = this.responder) !== null && _this$responder27 !== void 0 && _this$responder27.canDecreaseNestingLevel()) {
12214 return this.withTargetDOMRange(function () {
12215 var _this$responder28;
12216 return (_this$responder28 = this.responder) === null || _this$responder28 === void 0 ? void 0 : _this$responder28.decreaseNestingLevel();
12217 });
12218 }
12219 },
12220 formatRemove() {
12221 this.withTargetDOMRange(function () {
12222 for (const attributeName in (_this$responder29 = this.responder) === null || _this$responder29 === void 0 ? void 0 : _this$responder29.getCurrentAttributes()) {
12223 var _this$responder29, _this$responder30;
12224 (_this$responder30 = this.responder) === null || _this$responder30 === void 0 || _this$responder30.removeCurrentAttribute(attributeName);
12225 }
12226 });
12227 },
12228 formatSetBlockTextDirection() {
12229 return this.activateAttributeIfSupported("blockDir", this.event.data);
12230 },
12231 formatSetInlineTextDirection() {
12232 return this.activateAttributeIfSupported("textDir", this.event.data);
12233 },
12234 formatStrikeThrough() {
12235 return this.toggleAttributeIfSupported("strike");
12236 },
12237 formatSubscript() {
12238 return this.toggleAttributeIfSupported("sub");
12239 },
12240 formatSuperscript() {
12241 return this.toggleAttributeIfSupported("sup");
12242 },
12243 formatUnderline() {
12244 return this.toggleAttributeIfSupported("underline");
12245 },
12246 historyRedo() {
12247 var _this$delegate15;
12248 return (_this$delegate15 = this.delegate) === null || _this$delegate15 === void 0 ? void 0 : _this$delegate15.inputControllerWillPerformRedo();
12249 },
12250 historyUndo() {
12251 var _this$delegate16;
12252 return (_this$delegate16 = this.delegate) === null || _this$delegate16 === void 0 ? void 0 : _this$delegate16.inputControllerWillPerformUndo();
12253 },
12254 insertCompositionText() {
12255 this.composing = true;
12256 return this.insertString(this.event.data);
12257 },
12258 insertFromComposition() {
12259 this.composing = false;
12260 return this.insertString(this.event.data);
12261 },
12262 insertFromDrop() {
12263 const range = this.deleteByDragRange;
12264 if (range) {
12265 var _this$delegate17;
12266 this.deleteByDragRange = null;
12267 (_this$delegate17 = this.delegate) === null || _this$delegate17 === void 0 || _this$delegate17.inputControllerWillMoveText();
12268 return this.withTargetDOMRange(function () {
12269 var _this$responder31;
12270 return (_this$responder31 = this.responder) === null || _this$responder31 === void 0 ? void 0 : _this$responder31.moveTextFromRange(range);
12271 });
12272 }
12273 },
12274 insertFromPaste() {
12275 const {
12276 dataTransfer
12277 } = this.event;
12278 const paste = {
12279 dataTransfer
12280 };
12281 const href = dataTransfer.getData("URL");
12282 const html = dataTransfer.getData("text/html");
12283 if (href) {
12284 var _this$delegate18;
12285 let string;
12286 this.event.preventDefault();
12287 paste.type = "text/html";
12288 const name = dataTransfer.getData("public.url-name");
12289 if (name) {
12290 string = squishBreakableWhitespace(name).trim();
12291 } else {
12292 string = href;
12293 }
12294 paste.html = this.createLinkHTML(href, string);
12295 (_this$delegate18 = this.delegate) === null || _this$delegate18 === void 0 || _this$delegate18.inputControllerWillPaste(paste);
12296 this.withTargetDOMRange(function () {
12297 var _this$responder32;
12298 return (_this$responder32 = this.responder) === null || _this$responder32 === void 0 ? void 0 : _this$responder32.insertHTML(paste.html);
12299 });
12300 this.afterRender = () => {
12301 var _this$delegate19;
12302 return (_this$delegate19 = this.delegate) === null || _this$delegate19 === void 0 ? void 0 : _this$delegate19.inputControllerDidPaste(paste);
12303 };
12304 } else if (dataTransferIsPlainText(dataTransfer)) {
12305 var _this$delegate20;
12306 paste.type = "text/plain";
12307 paste.string = dataTransfer.getData("text/plain");
12308 (_this$delegate20 = this.delegate) === null || _this$delegate20 === void 0 || _this$delegate20.inputControllerWillPaste(paste);
12309 this.withTargetDOMRange(function () {
12310 var _this$responder33;
12311 return (_this$responder33 = this.responder) === null || _this$responder33 === void 0 ? void 0 : _this$responder33.insertString(paste.string);
12312 });
12313 this.afterRender = () => {
12314 var _this$delegate21;
12315 return (_this$delegate21 = this.delegate) === null || _this$delegate21 === void 0 ? void 0 : _this$delegate21.inputControllerDidPaste(paste);
12316 };
12317 } else if (processableFilePaste(this.event)) {
12318 var _this$delegate22;
12319 paste.type = "File";
12320 paste.file = dataTransfer.files[0];
12321 (_this$delegate22 = this.delegate) === null || _this$delegate22 === void 0 || _this$delegate22.inputControllerWillPaste(paste);
12322 this.withTargetDOMRange(function () {
12323 var _this$responder34;
12324 return (_this$responder34 = this.responder) === null || _this$responder34 === void 0 ? void 0 : _this$responder34.insertFile(paste.file);
12325 });
12326 this.afterRender = () => {
12327 var _this$delegate23;
12328 return (_this$delegate23 = this.delegate) === null || _this$delegate23 === void 0 ? void 0 : _this$delegate23.inputControllerDidPaste(paste);
12329 };
12330 } else if (html) {
12331 var _this$delegate24;
12332 this.event.preventDefault();
12333 paste.type = "text/html";
12334 paste.html = html;
12335 (_this$delegate24 = this.delegate) === null || _this$delegate24 === void 0 || _this$delegate24.inputControllerWillPaste(paste);
12336 this.withTargetDOMRange(function () {
12337 var _this$responder35;
12338 return (_this$responder35 = this.responder) === null || _this$responder35 === void 0 ? void 0 : _this$responder35.insertHTML(paste.html);
12339 });
12340 this.afterRender = () => {
12341 var _this$delegate25;
12342 return (_this$delegate25 = this.delegate) === null || _this$delegate25 === void 0 ? void 0 : _this$delegate25.inputControllerDidPaste(paste);
12343 };
12344 }
12345 },
12346 insertFromYank() {
12347 return this.insertString(this.event.data);
12348 },
12349 insertLineBreak() {
12350 return this.insertString("\n");
12351 },
12352 insertLink() {
12353 return this.activateAttributeIfSupported("href", this.event.data);
12354 },
12355 insertOrderedList() {
12356 return this.toggleAttributeIfSupported("number");
12357 },
12358 insertParagraph() {
12359 var _this$delegate26;
12360 (_this$delegate26 = this.delegate) === null || _this$delegate26 === void 0 || _this$delegate26.inputControllerWillPerformTyping();
12361 return this.withTargetDOMRange(function () {
12362 var _this$responder36;
12363 return (_this$responder36 = this.responder) === null || _this$responder36 === void 0 ? void 0 : _this$responder36.insertLineBreak();
12364 });
12365 },
12366 insertReplacementText() {
12367 const replacement = this.event.dataTransfer.getData("text/plain");
12368 const domRange = this.event.getTargetRanges()[0];
12369 this.withTargetDOMRange(domRange, () => {
12370 this.insertString(replacement, {
12371 updatePosition: false
12372 });
12373 });
12374 },
12375 insertText() {
12376 var _this$event$dataTrans;
12377 return this.insertString(this.event.data || ((_this$event$dataTrans = this.event.dataTransfer) === null || _this$event$dataTrans === void 0 ? void 0 : _this$event$dataTrans.getData("text/plain")));
12378 },
12379 insertTranspose() {
12380 return this.insertString(this.event.data);
12381 },
12382 insertUnorderedList() {
12383 return this.toggleAttributeIfSupported("bullet");
12384 }
12385 });
12386 const staticRangeToRange = function (staticRange) {
12387 const range = document.createRange();
12388 range.setStart(staticRange.startContainer, staticRange.startOffset);
12389 range.setEnd(staticRange.endContainer, staticRange.endOffset);
12390 return range;
12391 };
12392
12393 // Event helpers
12394
12395 const dragEventHasFiles = event => {
12396 var _event$dataTransfer;
12397 return Array.from(((_event$dataTransfer = event.dataTransfer) === null || _event$dataTransfer === void 0 ? void 0 : _event$dataTransfer.types) || []).includes("Files");
12398 };
12399 const processableFilePaste = event => {
12400 var _event$dataTransfer$f;
12401 // Paste events that only have files are handled by the paste event handler,
12402 // to work around Safari not supporting beforeinput.insertFromPaste for files.
12403
12404 // MS Office text pastes include a file with a screenshot of the text, but we should
12405 // handle them as text pastes.
12406 return ((_event$dataTransfer$f = event.dataTransfer.files) === null || _event$dataTransfer$f === void 0 ? void 0 : _event$dataTransfer$f[0]) && !pasteEventHasFilesOnly(event) && !dataTransferIsMsOfficePaste(event);
12407 };
12408 const pasteEventHasFilesOnly = function (event) {
12409 const clipboard = event.clipboardData;
12410 if (clipboard) {
12411 const fileTypes = Array.from(clipboard.types).filter(type => type.match(/file/i)); // "Files", "application/x-moz-file"
12412 return fileTypes.length === clipboard.types.length && clipboard.files.length >= 1;
12413 }
12414 };
12415 const pasteEventHasPlainTextOnly = function (event) {
12416 const clipboard = event.clipboardData;
12417 if (clipboard) {
12418 return clipboard.types.includes("text/plain") && clipboard.types.length === 1;
12419 }
12420 };
12421 const keyboardCommandFromKeyEvent = function (event) {
12422 const command = [];
12423 if (event.altKey) {
12424 command.push("alt");
12425 }
12426 if (event.shiftKey) {
12427 command.push("shift");
12428 }
12429 command.push(event.key);
12430 return command;
12431 };
12432 const pointFromEvent = event => ({
12433 x: event.clientX,
12434 y: event.clientY
12435 });
12436
12437 const attributeButtonSelector = "[data-trix-attribute]";
12438 const actionButtonSelector = "[data-trix-action]";
12439 const toolbarButtonSelector = "".concat(attributeButtonSelector, ", ").concat(actionButtonSelector);
12440 const dialogSelector = "[data-trix-dialog]";
12441 const activeDialogSelector = "".concat(dialogSelector, "[data-trix-active]");
12442 const dialogButtonSelector = "".concat(dialogSelector, " [data-trix-method]");
12443 const dialogInputSelector = "".concat(dialogSelector, " [data-trix-input]");
12444 const getInputForDialog = (element, attributeName) => {
12445 if (!attributeName) {
12446 attributeName = getAttributeName(element);
12447 }
12448 return element.querySelector("[data-trix-input][name='".concat(attributeName, "']"));
12449 };
12450 const getActionName = element => element.getAttribute("data-trix-action");
12451 const getAttributeName = element => {
12452 return element.getAttribute("data-trix-attribute") || element.getAttribute("data-trix-dialog-attribute");
12453 };
12454 const getDialogName = element => element.getAttribute("data-trix-dialog");
12455 class ToolbarController extends BasicObject {
12456 constructor(element) {
12457 super(element);
12458 this.didClickActionButton = this.didClickActionButton.bind(this);
12459 this.didClickAttributeButton = this.didClickAttributeButton.bind(this);
12460 this.didClickDialogButton = this.didClickDialogButton.bind(this);
12461 this.didKeyDownDialogInput = this.didKeyDownDialogInput.bind(this);
12462 this.element = element;
12463 this.attributes = {};
12464 this.actions = {};
12465 this.resetDialogInputs();
12466 handleEvent("mousedown", {
12467 onElement: this.element,
12468 matchingSelector: actionButtonSelector,
12469 withCallback: this.didClickActionButton
12470 });
12471 handleEvent("mousedown", {
12472 onElement: this.element,
12473 matchingSelector: attributeButtonSelector,
12474 withCallback: this.didClickAttributeButton
12475 });
12476 handleEvent("click", {
12477 onElement: this.element,
12478 matchingSelector: toolbarButtonSelector,
12479 preventDefault: true
12480 });
12481 handleEvent("click", {
12482 onElement: this.element,
12483 matchingSelector: dialogButtonSelector,
12484 withCallback: this.didClickDialogButton
12485 });
12486 handleEvent("keydown", {
12487 onElement: this.element,
12488 matchingSelector: dialogInputSelector,
12489 withCallback: this.didKeyDownDialogInput
12490 });
12491 }
12492
12493 // Event handlers
12494
12495 didClickActionButton(event, element) {
12496 var _this$delegate;
12497 (_this$delegate = this.delegate) === null || _this$delegate === void 0 || _this$delegate.toolbarDidClickButton();
12498 event.preventDefault();
12499 const actionName = getActionName(element);
12500 if (this.getDialog(actionName)) {
12501 return this.toggleDialog(actionName);
12502 } else {
12503 var _this$delegate2;
12504 return (_this$delegate2 = this.delegate) === null || _this$delegate2 === void 0 ? void 0 : _this$delegate2.toolbarDidInvokeAction(actionName, element);
12505 }
12506 }
12507 didClickAttributeButton(event, element) {
12508 var _this$delegate3;
12509 (_this$delegate3 = this.delegate) === null || _this$delegate3 === void 0 || _this$delegate3.toolbarDidClickButton();
12510 event.preventDefault();
12511 const attributeName = getAttributeName(element);
12512 if (this.getDialog(attributeName)) {
12513 this.toggleDialog(attributeName);
12514 } else {
12515 var _this$delegate4;
12516 (_this$delegate4 = this.delegate) === null || _this$delegate4 === void 0 || _this$delegate4.toolbarDidToggleAttribute(attributeName);
12517 }
12518 return this.refreshAttributeButtons();
12519 }
12520 didClickDialogButton(event, element) {
12521 const dialogElement = findClosestElementFromNode(element, {
12522 matchingSelector: dialogSelector
12523 });
12524 const method = element.getAttribute("data-trix-method");
12525 return this[method].call(this, dialogElement);
12526 }
12527 didKeyDownDialogInput(event, element) {
12528 if (event.keyCode === 13) {
12529 // Enter key
12530 event.preventDefault();
12531 const attribute = element.getAttribute("name");
12532 const dialog = this.getDialog(attribute);
12533 this.setAttribute(dialog);
12534 }
12535 if (event.keyCode === 27) {
12536 // Escape key
12537 event.preventDefault();
12538 return this.hideDialog();
12539 }
12540 }
12541
12542 // Action buttons
12543
12544 updateActions(actions) {
12545 this.actions = actions;
12546 return this.refreshActionButtons();
12547 }
12548 refreshActionButtons() {
12549 return this.eachActionButton((element, actionName) => {
12550 element.disabled = this.actions[actionName] === false;
12551 });
12552 }
12553 eachActionButton(callback) {
12554 return Array.from(this.element.querySelectorAll(actionButtonSelector)).map(element => callback(element, getActionName(element)));
12555 }
12556
12557 // Attribute buttons
12558
12559 updateAttributes(attributes) {
12560 this.attributes = attributes;
12561 return this.refreshAttributeButtons();
12562 }
12563 refreshAttributeButtons() {
12564 return this.eachAttributeButton((element, attributeName) => {
12565 element.disabled = this.attributes[attributeName] === false;
12566 if (this.attributes[attributeName] || this.dialogIsVisible(attributeName)) {
12567 element.setAttribute("data-trix-active", "");
12568 return element.classList.add("trix-active");
12569 } else {
12570 element.removeAttribute("data-trix-active");
12571 return element.classList.remove("trix-active");
12572 }
12573 });
12574 }
12575 eachAttributeButton(callback) {
12576 return Array.from(this.element.querySelectorAll(attributeButtonSelector)).map(element => callback(element, getAttributeName(element)));
12577 }
12578 applyKeyboardCommand(keys) {
12579 const keyString = JSON.stringify(keys.sort());
12580 for (const button of Array.from(this.element.querySelectorAll("[data-trix-key]"))) {
12581 const buttonKeys = button.getAttribute("data-trix-key").split("+");
12582 const buttonKeyString = JSON.stringify(buttonKeys.sort());
12583 if (buttonKeyString === keyString) {
12584 triggerEvent("mousedown", {
12585 onElement: button
12586 });
12587 return true;
12588 }
12589 }
12590 return false;
12591 }
12592
12593 // Dialogs
12594
12595 dialogIsVisible(dialogName) {
12596 const element = this.getDialog(dialogName);
12597 if (element) {
12598 return element.hasAttribute("data-trix-active");
12599 }
12600 }
12601 toggleDialog(dialogName) {
12602 if (this.dialogIsVisible(dialogName)) {
12603 return this.hideDialog();
12604 } else {
12605 return this.showDialog(dialogName);
12606 }
12607 }
12608 showDialog(dialogName) {
12609 var _this$delegate5, _this$delegate6;
12610 this.hideDialog();
12611 (_this$delegate5 = this.delegate) === null || _this$delegate5 === void 0 || _this$delegate5.toolbarWillShowDialog();
12612 const element = this.getDialog(dialogName);
12613 element.setAttribute("data-trix-active", "");
12614 element.classList.add("trix-active");
12615 Array.from(element.querySelectorAll("input[disabled]")).forEach(disabledInput => {
12616 disabledInput.removeAttribute("disabled");
12617 });
12618 const attributeName = getAttributeName(element);
12619 if (attributeName) {
12620 const input = getInputForDialog(element, dialogName);
12621 if (input) {
12622 input.value = this.attributes[attributeName] || "";
12623 input.select();
12624 }
12625 }
12626 return (_this$delegate6 = this.delegate) === null || _this$delegate6 === void 0 ? void 0 : _this$delegate6.toolbarDidShowDialog(dialogName);
12627 }
12628 setAttribute(dialogElement) {
12629 const attributeName = getAttributeName(dialogElement);
12630 const input = getInputForDialog(dialogElement, attributeName);
12631 if (input.willValidate && !input.checkValidity()) {
12632 input.setAttribute("data-trix-validate", "");
12633 input.classList.add("trix-validate");
12634 return input.focus();
12635 } else {
12636 var _this$delegate7;
12637 (_this$delegate7 = this.delegate) === null || _this$delegate7 === void 0 || _this$delegate7.toolbarDidUpdateAttribute(attributeName, input.value);
12638 return this.hideDialog();
12639 }
12640 }
12641 removeAttribute(dialogElement) {
12642 var _this$delegate8;
12643 const attributeName = getAttributeName(dialogElement);
12644 (_this$delegate8 = this.delegate) === null || _this$delegate8 === void 0 || _this$delegate8.toolbarDidRemoveAttribute(attributeName);
12645 return this.hideDialog();
12646 }
12647 hideDialog() {
12648 const element = this.element.querySelector(activeDialogSelector);
12649 if (element) {
12650 var _this$delegate9;
12651 element.removeAttribute("data-trix-active");
12652 element.classList.remove("trix-active");
12653 this.resetDialogInputs();
12654 return (_this$delegate9 = this.delegate) === null || _this$delegate9 === void 0 ? void 0 : _this$delegate9.toolbarDidHideDialog(getDialogName(element));
12655 }
12656 }
12657 resetDialogInputs() {
12658 Array.from(this.element.querySelectorAll(dialogInputSelector)).forEach(input => {
12659 input.setAttribute("disabled", "disabled");
12660 input.removeAttribute("data-trix-validate");
12661 input.classList.remove("trix-validate");
12662 });
12663 }
12664 getDialog(dialogName) {
12665 return this.element.querySelector("[data-trix-dialog=".concat(dialogName, "]"));
12666 }
12667 }
12668
12669 const snapshotsAreEqual = (a, b) => rangesAreEqual(a.selectedRange, b.selectedRange) && a.document.isEqualTo(b.document);
12670 class EditorController extends Controller {
12671 constructor(_ref) {
12672 let {
12673 editorElement,
12674 document,
12675 html
12676 } = _ref;
12677 super(...arguments);
12678 this.editorElement = editorElement;
12679 this.selectionManager = new SelectionManager(this.editorElement);
12680 this.selectionManager.delegate = this;
12681 this.composition = new Composition();
12682 this.composition.delegate = this;
12683 this.attachmentManager = new AttachmentManager(this.composition.getAttachments());
12684 this.attachmentManager.delegate = this;
12685 this.inputController = input.getLevel() === 2 ? new Level2InputController(this.editorElement) : new Level0InputController(this.editorElement);
12686 this.inputController.delegate = this;
12687 this.inputController.responder = this.composition;
12688 this.compositionController = new CompositionController(this.editorElement, this.composition);
12689 this.compositionController.delegate = this;
12690 this.toolbarController = new ToolbarController(this.editorElement.toolbarElement);
12691 this.toolbarController.delegate = this;
12692 this.editor = new Editor(this.composition, this.selectionManager, this.editorElement);
12693 if (document) {
12694 this.editor.loadDocument(document);
12695 } else {
12696 this.editor.loadHTML(html);
12697 }
12698 }
12699 registerSelectionManager() {
12700 return selectionChangeObserver.registerSelectionManager(this.selectionManager);
12701 }
12702 unregisterSelectionManager() {
12703 return selectionChangeObserver.unregisterSelectionManager(this.selectionManager);
12704 }
12705 render() {
12706 return this.compositionController.render();
12707 }
12708 reparse() {
12709 return this.composition.replaceHTML(this.editorElement.innerHTML);
12710 }
12711
12712 // Composition delegate
12713
12714 compositionDidChangeDocument(document) {
12715 this.notifyEditorElement("document-change");
12716 if (!this.handlingInput) {
12717 return this.render();
12718 }
12719 }
12720 compositionDidChangeCurrentAttributes(currentAttributes) {
12721 this.currentAttributes = currentAttributes;
12722 this.toolbarController.updateAttributes(this.currentAttributes);
12723 this.updateCurrentActions();
12724 return this.notifyEditorElement("attributes-change", {
12725 attributes: this.currentAttributes
12726 });
12727 }
12728 compositionDidPerformInsertionAtRange(range) {
12729 if (this.pasting) {
12730 this.pastedRange = range;
12731 }
12732 }
12733 compositionShouldAcceptFile(file) {
12734 return this.notifyEditorElement("file-accept", {
12735 file
12736 });
12737 }
12738 compositionDidAddAttachment(attachment) {
12739 const managedAttachment = this.attachmentManager.manageAttachment(attachment);
12740 return this.notifyEditorElement("attachment-add", {
12741 attachment: managedAttachment
12742 });
12743 }
12744 compositionDidEditAttachment(attachment) {
12745 this.compositionController.rerenderViewForObject(attachment);
12746 const managedAttachment = this.attachmentManager.manageAttachment(attachment);
12747 this.notifyEditorElement("attachment-edit", {
12748 attachment: managedAttachment
12749 });
12750 return this.notifyEditorElement("change");
12751 }
12752 compositionDidChangeAttachmentPreviewURL(attachment) {
12753 this.compositionController.invalidateViewForObject(attachment);
12754 return this.notifyEditorElement("change");
12755 }
12756 compositionDidRemoveAttachment(attachment) {
12757 const managedAttachment = this.attachmentManager.unmanageAttachment(attachment);
12758 return this.notifyEditorElement("attachment-remove", {
12759 attachment: managedAttachment
12760 });
12761 }
12762 compositionDidStartEditingAttachment(attachment, options) {
12763 this.attachmentLocationRange = this.composition.document.getLocationRangeOfAttachment(attachment);
12764 this.compositionController.installAttachmentEditorForAttachment(attachment, options);
12765 return this.selectionManager.setLocationRange(this.attachmentLocationRange);
12766 }
12767 compositionDidStopEditingAttachment(attachment) {
12768 this.compositionController.uninstallAttachmentEditor();
12769 this.attachmentLocationRange = null;
12770 }
12771 compositionDidRequestChangingSelectionToLocationRange(locationRange) {
12772 if (this.loadingSnapshot && !this.isFocused()) return;
12773 this.requestedLocationRange = locationRange;
12774 this.compositionRevisionWhenLocationRangeRequested = this.composition.revision;
12775 if (!this.handlingInput) {
12776 return this.render();
12777 }
12778 }
12779 compositionWillLoadSnapshot() {
12780 this.loadingSnapshot = true;
12781 }
12782 compositionDidLoadSnapshot() {
12783 this.compositionController.refreshViewCache();
12784 this.render();
12785 this.loadingSnapshot = false;
12786 }
12787 getSelectionManager() {
12788 return this.selectionManager;
12789 }
12790
12791 // Attachment manager delegate
12792
12793 attachmentManagerDidRequestRemovalOfAttachment(attachment) {
12794 return this.removeAttachment(attachment);
12795 }
12796
12797 // Document controller delegate
12798
12799 compositionControllerWillSyncDocumentView() {
12800 this.inputController.editorWillSyncDocumentView();
12801 this.selectionManager.lock();
12802 return this.selectionManager.clearSelection();
12803 }
12804 compositionControllerDidSyncDocumentView() {
12805 this.inputController.editorDidSyncDocumentView();
12806 this.selectionManager.unlock();
12807 this.updateCurrentActions();
12808 return this.notifyEditorElement("sync");
12809 }
12810 compositionControllerDidRender() {
12811 if (this.requestedLocationRange) {
12812 if (this.compositionRevisionWhenLocationRangeRequested === this.composition.revision) {
12813 this.selectionManager.setLocationRange(this.requestedLocationRange);
12814 }
12815 this.requestedLocationRange = null;
12816 this.compositionRevisionWhenLocationRangeRequested = null;
12817 }
12818 if (this.renderedCompositionRevision !== this.composition.revision) {
12819 this.runEditorFilters();
12820 this.composition.updateCurrentAttributes();
12821 this.notifyEditorElement("render");
12822 }
12823 this.renderedCompositionRevision = this.composition.revision;
12824 }
12825 compositionControllerDidFocus() {
12826 if (this.isFocusedInvisibly()) {
12827 this.setLocationRange({
12828 index: 0,
12829 offset: 0
12830 });
12831 }
12832 this.toolbarController.hideDialog();
12833 return this.notifyEditorElement("focus");
12834 }
12835 compositionControllerDidBlur() {
12836 return this.notifyEditorElement("blur");
12837 }
12838 compositionControllerDidSelectAttachment(attachment, options) {
12839 this.toolbarController.hideDialog();
12840 return this.composition.editAttachment(attachment, options);
12841 }
12842 compositionControllerDidRequestDeselectingAttachment(attachment) {
12843 const locationRange = this.attachmentLocationRange || this.composition.document.getLocationRangeOfAttachment(attachment);
12844 return this.selectionManager.setLocationRange(locationRange[1]);
12845 }
12846 compositionControllerWillUpdateAttachment(attachment) {
12847 return this.editor.recordUndoEntry("Edit Attachment", {
12848 context: attachment.id,
12849 consolidatable: true
12850 });
12851 }
12852 compositionControllerDidRequestRemovalOfAttachment(attachment) {
12853 return this.removeAttachment(attachment);
12854 }
12855
12856 // Input controller delegate
12857
12858 inputControllerWillHandleInput() {
12859 this.handlingInput = true;
12860 this.requestedRender = false;
12861 }
12862 inputControllerDidRequestRender() {
12863 this.requestedRender = true;
12864 }
12865 inputControllerDidHandleInput() {
12866 this.handlingInput = false;
12867 if (this.requestedRender) {
12868 this.requestedRender = false;
12869 return this.render();
12870 }
12871 }
12872 inputControllerDidAllowUnhandledInput() {
12873 return this.notifyEditorElement("change");
12874 }
12875 inputControllerDidRequestReparse() {
12876 return this.reparse();
12877 }
12878 inputControllerWillPerformTyping() {
12879 return this.recordTypingUndoEntry();
12880 }
12881 inputControllerWillPerformFormatting(attributeName) {
12882 return this.recordFormattingUndoEntry(attributeName);
12883 }
12884 inputControllerWillCutText() {
12885 return this.editor.recordUndoEntry("Cut");
12886 }
12887 inputControllerWillPaste(paste) {
12888 this.editor.recordUndoEntry("Paste");
12889 this.pasting = true;
12890 return this.notifyEditorElement("before-paste", {
12891 paste
12892 });
12893 }
12894 inputControllerDidPaste(paste) {
12895 paste.range = this.pastedRange;
12896 this.pastedRange = null;
12897 this.pasting = null;
12898 return this.notifyEditorElement("paste", {
12899 paste
12900 });
12901 }
12902 inputControllerWillMoveText() {
12903 return this.editor.recordUndoEntry("Move");
12904 }
12905 inputControllerWillAttachFiles() {
12906 return this.editor.recordUndoEntry("Drop Files");
12907 }
12908 inputControllerWillPerformUndo() {
12909 return this.editor.undo();
12910 }
12911 inputControllerWillPerformRedo() {
12912 return this.editor.redo();
12913 }
12914 inputControllerDidReceiveKeyboardCommand(keys) {
12915 return this.toolbarController.applyKeyboardCommand(keys);
12916 }
12917 inputControllerDidStartDrag() {
12918 this.locationRangeBeforeDrag = this.selectionManager.getLocationRange();
12919 }
12920 inputControllerDidReceiveDragOverPoint(point) {
12921 return this.selectionManager.setLocationRangeFromPointRange(point);
12922 }
12923 inputControllerDidCancelDrag() {
12924 this.selectionManager.setLocationRange(this.locationRangeBeforeDrag);
12925 this.locationRangeBeforeDrag = null;
12926 }
12927
12928 // Selection manager delegate
12929
12930 locationRangeDidChange(locationRange) {
12931 this.composition.updateCurrentAttributes();
12932 this.updateCurrentActions();
12933 if (this.attachmentLocationRange && !rangesAreEqual(this.attachmentLocationRange, locationRange)) {
12934 this.composition.stopEditingAttachment();
12935 }
12936 return this.notifyEditorElement("selection-change");
12937 }
12938
12939 // Toolbar controller delegate
12940
12941 toolbarDidClickButton() {
12942 if (!this.getLocationRange()) {
12943 return this.setLocationRange({
12944 index: 0,
12945 offset: 0
12946 });
12947 }
12948 }
12949 toolbarDidInvokeAction(actionName, invokingElement) {
12950 return this.invokeAction(actionName, invokingElement);
12951 }
12952 toolbarDidToggleAttribute(attributeName) {
12953 this.recordFormattingUndoEntry(attributeName);
12954 this.composition.toggleCurrentAttribute(attributeName);
12955 this.render();
12956 if (!this.selectionFrozen) {
12957 return this.editorElement.focus();
12958 }
12959 }
12960 toolbarDidUpdateAttribute(attributeName, value) {
12961 this.recordFormattingUndoEntry(attributeName);
12962 this.composition.setCurrentAttribute(attributeName, value);
12963 this.render();
12964 if (!this.selectionFrozen) {
12965 return this.editorElement.focus();
12966 }
12967 }
12968 toolbarDidRemoveAttribute(attributeName) {
12969 this.recordFormattingUndoEntry(attributeName);
12970 this.composition.removeCurrentAttribute(attributeName);
12971 this.render();
12972 if (!this.selectionFrozen) {
12973 return this.editorElement.focus();
12974 }
12975 }
12976 toolbarWillShowDialog(dialogElement) {
12977 this.composition.expandSelectionForEditing();
12978 return this.freezeSelection();
12979 }
12980 toolbarDidShowDialog(dialogName) {
12981 return this.notifyEditorElement("toolbar-dialog-show", {
12982 dialogName
12983 });
12984 }
12985 toolbarDidHideDialog(dialogName) {
12986 this.thawSelection();
12987 this.editorElement.focus();
12988 return this.notifyEditorElement("toolbar-dialog-hide", {
12989 dialogName
12990 });
12991 }
12992
12993 // Selection
12994
12995 freezeSelection() {
12996 if (!this.selectionFrozen) {
12997 this.selectionManager.lock();
12998 this.composition.freezeSelection();
12999 this.selectionFrozen = true;
13000 return this.render();
13001 }
13002 }
13003 thawSelection() {
13004 if (this.selectionFrozen) {
13005 this.composition.thawSelection();
13006 this.selectionManager.unlock();
13007 this.selectionFrozen = false;
13008 return this.render();
13009 }
13010 }
13011 canInvokeAction(actionName) {
13012 if (this.actionIsExternal(actionName)) {
13013 return true;
13014 } else {
13015 var _this$actions$actionN;
13016 return !!((_this$actions$actionN = this.actions[actionName]) !== null && _this$actions$actionN !== void 0 && (_this$actions$actionN = _this$actions$actionN.test) !== null && _this$actions$actionN !== void 0 && _this$actions$actionN.call(this));
13017 }
13018 }
13019 invokeAction(actionName, invokingElement) {
13020 if (this.actionIsExternal(actionName)) {
13021 return this.notifyEditorElement("action-invoke", {
13022 actionName,
13023 invokingElement
13024 });
13025 } else {
13026 var _this$actions$actionN2;
13027 return (_this$actions$actionN2 = this.actions[actionName]) === null || _this$actions$actionN2 === void 0 || (_this$actions$actionN2 = _this$actions$actionN2.perform) === null || _this$actions$actionN2 === void 0 ? void 0 : _this$actions$actionN2.call(this);
13028 }
13029 }
13030 actionIsExternal(actionName) {
13031 return /^x-./.test(actionName);
13032 }
13033 getCurrentActions() {
13034 const result = {};
13035 for (const actionName in this.actions) {
13036 result[actionName] = this.canInvokeAction(actionName);
13037 }
13038 return result;
13039 }
13040 updateCurrentActions() {
13041 const currentActions = this.getCurrentActions();
13042 if (!objectsAreEqual(currentActions, this.currentActions)) {
13043 this.currentActions = currentActions;
13044 this.toolbarController.updateActions(this.currentActions);
13045 return this.notifyEditorElement("actions-change", {
13046 actions: this.currentActions
13047 });
13048 }
13049 }
13050
13051 // Editor filters
13052
13053 runEditorFilters() {
13054 let snapshot = this.composition.getSnapshot();
13055 Array.from(this.editor.filters).forEach(filter => {
13056 const {
13057 document,
13058 selectedRange
13059 } = snapshot;
13060 snapshot = filter.call(this.editor, snapshot) || {};
13061 if (!snapshot.document) {
13062 snapshot.document = document;
13063 }
13064 if (!snapshot.selectedRange) {
13065 snapshot.selectedRange = selectedRange;
13066 }
13067 });
13068 if (!snapshotsAreEqual(snapshot, this.composition.getSnapshot())) {
13069 return this.composition.loadSnapshot(snapshot);
13070 }
13071 }
13072
13073 // Private
13074
13075 updateInputElement() {
13076 const element = this.compositionController.getSerializableElement();
13077 const value = serializeToContentType(element, "text/html");
13078 return this.editorElement.setFormValue(value);
13079 }
13080 notifyEditorElement(message, data) {
13081 switch (message) {
13082 case "document-change":
13083 this.documentChangedSinceLastRender = true;
13084 break;
13085 case "render":
13086 if (this.documentChangedSinceLastRender) {
13087 this.documentChangedSinceLastRender = false;
13088 this.notifyEditorElement("change");
13089 }
13090 break;
13091 case "change":
13092 case "attachment-add":
13093 case "attachment-edit":
13094 case "attachment-remove":
13095 this.updateInputElement();
13096 break;
13097 }
13098 return this.editorElement.notify(message, data);
13099 }
13100 removeAttachment(attachment) {
13101 this.editor.recordUndoEntry("Delete Attachment");
13102 this.composition.removeAttachment(attachment);
13103 return this.render();
13104 }
13105 recordFormattingUndoEntry(attributeName) {
13106 const blockConfig = getBlockConfig(attributeName);
13107 const locationRange = this.selectionManager.getLocationRange();
13108 if (blockConfig || !rangeIsCollapsed(locationRange)) {
13109 return this.editor.recordUndoEntry("Formatting", {
13110 context: this.getUndoContext(),
13111 consolidatable: true
13112 });
13113 }
13114 }
13115 recordTypingUndoEntry() {
13116 return this.editor.recordUndoEntry("Typing", {
13117 context: this.getUndoContext(this.currentAttributes),
13118 consolidatable: true
13119 });
13120 }
13121 getUndoContext() {
13122 for (var _len = arguments.length, context = new Array(_len), _key = 0; _key < _len; _key++) {
13123 context[_key] = arguments[_key];
13124 }
13125 return [this.getLocationContext(), this.getTimeContext(), ...Array.from(context)];
13126 }
13127 getLocationContext() {
13128 const locationRange = this.selectionManager.getLocationRange();
13129 if (rangeIsCollapsed(locationRange)) {
13130 return locationRange[0].index;
13131 } else {
13132 return locationRange;
13133 }
13134 }
13135 getTimeContext() {
13136 if (undo.interval > 0) {
13137 return Math.floor(new Date().getTime() / undo.interval);
13138 } else {
13139 return 0;
13140 }
13141 }
13142 isFocused() {
13143 var _this$editorElement$o;
13144 return this.editorElement === ((_this$editorElement$o = this.editorElement.ownerDocument) === null || _this$editorElement$o === void 0 ? void 0 : _this$editorElement$o.activeElement);
13145 }
13146
13147 // Detect "Cursor disappears sporadically" Firefox bug.
13148 // - https://bugzilla.mozilla.org/show_bug.cgi?id=226301
13149 isFocusedInvisibly() {
13150 return this.isFocused() && !this.getLocationRange();
13151 }
13152 get actions() {
13153 return this.constructor.actions;
13154 }
13155 }
13156 _defineProperty(EditorController, "actions", {
13157 undo: {
13158 test() {
13159 return this.editor.canUndo();
13160 },
13161 perform() {
13162 return this.editor.undo();
13163 }
13164 },
13165 redo: {
13166 test() {
13167 return this.editor.canRedo();
13168 },
13169 perform() {
13170 return this.editor.redo();
13171 }
13172 },
13173 link: {
13174 test() {
13175 return this.editor.canActivateAttribute("href");
13176 }
13177 },
13178 increaseNestingLevel: {
13179 test() {
13180 return this.editor.canIncreaseNestingLevel();
13181 },
13182 perform() {
13183 return this.editor.increaseNestingLevel() && this.render();
13184 }
13185 },
13186 decreaseNestingLevel: {
13187 test() {
13188 return this.editor.canDecreaseNestingLevel();
13189 },
13190 perform() {
13191 return this.editor.decreaseNestingLevel() && this.render();
13192 }
13193 },
13194 attachFiles: {
13195 test() {
13196 return true;
13197 },
13198 perform() {
13199 return input.pickFiles(this.editor.insertFiles);
13200 }
13201 }
13202 });
13203 EditorController.proxyMethod("getSelectionManager().setLocationRange");
13204 EditorController.proxyMethod("getSelectionManager().getLocationRange");
13205
13206 var controllers = /*#__PURE__*/Object.freeze({
13207 __proto__: null,
13208 AttachmentEditorController: AttachmentEditorController,
13209 CompositionController: CompositionController,
13210 Controller: Controller,
13211 EditorController: EditorController,
13212 InputController: InputController,
13213 Level0InputController: Level0InputController,
13214 Level2InputController: Level2InputController,
13215 ToolbarController: ToolbarController
13216 });
13217
13218 var observers = /*#__PURE__*/Object.freeze({
13219 __proto__: null,
13220 MutationObserver: MutationObserver,
13221 SelectionChangeObserver: SelectionChangeObserver
13222 });
13223
13224 var operations = /*#__PURE__*/Object.freeze({
13225 __proto__: null,
13226 FileVerificationOperation: FileVerificationOperation,
13227 ImagePreloadOperation: ImagePreloadOperation
13228 });
13229
13230 installDefaultCSSForTagName("trix-toolbar", "%t {\n display: block;\n}\n\n%t {\n white-space: nowrap;\n}\n\n%t [data-trix-dialog] {\n display: none;\n}\n\n%t [data-trix-dialog][data-trix-active] {\n display: block;\n}\n\n%t [data-trix-dialog] [data-trix-validate]:invalid {\n background-color: #ffdddd;\n}");
13231 class TrixToolbarElement extends HTMLElement {
13232 // Element lifecycle
13233
13234 connectedCallback() {
13235 if (this.innerHTML === "") {
13236 this.innerHTML = toolbar.getDefaultHTML();
13237 }
13238 }
13239 }
13240
13241 let id = 0;
13242
13243 // Contenteditable support helpers
13244
13245 const autofocus = function (element) {
13246 if (!document.querySelector(":focus")) {
13247 if (element.hasAttribute("autofocus") && document.querySelector("[autofocus]") === element) {
13248 return element.focus();
13249 }
13250 }
13251 };
13252 const makeEditable = function (element) {
13253 if (element.hasAttribute("contenteditable")) {
13254 return;
13255 }
13256 element.setAttribute("contenteditable", "");
13257 return handleEventOnce("focus", {
13258 onElement: element,
13259 withCallback() {
13260 return configureContentEditable(element);
13261 }
13262 });
13263 };
13264 const configureContentEditable = function (element) {
13265 disableObjectResizing(element);
13266 return setDefaultParagraphSeparator(element);
13267 };
13268 const disableObjectResizing = function (element) {
13269 var _document$queryComman, _document;
13270 if ((_document$queryComman = (_document = document).queryCommandSupported) !== null && _document$queryComman !== void 0 && _document$queryComman.call(_document, "enableObjectResizing")) {
13271 document.execCommand("enableObjectResizing", false, false);
13272 return handleEvent("mscontrolselect", {
13273 onElement: element,
13274 preventDefault: true
13275 });
13276 }
13277 };
13278 const setDefaultParagraphSeparator = function (element) {
13279 var _document$queryComman2, _document2;
13280 if ((_document$queryComman2 = (_document2 = document).queryCommandSupported) !== null && _document$queryComman2 !== void 0 && _document$queryComman2.call(_document2, "DefaultParagraphSeparator")) {
13281 const {
13282 tagName
13283 } = attributes.default;
13284 if (["div", "p"].includes(tagName)) {
13285 return document.execCommand("DefaultParagraphSeparator", false, tagName);
13286 }
13287 }
13288 };
13289
13290 // Accessibility helpers
13291
13292 const addAccessibilityRole = function (element) {
13293 if (element.hasAttribute("role")) {
13294 return;
13295 }
13296 return element.setAttribute("role", "textbox");
13297 };
13298 const ensureAriaLabel = function (element) {
13299 if (element.hasAttribute("aria-label") || element.hasAttribute("aria-labelledby")) {
13300 return;
13301 }
13302 const update = function () {
13303 const texts = Array.from(element.labels).map(label => {
13304 if (!label.contains(element)) return label.textContent;
13305 }).filter(text => text);
13306 const text = texts.join(" ");
13307 if (text) {
13308 return element.setAttribute("aria-label", text);
13309 } else {
13310 return element.removeAttribute("aria-label");
13311 }
13312 };
13313 update();
13314 return handleEvent("focus", {
13315 onElement: element,
13316 withCallback: update
13317 });
13318 };
13319
13320 // Style
13321
13322 const cursorTargetStyles = function () {
13323 if (browser$1.forcesObjectResizing) {
13324 return {
13325 display: "inline",
13326 width: "auto"
13327 };
13328 } else {
13329 return {
13330 display: "inline-block",
13331 width: "1px"
13332 };
13333 }
13334 }();
13335 installDefaultCSSForTagName("trix-editor", "%t {\n display: block;\n}\n\n%t:empty::before {\n content: attr(placeholder);\n color: graytext;\n cursor: text;\n pointer-events: none;\n white-space: pre-line;\n}\n\n%t a[contenteditable=false] {\n cursor: text;\n}\n\n%t img {\n max-width: 100%;\n height: auto;\n}\n\n%t ".concat(attachmentSelector, " figcaption textarea {\n resize: none;\n}\n\n%t ").concat(attachmentSelector, " figcaption textarea.trix-autoresize-clone {\n position: absolute;\n left: -9999px;\n max-height: 0px;\n}\n\n%t ").concat(attachmentSelector, " figcaption[data-trix-placeholder]:empty::before {\n content: attr(data-trix-placeholder);\n color: graytext;\n}\n\n%t [data-trix-cursor-target] {\n display: ").concat(cursorTargetStyles.display, " !important;\n width: ").concat(cursorTargetStyles.width, " !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n}\n\n%t [data-trix-cursor-target=left] {\n vertical-align: top !important;\n margin-left: -1px !important;\n}\n\n%t [data-trix-cursor-target=right] {\n vertical-align: bottom !important;\n margin-right: -1px !important;\n}"));
13336 var _internals = /*#__PURE__*/new WeakMap();
13337 var _validate = /*#__PURE__*/new WeakSet();
13338 class ElementInternalsDelegate {
13339 constructor(element) {
13340 _classPrivateMethodInitSpec(this, _validate);
13341 _classPrivateFieldInitSpec(this, _internals, {
13342 writable: true,
13343 value: void 0
13344 });
13345 this.element = element;
13346 _classPrivateFieldSet(this, _internals, element.attachInternals());
13347 }
13348 connectedCallback() {
13349 _classPrivateMethodGet(this, _validate, _validate2).call(this);
13350 }
13351 disconnectedCallback() {}
13352 get labels() {
13353 return _classPrivateFieldGet(this, _internals).labels;
13354 }
13355 get disabled() {
13356 var _this$element$inputEl;
13357 return (_this$element$inputEl = this.element.inputElement) === null || _this$element$inputEl === void 0 ? void 0 : _this$element$inputEl.disabled;
13358 }
13359 set disabled(value) {
13360 this.element.toggleAttribute("disabled", value);
13361 }
13362 get required() {
13363 return this.element.hasAttribute("required");
13364 }
13365 set required(value) {
13366 this.element.toggleAttribute("required", value);
13367 _classPrivateMethodGet(this, _validate, _validate2).call(this);
13368 }
13369 get validity() {
13370 return _classPrivateFieldGet(this, _internals).validity;
13371 }
13372 get validationMessage() {
13373 return _classPrivateFieldGet(this, _internals).validationMessage;
13374 }
13375 get willValidate() {
13376 return _classPrivateFieldGet(this, _internals).willValidate;
13377 }
13378 setFormValue(value) {
13379 _classPrivateMethodGet(this, _validate, _validate2).call(this);
13380 }
13381 checkValidity() {
13382 return _classPrivateFieldGet(this, _internals).checkValidity();
13383 }
13384 reportValidity() {
13385 return _classPrivateFieldGet(this, _internals).reportValidity();
13386 }
13387 setCustomValidity(validationMessage) {
13388 _classPrivateMethodGet(this, _validate, _validate2).call(this, validationMessage);
13389 }
13390 }
13391 function _validate2() {
13392 let customValidationMessage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
13393 const {
13394 required,
13395 value
13396 } = this.element;
13397 const valueMissing = required && !value;
13398 const customError = !!customValidationMessage;
13399 const input = makeElement("input", {
13400 required
13401 });
13402 const validationMessage = customValidationMessage || input.validationMessage;
13403 _classPrivateFieldGet(this, _internals).setValidity({
13404 valueMissing,
13405 customError
13406 }, validationMessage);
13407 }
13408 var _focusHandler = /*#__PURE__*/new WeakMap();
13409 var _resetBubbled = /*#__PURE__*/new WeakMap();
13410 var _clickBubbled = /*#__PURE__*/new WeakMap();
13411 class LegacyDelegate {
13412 constructor(element) {
13413 _classPrivateFieldInitSpec(this, _focusHandler, {
13414 writable: true,
13415 value: void 0
13416 });
13417 _classPrivateFieldInitSpec(this, _resetBubbled, {
13418 writable: true,
13419 value: event => {
13420 if (event.defaultPrevented) return;
13421 if (event.target !== this.element.form) return;
13422 this.element.reset();
13423 }
13424 });
13425 _classPrivateFieldInitSpec(this, _clickBubbled, {
13426 writable: true,
13427 value: event => {
13428 if (event.defaultPrevented) return;
13429 if (this.element.contains(event.target)) return;
13430 const label = findClosestElementFromNode(event.target, {
13431 matchingSelector: "label"
13432 });
13433 if (!label) return;
13434 if (!Array.from(this.labels).includes(label)) return;
13435 this.element.focus();
13436 }
13437 });
13438 this.element = element;
13439 }
13440 connectedCallback() {
13441 _classPrivateFieldSet(this, _focusHandler, ensureAriaLabel(this.element));
13442 window.addEventListener("reset", _classPrivateFieldGet(this, _resetBubbled), false);
13443 window.addEventListener("click", _classPrivateFieldGet(this, _clickBubbled), false);
13444 }
13445 disconnectedCallback() {
13446 var _classPrivateFieldGet2;
13447 (_classPrivateFieldGet2 = _classPrivateFieldGet(this, _focusHandler)) === null || _classPrivateFieldGet2 === void 0 || _classPrivateFieldGet2.destroy();
13448 window.removeEventListener("reset", _classPrivateFieldGet(this, _resetBubbled), false);
13449 window.removeEventListener("click", _classPrivateFieldGet(this, _clickBubbled), false);
13450 }
13451 get labels() {
13452 const labels = [];
13453 if (this.element.id && this.element.ownerDocument) {
13454 labels.push(...Array.from(this.element.ownerDocument.querySelectorAll("label[for='".concat(this.element.id, "']")) || []));
13455 }
13456 const label = findClosestElementFromNode(this.element, {
13457 matchingSelector: "label"
13458 });
13459 if (label) {
13460 if ([this.element, null].includes(label.control)) {
13461 labels.push(label);
13462 }
13463 }
13464 return labels;
13465 }
13466 get disabled() {
13467 console.warn("This browser does not support the [disabled] attribute for trix-editor elements.");
13468 return false;
13469 }
13470 set disabled(value) {
13471 console.warn("This browser does not support the [disabled] attribute for trix-editor elements.");
13472 }
13473 get required() {
13474 console.warn("This browser does not support the [required] attribute for trix-editor elements.");
13475 return false;
13476 }
13477 set required(value) {
13478 console.warn("This browser does not support the [required] attribute for trix-editor elements.");
13479 }
13480 get validity() {
13481 console.warn("This browser does not support the validity property for trix-editor elements.");
13482 return null;
13483 }
13484 get validationMessage() {
13485 console.warn("This browser does not support the validationMessage property for trix-editor elements.");
13486 return "";
13487 }
13488 get willValidate() {
13489 console.warn("This browser does not support the willValidate property for trix-editor elements.");
13490 return false;
13491 }
13492 setFormValue(value) {}
13493 checkValidity() {
13494 console.warn("This browser does not support checkValidity() for trix-editor elements.");
13495 return true;
13496 }
13497 reportValidity() {
13498 console.warn("This browser does not support reportValidity() for trix-editor elements.");
13499 return true;
13500 }
13501 setCustomValidity(validationMessage) {
13502 console.warn("This browser does not support setCustomValidity(validationMessage) for trix-editor elements.");
13503 }
13504 }
13505 var _delegate = /*#__PURE__*/new WeakMap();
13506 class TrixEditorElement extends HTMLElement {
13507 constructor() {
13508 super();
13509 _classPrivateFieldInitSpec(this, _delegate, {
13510 writable: true,
13511 value: void 0
13512 });
13513 _classPrivateFieldSet(this, _delegate, this.constructor.formAssociated ? new ElementInternalsDelegate(this) : new LegacyDelegate(this));
13514 }
13515
13516 // Properties
13517
13518 get trixId() {
13519 if (this.hasAttribute("trix-id")) {
13520 return this.getAttribute("trix-id");
13521 } else {
13522 this.setAttribute("trix-id", ++id);
13523 return this.trixId;
13524 }
13525 }
13526 get labels() {
13527 return _classPrivateFieldGet(this, _delegate).labels;
13528 }
13529 get disabled() {
13530 return _classPrivateFieldGet(this, _delegate).disabled;
13531 }
13532 set disabled(value) {
13533 _classPrivateFieldGet(this, _delegate).disabled = value;
13534 }
13535 get required() {
13536 return _classPrivateFieldGet(this, _delegate).required;
13537 }
13538 set required(value) {
13539 _classPrivateFieldGet(this, _delegate).required = value;
13540 }
13541 get validity() {
13542 return _classPrivateFieldGet(this, _delegate).validity;
13543 }
13544 get validationMessage() {
13545 return _classPrivateFieldGet(this, _delegate).validationMessage;
13546 }
13547 get willValidate() {
13548 return _classPrivateFieldGet(this, _delegate).willValidate;
13549 }
13550 get type() {
13551 return this.localName;
13552 }
13553 get toolbarElement() {
13554 if (this.hasAttribute("toolbar")) {
13555 var _this$ownerDocument;
13556 return (_this$ownerDocument = this.ownerDocument) === null || _this$ownerDocument === void 0 ? void 0 : _this$ownerDocument.getElementById(this.getAttribute("toolbar"));
13557 } else if (this.parentNode) {
13558 const toolbarId = "trix-toolbar-".concat(this.trixId);
13559 this.setAttribute("toolbar", toolbarId);
13560 const element = makeElement("trix-toolbar", {
13561 id: toolbarId
13562 });
13563 this.parentNode.insertBefore(element, this);
13564 return element;
13565 } else {
13566 return undefined;
13567 }
13568 }
13569 get form() {
13570 var _this$inputElement;
13571 return (_this$inputElement = this.inputElement) === null || _this$inputElement === void 0 ? void 0 : _this$inputElement.form;
13572 }
13573 get inputElement() {
13574 if (this.hasAttribute("input")) {
13575 var _this$ownerDocument2;
13576 return (_this$ownerDocument2 = this.ownerDocument) === null || _this$ownerDocument2 === void 0 ? void 0 : _this$ownerDocument2.getElementById(this.getAttribute("input"));
13577 } else if (this.parentNode) {
13578 const inputId = "trix-input-".concat(this.trixId);
13579 this.setAttribute("input", inputId);
13580 const element = makeElement("input", {
13581 type: "hidden",
13582 id: inputId
13583 });
13584 this.parentNode.insertBefore(element, this.nextElementSibling);
13585 return element;
13586 } else {
13587 return undefined;
13588 }
13589 }
13590 get editor() {
13591 var _this$editorControlle;
13592 return (_this$editorControlle = this.editorController) === null || _this$editorControlle === void 0 ? void 0 : _this$editorControlle.editor;
13593 }
13594 get name() {
13595 var _this$inputElement2;
13596 return (_this$inputElement2 = this.inputElement) === null || _this$inputElement2 === void 0 ? void 0 : _this$inputElement2.name;
13597 }
13598 get value() {
13599 var _this$inputElement3;
13600 return (_this$inputElement3 = this.inputElement) === null || _this$inputElement3 === void 0 ? void 0 : _this$inputElement3.value;
13601 }
13602 set value(defaultValue) {
13603 var _this$editor;
13604 this.defaultValue = defaultValue;
13605 (_this$editor = this.editor) === null || _this$editor === void 0 || _this$editor.loadHTML(this.defaultValue);
13606 }
13607
13608 // Controller delegate methods
13609
13610 notify(message, data) {
13611 if (this.editorController) {
13612 return triggerEvent("trix-".concat(message), {
13613 onElement: this,
13614 attributes: data
13615 });
13616 }
13617 }
13618 setFormValue(value) {
13619 if (this.inputElement) {
13620 this.inputElement.value = value;
13621 _classPrivateFieldGet(this, _delegate).setFormValue(value);
13622 }
13623 }
13624
13625 // Element lifecycle
13626
13627 connectedCallback() {
13628 if (!this.hasAttribute("data-trix-internal")) {
13629 makeEditable(this);
13630 addAccessibilityRole(this);
13631 if (!this.editorController) {
13632 triggerEvent("trix-before-initialize", {
13633 onElement: this
13634 });
13635 this.editorController = new EditorController({
13636 editorElement: this,
13637 html: this.defaultValue = this.value
13638 });
13639 requestAnimationFrame(() => triggerEvent("trix-initialize", {
13640 onElement: this
13641 }));
13642 }
13643 this.editorController.registerSelectionManager();
13644 _classPrivateFieldGet(this, _delegate).connectedCallback();
13645 autofocus(this);
13646 }
13647 }
13648 disconnectedCallback() {
13649 var _this$editorControlle2;
13650 (_this$editorControlle2 = this.editorController) === null || _this$editorControlle2 === void 0 || _this$editorControlle2.unregisterSelectionManager();
13651 _classPrivateFieldGet(this, _delegate).disconnectedCallback();
13652 }
13653
13654 // Form support
13655
13656 checkValidity() {
13657 return _classPrivateFieldGet(this, _delegate).checkValidity();
13658 }
13659 reportValidity() {
13660 return _classPrivateFieldGet(this, _delegate).reportValidity();
13661 }
13662 setCustomValidity(validationMessage) {
13663 _classPrivateFieldGet(this, _delegate).setCustomValidity(validationMessage);
13664 }
13665 formDisabledCallback(disabled) {
13666 if (this.inputElement) {
13667 this.inputElement.disabled = disabled;
13668 }
13669 this.toggleAttribute("contenteditable", !disabled);
13670 }
13671 formResetCallback() {
13672 this.reset();
13673 }
13674 reset() {
13675 this.value = this.defaultValue;
13676 }
13677 }
13678 _defineProperty(TrixEditorElement, "formAssociated", "ElementInternals" in window);
13679
13680 var elements = /*#__PURE__*/Object.freeze({
13681 __proto__: null,
13682 TrixEditorElement: TrixEditorElement,
13683 TrixToolbarElement: TrixToolbarElement
13684 });
13685
13686 var filters = /*#__PURE__*/Object.freeze({
13687 __proto__: null,
13688 Filter: Filter,
13689 attachmentGalleryFilter: attachmentGalleryFilter
13690 });
13691
13692 const Trix = {
13693 VERSION: version,
13694 config,
13695 core,
13696 models,
13697 views,
13698 controllers,
13699 observers,
13700 operations,
13701 elements,
13702 filters
13703 };
13704
13705 // Expose models under the Trix constant for compatibility with v1
13706 Object.assign(Trix, models);
13707 function start() {
13708 if (!customElements.get("trix-toolbar")) {
13709 customElements.define("trix-toolbar", TrixToolbarElement);
13710 }
13711 if (!customElements.get("trix-editor")) {
13712 customElements.define("trix-editor", TrixEditorElement);
13713 }
13714 }
13715 window.Trix = Trix;
13716 setTimeout(start, 0);
13717
13718 return Trix;
13719
13720}));
diff --git a/public/assets/trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js.gz b/public/assets/trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js.gz
new file mode 100644
index 0000000..8abb305
--- /dev/null
+++ b/public/assets/trix-488ac88b50edee8aab73dd826e9967075eed9000a13fd13cbcc17745f86650cc.js.gz
Binary files differ
diff --git a/public/assets/trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css b/public/assets/trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css
new file mode 100644
index 0000000..b07d206
--- /dev/null
+++ b/public/assets/trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css
@@ -0,0 +1,412 @@
1trix-editor {
2 border: 1px solid #bbb;
3 border-radius: 3px;
4 margin: 0;
5 padding: 0.4em 0.6em;
6 min-height: 5em;
7 outline: none; }
8
9trix-toolbar * {
10 box-sizing: border-box; }
11
12trix-toolbar .trix-button-row {
13 display: flex;
14 flex-wrap: nowrap;
15 justify-content: space-between;
16 overflow-x: auto; }
17
18trix-toolbar .trix-button-group {
19 display: flex;
20 margin-bottom: 10px;
21 border: 1px solid #bbb;
22 border-top-color: #ccc;
23 border-bottom-color: #888;
24 border-radius: 3px; }
25 trix-toolbar .trix-button-group:not(:first-child) {
26 margin-left: 1.5vw; }
27 @media (max-width: 768px) {
28 trix-toolbar .trix-button-group:not(:first-child) {
29 margin-left: 0; } }
30
31trix-toolbar .trix-button-group-spacer {
32 flex-grow: 1; }
33 @media (max-width: 768px) {
34 trix-toolbar .trix-button-group-spacer {
35 display: none; } }
36
37trix-toolbar .trix-button {
38 position: relative;
39 float: left;
40 color: rgba(0, 0, 0, 0.6);
41 font-size: 0.75em;
42 font-weight: 600;
43 white-space: nowrap;
44 padding: 0 0.5em;
45 margin: 0;
46 outline: none;
47 border: none;
48 border-bottom: 1px solid #ddd;
49 border-radius: 0;
50 background: transparent; }
51 trix-toolbar .trix-button:not(:first-child) {
52 border-left: 1px solid #ccc; }
53 trix-toolbar .trix-button.trix-active {
54 background: #cbeefa;
55 color: black; }
56 trix-toolbar .trix-button:not(:disabled) {
57 cursor: pointer; }
58 trix-toolbar .trix-button:disabled {
59 color: rgba(0, 0, 0, 0.125); }
60 @media (max-width: 768px) {
61 trix-toolbar .trix-button {
62 letter-spacing: -0.01em;
63 padding: 0 0.3em; } }
64
65trix-toolbar .trix-button--icon {
66 font-size: inherit;
67 width: 2.6em;
68 height: 1.6em;
69 max-width: calc(0.8em + 4vw);
70 text-indent: -9999px; }
71 @media (max-width: 768px) {
72 trix-toolbar .trix-button--icon {
73 height: 2em;
74 max-width: calc(0.8em + 3.5vw); } }
75 trix-toolbar .trix-button--icon::before {
76 display: inline-block;
77 position: absolute;
78 top: 0;
79 right: 0;
80 bottom: 0;
81 left: 0;
82 opacity: 0.6;
83 content: "";
84 background-position: center;
85 background-repeat: no-repeat;
86 background-size: contain; }
87 @media (max-width: 768px) {
88 trix-toolbar .trix-button--icon::before {
89 right: 6%;
90 left: 6%; } }
91 trix-toolbar .trix-button--icon.trix-active::before {
92 opacity: 1; }
93 trix-toolbar .trix-button--icon:disabled::before {
94 opacity: 0.125; }
95
96trix-toolbar .trix-button--icon-attach::before {
97 background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M10.5%2018V7.5c0-2.25%203-2.25%203%200V18c0%204.125-6%204.125-6%200V7.5c0-6.375%209-6.375%209%200V18%22%20stroke%3D%22%23000%22%20stroke-width%3D%222%22%20stroke-miterlimit%3D%2210%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%2F%3E%3C%2Fsvg%3E");
98 top: 8%;
99 bottom: 4%; }
100
101trix-toolbar .trix-button--icon-bold::before {
102 background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M6.522%2019.242a.5.5%200%200%201-.5-.5V5.35a.5.5%200%200%201%20.5-.5h5.783c1.347%200%202.46.345%203.24.982.783.64%201.216%201.562%201.216%202.683%200%201.13-.587%202.129-1.476%202.71a.35.35%200%200%200%20.049.613c1.259.56%202.101%201.742%202.101%203.22%200%201.282-.483%202.334-1.363%203.063-.876.726-2.132%201.12-3.66%201.12h-5.89ZM9.27%207.347v3.362h1.97c.766%200%201.347-.17%201.733-.464.38-.291.587-.716.587-1.27%200-.53-.183-.928-.513-1.198-.334-.273-.838-.43-1.505-.43H9.27Zm0%205.606v3.791h2.389c.832%200%201.448-.177%201.853-.497.399-.315.614-.786.614-1.423%200-.62-.22-1.077-.63-1.385-.418-.313-1.053-.486-1.905-.486H9.27Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
103
104trix-toolbar .trix-button--icon-italic::before {
105 background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M9%205h6.5v2h-2.23l-2.31%2010H13v2H6v-2h2.461l2.306-10H9V5Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
106
107trix-toolbar .trix-button--icon-link::before {
108 background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M18.948%205.258a4.337%204.337%200%200%200-6.108%200L11.217%206.87a.993.993%200%200%200%200%201.41c.392.39%201.027.39%201.418%200l1.623-1.613a2.323%202.323%200%200%201%203.271%200%202.29%202.29%200%200%201%200%203.251l-2.393%202.38a3.021%203.021%200%200%201-4.255%200l-.05-.049a1.007%201.007%200%200%200-1.418%200%20.993.993%200%200%200%200%201.41l.05.049a5.036%205.036%200%200%200%207.091%200l2.394-2.38a4.275%204.275%200%200%200%200-6.072Zm-13.683%2013.6a4.337%204.337%200%200%200%206.108%200l1.262-1.255a.993.993%200%200%200%200-1.41%201.007%201.007%200%200%200-1.418%200L9.954%2017.45a2.323%202.323%200%200%201-3.27%200%202.29%202.29%200%200%201%200-3.251l2.344-2.331a2.579%202.579%200%200%201%203.631%200c.392.39%201.027.39%201.419%200a.993.993%200%200%200%200-1.41%204.593%204.593%200%200%200-6.468%200l-2.345%202.33a4.275%204.275%200%200%200%200%206.072Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
109
110trix-toolbar .trix-button--icon-strike::before {
111 background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M6%2014.986c.088%202.647%202.246%204.258%205.635%204.258%203.496%200%205.713-1.728%205.713-4.463%200-.275-.02-.536-.062-.781h-3.461c.398.293.573.654.573%201.123%200%201.035-1.074%201.787-2.646%201.787-1.563%200-2.773-.762-2.91-1.924H6ZM6.432%2010h3.763c-.632-.314-.914-.715-.914-1.273%200-1.045.977-1.739%202.432-1.739%201.475%200%202.52.723%202.617%201.914h2.764c-.05-2.548-2.11-4.238-5.39-4.238-3.145%200-5.392%201.719-5.392%204.316%200%20.363.04.703.12%201.02ZM4%2011a1%201%200%201%200%200%202h15a1%201%200%201%200%200-2H4Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
112
113trix-toolbar .trix-button--icon-quote::before {
114 background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M4.581%208.471c.44-.5%201.056-.834%201.758-.995C8.074%207.17%209.201%207.822%2010%208.752c1.354%201.578%201.33%203.555.394%205.277-.941%201.731-2.788%203.163-4.988%203.56a.622.622%200%200%201-.653-.317c-.113-.205-.121-.49.16-.764.294-.286.567-.566.791-.835.222-.266.413-.54.524-.815.113-.28.156-.597.026-.908-.128-.303-.39-.524-.72-.69a3.02%203.02%200%200%201-1.674-2.7c0-.905.283-1.59.72-2.088Zm9.419%200c.44-.5%201.055-.834%201.758-.995%201.734-.306%202.862.346%203.66%201.276%201.355%201.578%201.33%203.555.395%205.277-.941%201.731-2.789%203.163-4.988%203.56a.622.622%200%200%201-.653-.317c-.113-.205-.122-.49.16-.764.294-.286.567-.566.791-.835.222-.266.412-.54.523-.815.114-.28.157-.597.026-.908-.127-.303-.39-.524-.72-.69a3.02%203.02%200%200%201-1.672-2.701c0-.905.283-1.59.72-2.088Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
115
116trix-toolbar .trix-button--icon-heading-1::before {
117 background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M21.5%207.5v-3h-12v3H14v13h3v-13h4.5ZM9%2013.5h3.5v-3h-10v3H6v7h3v-7Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
118
119trix-toolbar .trix-button--icon-code::before {
120 background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M3.293%2011.293a1%201%200%200%200%200%201.414l4%204a1%201%200%201%200%201.414-1.414L5.414%2012l3.293-3.293a1%201%200%200%200-1.414-1.414l-4%204Zm13.414%205.414%204-4a1%201%200%200%200%200-1.414l-4-4a1%201%200%201%200-1.414%201.414L18.586%2012l-3.293%203.293a1%201%200%200%200%201.414%201.414Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
121
122trix-toolbar .trix-button--icon-bullet-list::before {
123 background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M5%207.5a1.5%201.5%200%201%200%200-3%201.5%201.5%200%200%200%200%203ZM8%206a1%201%200%200%201%201-1h11a1%201%200%201%201%200%202H9a1%201%200%200%201-1-1Zm1%205a1%201%200%201%200%200%202h11a1%201%200%201%200%200-2H9Zm0%206a1%201%200%201%200%200%202h11a1%201%200%201%200%200-2H9Zm-2.5-5a1.5%201.5%200%201%201-3%200%201.5%201.5%200%200%201%203%200ZM5%2019.5a1.5%201.5%200%201%200%200-3%201.5%201.5%200%200%200%200%203Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
124
125trix-toolbar .trix-button--icon-number-list::before {
126 background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M3%204h2v4H4V5H3V4Zm5%202a1%201%200%200%201%201-1h11a1%201%200%201%201%200%202H9a1%201%200%200%201-1-1Zm1%205a1%201%200%201%200%200%202h11a1%201%200%201%200%200-2H9Zm0%206a1%201%200%201%200%200%202h11a1%201%200%201%200%200-2H9Zm-3.5-7H6v1l-1.5%202H6v1H3v-1l1.667-2H3v-1h2.5ZM3%2017v-1h3v4H3v-1h2v-.5H4v-1h1V17H3Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
127
128trix-toolbar .trix-button--icon-undo::before {
129 background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M3%2014a1%201%200%200%200%201%201h6a1%201%200%201%200%200-2H6.257c2.247-2.764%205.151-3.668%207.579-3.264%202.589.432%204.739%202.356%205.174%205.405a1%201%200%200%200%201.98-.283c-.564-3.95-3.415-6.526-6.825-7.095C11.084%207.25%207.63%208.377%205%2011.39V8a1%201%200%200%200-2%200v6Zm2-1Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
130
131trix-toolbar .trix-button--icon-redo::before {
132 background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M21%2014a1%201%200%200%201-1%201h-6a1%201%200%201%201%200-2h3.743c-2.247-2.764-5.151-3.668-7.579-3.264-2.589.432-4.739%202.356-5.174%205.405a1%201%200%200%201-1.98-.283c.564-3.95%203.415-6.526%206.826-7.095%203.08-.513%206.534.614%209.164%203.626V8a1%201%200%201%201%202%200v6Zm-2-1Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
133
134trix-toolbar .trix-button--icon-decrease-nesting-level::before {
135 background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M5%206a1%201%200%200%201%201-1h12a1%201%200%201%201%200%202H6a1%201%200%200%201-1-1Zm4%205a1%201%200%201%200%200%202h9a1%201%200%201%200%200-2H9Zm-3%206a1%201%200%201%200%200%202h12a1%201%200%201%200%200-2H6Zm-3.707-5.707a1%201%200%200%200%200%201.414l2%202a1%201%200%201%200%201.414-1.414L4.414%2012l1.293-1.293a1%201%200%200%200-1.414-1.414l-2%202Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
136
137trix-toolbar .trix-button--icon-increase-nesting-level::before {
138 background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M5%206a1%201%200%200%201%201-1h12a1%201%200%201%201%200%202H6a1%201%200%200%201-1-1Zm4%205a1%201%200%201%200%200%202h9a1%201%200%201%200%200-2H9Zm-3%206a1%201%200%201%200%200%202h12a1%201%200%201%200%200-2H6Zm-2.293-2.293%202-2a1%201%200%200%200%200-1.414l-2-2a1%201%200%201%200-1.414%201.414L3.586%2012l-1.293%201.293a1%201%200%201%200%201.414%201.414Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
139
140trix-toolbar .trix-dialogs {
141 position: relative; }
142
143trix-toolbar .trix-dialog {
144 position: absolute;
145 top: 0;
146 left: 0;
147 right: 0;
148 font-size: 0.75em;
149 padding: 15px 10px;
150 background: #fff;
151 box-shadow: 0 0.3em 1em #ccc;
152 border-top: 2px solid #888;
153 border-radius: 5px;
154 z-index: 5; }
155
156trix-toolbar .trix-input--dialog {
157 font-size: inherit;
158 font-weight: normal;
159 padding: 0.5em 0.8em;
160 margin: 0 10px 0 0;
161 border-radius: 3px;
162 border: 1px solid #bbb;
163 background-color: #fff;
164 box-shadow: none;
165 outline: none;
166 -webkit-appearance: none;
167 -moz-appearance: none; }
168 trix-toolbar .trix-input--dialog.validate:invalid {
169 box-shadow: #F00 0px 0px 1.5px 1px; }
170
171trix-toolbar .trix-button--dialog {
172 font-size: inherit;
173 padding: 0.5em;
174 border-bottom: none; }
175
176trix-toolbar .trix-dialog--link {
177 max-width: 600px; }
178
179trix-toolbar .trix-dialog__link-fields {
180 display: flex;
181 align-items: baseline; }
182 trix-toolbar .trix-dialog__link-fields .trix-input {
183 flex: 1; }
184 trix-toolbar .trix-dialog__link-fields .trix-button-group {
185 flex: 0 0 content;
186 margin: 0; }
187
188trix-editor [data-trix-mutable]:not(.attachment__caption-editor) {
189 -webkit-user-select: none;
190 -moz-user-select: none;
191 -ms-user-select: none;
192 user-select: none; }
193
194trix-editor [data-trix-mutable]::-moz-selection,
195trix-editor [data-trix-cursor-target]::-moz-selection, trix-editor [data-trix-mutable] ::-moz-selection {
196 background: none; }
197
198trix-editor [data-trix-mutable]::selection,
199trix-editor [data-trix-cursor-target]::selection, trix-editor [data-trix-mutable] ::selection {
200 background: none; }
201
202trix-editor .attachment__caption-editor:focus[data-trix-mutable]::-moz-selection {
203 background: highlight; }
204
205trix-editor .attachment__caption-editor:focus[data-trix-mutable]::selection {
206 background: highlight; }
207
208trix-editor [data-trix-mutable].attachment.attachment--file {
209 box-shadow: 0 0 0 2px highlight;
210 border-color: transparent; }
211
212trix-editor [data-trix-mutable].attachment img {
213 box-shadow: 0 0 0 2px highlight; }
214
215trix-editor .attachment {
216 position: relative; }
217 trix-editor .attachment:hover {
218 cursor: default; }
219
220trix-editor .attachment--preview .attachment__caption:hover {
221 cursor: text; }
222
223trix-editor .attachment__progress {
224 position: absolute;
225 z-index: 1;
226 height: 20px;
227 top: calc(50% - 10px);
228 left: 5%;
229 width: 90%;
230 opacity: 0.9;
231 transition: opacity 200ms ease-in; }
232 trix-editor .attachment__progress[value="100"] {
233 opacity: 0; }
234
235trix-editor .attachment__caption-editor {
236 display: inline-block;
237 width: 100%;
238 margin: 0;
239 padding: 0;
240 font-size: inherit;
241 font-family: inherit;
242 line-height: inherit;
243 color: inherit;
244 text-align: center;
245 vertical-align: top;
246 border: none;
247 outline: none;
248 -webkit-appearance: none;
249 -moz-appearance: none; }
250
251trix-editor .attachment__toolbar {
252 position: absolute;
253 z-index: 1;
254 top: -0.9em;
255 left: 0;
256 width: 100%;
257 text-align: center; }
258
259trix-editor .trix-button-group {
260 display: inline-flex; }
261
262trix-editor .trix-button {
263 position: relative;
264 float: left;
265 color: #666;
266 white-space: nowrap;
267 font-size: 80%;
268 padding: 0 0.8em;
269 margin: 0;
270 outline: none;
271 border: none;
272 border-radius: 0;
273 background: transparent; }
274 trix-editor .trix-button:not(:first-child) {
275 border-left: 1px solid #ccc; }
276 trix-editor .trix-button.trix-active {
277 background: #cbeefa; }
278 trix-editor .trix-button:not(:disabled) {
279 cursor: pointer; }
280
281trix-editor .trix-button--remove {
282 text-indent: -9999px;
283 display: inline-block;
284 padding: 0;
285 outline: none;
286 width: 1.8em;
287 height: 1.8em;
288 line-height: 1.8em;
289 border-radius: 50%;
290 background-color: #fff;
291 border: 2px solid highlight;
292 box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.25); }
293 trix-editor .trix-button--remove::before {
294 display: inline-block;
295 position: absolute;
296 top: 0;
297 right: 0;
298 bottom: 0;
299 left: 0;
300 opacity: 0.7;
301 content: "";
302 background-image: url("data:image/svg+xml,%3Csvg%20height%3D%2224%22%20width%3D%2224%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M19%206.41%2017.59%205%2012%2010.59%206.41%205%205%206.41%2010.59%2012%205%2017.59%206.41%2019%2012%2013.41%2017.59%2019%2019%2017.59%2013.41%2012z%22%2F%3E%3Cpath%20d%3D%22M0%200h24v24H0z%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E");
303 background-position: center;
304 background-repeat: no-repeat;
305 background-size: 90%; }
306 trix-editor .trix-button--remove:hover {
307 border-color: #333; }
308 trix-editor .trix-button--remove:hover::before {
309 opacity: 1; }
310
311trix-editor .attachment__metadata-container {
312 position: relative; }
313
314trix-editor .attachment__metadata {
315 position: absolute;
316 left: 50%;
317 top: 2em;
318 transform: translate(-50%, 0);
319 max-width: 90%;
320 padding: 0.1em 0.6em;
321 font-size: 0.8em;
322 color: #fff;
323 background-color: rgba(0, 0, 0, 0.7);
324 border-radius: 3px; }
325 trix-editor .attachment__metadata .attachment__name {
326 display: inline-block;
327 max-width: 100%;
328 vertical-align: bottom;
329 overflow: hidden;
330 text-overflow: ellipsis;
331 white-space: nowrap; }
332 trix-editor .attachment__metadata .attachment__size {
333 margin-left: 0.2em;
334 white-space: nowrap; }
335
336.trix-content {
337 line-height: 1.5;
338 overflow-wrap: break-word;
339 word-break: break-word; }
340 .trix-content * {
341 box-sizing: border-box;
342 margin: 0;
343 padding: 0; }
344 .trix-content h1 {
345 font-size: 1.2em;
346 line-height: 1.2; }
347 .trix-content blockquote {
348 border: 0 solid #ccc;
349 border-left-width: 0.3em;
350 margin-left: 0.3em;
351 padding-left: 0.6em; }
352 .trix-content [dir=rtl] blockquote,
353 .trix-content blockquote[dir=rtl] {
354 border-width: 0;
355 border-right-width: 0.3em;
356 margin-right: 0.3em;
357 padding-right: 0.6em; }
358 .trix-content li {
359 margin-left: 1em; }
360 .trix-content [dir=rtl] li {
361 margin-right: 1em; }
362 .trix-content pre {
363 display: inline-block;
364 width: 100%;
365 vertical-align: top;
366 font-family: monospace;
367 font-size: 0.9em;
368 padding: 0.5em;
369 white-space: pre;
370 background-color: #eee;
371 overflow-x: auto; }
372 .trix-content img {
373 max-width: 100%;
374 height: auto; }
375 .trix-content .attachment {
376 display: inline-block;
377 position: relative;
378 max-width: 100%; }
379 .trix-content .attachment a {
380 color: inherit;
381 text-decoration: none; }
382 .trix-content .attachment a:hover, .trix-content .attachment a:visited:hover {
383 color: inherit; }
384 .trix-content .attachment__caption {
385 text-align: center; }
386 .trix-content .attachment__caption .attachment__name + .attachment__size::before {
387 content: ' \2022 '; }
388 .trix-content .attachment--preview {
389 width: 100%;
390 text-align: center; }
391 .trix-content .attachment--preview .attachment__caption {
392 color: #666;
393 font-size: 0.9em;
394 line-height: 1.2; }
395 .trix-content .attachment--file {
396 color: #333;
397 line-height: 1;
398 margin: 0 2px 2px 2px;
399 padding: 0.4em 1em;
400 border: 1px solid #bbb;
401 border-radius: 5px; }
402 .trix-content .attachment-gallery {
403 display: flex;
404 flex-wrap: wrap;
405 position: relative; }
406 .trix-content .attachment-gallery .attachment {
407 flex: 1 0 33%;
408 padding: 0 0.5em;
409 max-width: 33%; }
410 .trix-content .attachment-gallery.attachment-gallery--2 .attachment, .trix-content .attachment-gallery.attachment-gallery--4 .attachment {
411 flex-basis: 50%;
412 max-width: 50%; }
diff --git a/public/assets/trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css.gz b/public/assets/trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css.gz
new file mode 100644
index 0000000..f20eeb7
--- /dev/null
+++ b/public/assets/trix-4c7f56767699ae6c08f21004c9dc23a1b76b0734b0fca61d4534900ee0fef211.css.gz
Binary files differ
diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css
index 7031f77..1a29eff 100644
--- a/public/stylesheets/admin.css
+++ b/public/stylesheets/admin.css
@@ -116,6 +116,28 @@ input[type=submit],
116 text-transform: lowercase; 116 text-transform: lowercase;
117} 117}
118 118
119/* button_to forms: render submit inputs as plain links */
120form.button_to {
121 display: inline;
122 margin: 0;
123 padding: 0;
124}
125
126form.button_to input[type="submit"] {
127 background: none;
128 border: none;
129 padding: 0;
130 margin: 0;
131 font: inherit;
132 color: inherit;
133 cursor: pointer;
134 text-decoration: underline;
135}
136
137form.button_to input[type="submit"]:hover {
138 color: inherit;
139}
140
119#admin_wizard { 141#admin_wizard {
120 margin-bottom: 2rem; 142 margin-bottom: 2rem;
121} 143}