blacklight-spotlight 3.5.0.1 → 3.6.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (213) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +20 -0
  3. data/Rakefile +6 -7
  4. data/app/assets/config/spotlight/manifest.js +1 -0
  5. data/app/assets/javascripts/spotlight/application.js +14 -14
  6. data/app/assets/javascripts/spotlight/spotlight.esm.js +7148 -0
  7. data/app/assets/javascripts/spotlight/spotlight.esm.js.map +1 -0
  8. data/app/assets/javascripts/spotlight/spotlight.js +7148 -15
  9. data/app/assets/javascripts/spotlight/spotlight.js.map +1 -0
  10. data/app/assets/stylesheets/spotlight/_catalog.scss +16 -0
  11. data/app/controllers/concerns/spotlight/base.rb +2 -1
  12. data/app/controllers/concerns/spotlight/controller.rb +10 -0
  13. data/app/controllers/spotlight/admin_users_controller.rb +4 -4
  14. data/app/controllers/spotlight/appearances_controller.rb +6 -6
  15. data/app/controllers/spotlight/browse_controller.rb +1 -1
  16. data/app/controllers/spotlight/catalog_controller.rb +20 -15
  17. data/app/controllers/spotlight/concerns/application_controller.rb +1 -0
  18. data/app/controllers/spotlight/concerns/catalog_search_context.rb +2 -2
  19. data/app/controllers/spotlight/contacts_controller.rb +6 -6
  20. data/app/controllers/spotlight/dashboards_controller.rb +2 -2
  21. data/app/controllers/spotlight/exhibits_controller.rb +19 -19
  22. data/app/controllers/spotlight/featured_images_controller.rb +1 -1
  23. data/app/controllers/spotlight/home_pages_controller.rb +7 -7
  24. data/app/controllers/spotlight/lock_controller.rb +1 -1
  25. data/app/controllers/spotlight/metadata_configurations_controller.rb +2 -2
  26. data/app/controllers/spotlight/pages_controller.rb +4 -3
  27. data/app/controllers/spotlight/search_configurations_controller.rb +6 -6
  28. data/app/controllers/spotlight/searches_controller.rb +22 -22
  29. data/app/controllers/spotlight/solr_controller.rb +1 -1
  30. data/app/controllers/spotlight/translations_controller.rb +8 -10
  31. data/app/controllers/spotlight/versions_controller.rb +2 -1
  32. data/app/helpers/spotlight/application_helper.rb +33 -17
  33. data/app/helpers/spotlight/crud_link_helpers.rb +12 -2
  34. data/app/helpers/spotlight/pages_helper.rb +1 -1
  35. data/app/helpers/spotlight/roles_helper.rb +2 -2
  36. data/app/helpers/spotlight/title_helper.rb +1 -1
  37. data/app/helpers/spotlight/translations_helper.rb +1 -3
  38. data/app/javascript/spotlight/admin/add_another.es6 +24 -0
  39. data/app/javascript/spotlight/admin/add_image_selector.es6 +38 -0
  40. data/app/javascript/spotlight/admin/add_new_button.es6 +77 -0
  41. data/app/javascript/spotlight/admin/appearance.es6 +22 -0
  42. data/app/javascript/spotlight/admin/blacklight_configuration.es6 +65 -0
  43. data/app/{assets/javascripts → javascript}/spotlight/admin/block_mixins/autocompleteable.js +8 -8
  44. data/app/{assets/javascripts → javascript}/spotlight/admin/block_mixins/formable.js +1 -1
  45. data/app/javascript/spotlight/admin/block_mixins/plustextable.js +58 -0
  46. data/app/{assets/javascripts → javascript}/spotlight/admin/blocks/block.js +2 -1
  47. data/app/javascript/spotlight/admin/blocks/browse_block.js +86 -0
  48. data/app/javascript/spotlight/admin/blocks/browse_group_categories_block.js +88 -0
  49. data/app/{assets/javascripts → javascript}/spotlight/admin/blocks/iframe_block.js +7 -11
  50. data/app/{assets/javascripts → javascript}/spotlight/admin/blocks/link_to_search_block.js +0 -2
  51. data/app/javascript/spotlight/admin/blocks/oembed_block.js +41 -0
  52. data/app/{assets/javascripts → javascript}/spotlight/admin/blocks/pages_block.js +1 -1
  53. data/app/{assets/javascripts → javascript}/spotlight/admin/blocks/resources_block.js +45 -42
  54. data/app/{assets/javascripts → javascript}/spotlight/admin/blocks/rule_block.js +2 -4
  55. data/app/{assets/javascripts → javascript}/spotlight/admin/blocks/search_result_block.js +7 -9
  56. data/app/{assets/javascripts → javascript}/spotlight/admin/blocks/solr_documents_base_block.js +22 -22
  57. data/app/{assets/javascripts → javascript}/spotlight/admin/blocks/solr_documents_block.js +7 -7
  58. data/app/{assets/javascripts → javascript}/spotlight/admin/blocks/solr_documents_carousel_block.js +14 -15
  59. data/app/javascript/spotlight/admin/blocks/uploaded_items_block.js +147 -0
  60. data/app/javascript/spotlight/admin/checkbox_submit.es6 +75 -0
  61. data/app/javascript/spotlight/admin/copy_email_addresses.es6 +5 -0
  62. data/app/{assets/javascripts/spotlight/admin/crop.es6 → javascript/spotlight/admin/crop.js} +5 -4
  63. data/app/javascript/spotlight/admin/croppable.es6 +10 -0
  64. data/app/{assets/javascripts/spotlight/admin/edit_in_place.js → javascript/spotlight/admin/edit_in_place.es6} +6 -13
  65. data/app/javascript/spotlight/admin/exhibit_tag_autocomplete.es6 +39 -0
  66. data/app/javascript/spotlight/admin/exhibits.es6 +59 -0
  67. data/app/{assets/javascripts/spotlight/admin/form_observer.js → javascript/spotlight/admin/form_observer.es6} +23 -21
  68. data/app/javascript/spotlight/admin/index.js +85 -0
  69. data/app/javascript/spotlight/admin/locks.es6 +12 -0
  70. data/app/{assets/javascripts → javascript}/spotlight/admin/multi_image_selector.js +2 -1
  71. data/app/javascript/spotlight/admin/pages.es6 +42 -0
  72. data/app/{assets/javascripts/spotlight/admin/progress_monitor.js → javascript/spotlight/admin/progress_monitor.es6} +5 -9
  73. data/app/javascript/spotlight/admin/readonly_checkbox.es6 +8 -0
  74. data/app/{assets/javascripts → javascript}/spotlight/admin/search_typeahead.js +3 -46
  75. data/app/{assets/javascripts/spotlight/admin/select_related_input.js → javascript/spotlight/admin/select_related_input.es6} +6 -3
  76. data/app/{assets/javascripts → javascript}/spotlight/admin/sir-trevor/block_controls.js +6 -4
  77. data/app/{assets/javascripts → javascript}/spotlight/admin/sir-trevor/block_limits.js +2 -0
  78. data/app/{assets/javascripts → javascript}/spotlight/admin/spotlight_nestable.js +4 -8
  79. data/app/javascript/spotlight/admin/tabs.es6 +8 -0
  80. data/app/{assets/javascripts/spotlight/admin/translation_progress.js → javascript/spotlight/admin/translation_progress.es6} +6 -13
  81. data/app/{assets/javascripts/spotlight/admin/users.js → javascript/spotlight/admin/users.es6} +7 -17
  82. data/app/javascript/spotlight/admin/visibility_toggle.es6 +23 -0
  83. data/app/javascript/spotlight/index.js +10 -0
  84. data/app/javascript/spotlight/spotlight.js +32 -0
  85. data/app/{assets/javascripts/spotlight/user/analytics.js → javascript/spotlight/user/analytics.es6} +4 -4
  86. data/app/{assets/javascripts/spotlight/user/browse_group_categories.js → javascript/spotlight/user/browse_group_categories.es6} +4 -13
  87. data/app/javascript/spotlight/user/carousel.es6 +5 -0
  88. data/app/{assets/javascripts/spotlight/user/clear_form_button.js → javascript/spotlight/user/clear_form_button.es6} +5 -9
  89. data/app/javascript/spotlight/user/index.js +17 -0
  90. data/app/{assets/javascripts/spotlight/user/report_a_problem.js → javascript/spotlight/user/report_a_problem.es6} +6 -15
  91. data/app/javascript/spotlight/user/zpr_links.es6 +44 -0
  92. data/app/jobs/spotlight/add_uploads_from_csv.rb +1 -2
  93. data/app/models/concerns/spotlight/browse_category_search_builder.rb +7 -3
  94. data/app/models/concerns/spotlight/exhibit_defaults.rb +1 -1
  95. data/app/models/concerns/spotlight/exhibit_documents.rb +2 -2
  96. data/app/models/concerns/spotlight/resources/web.rb +1 -1
  97. data/app/models/concerns/spotlight/solr_document/atomic_updates.rb +1 -1
  98. data/app/models/concerns/spotlight/solr_document/finder.rb +2 -2
  99. data/app/models/concerns/spotlight/solr_document.rb +2 -2
  100. data/app/models/concerns/spotlight/translatables.rb +1 -1
  101. data/app/models/sir_trevor_rails/blocks/displayable.rb +2 -2
  102. data/app/models/sir_trevor_rails/blocks/solr_documents_block.rb +17 -6
  103. data/app/models/spotlight/analytics/ga.rb +5 -5
  104. data/app/models/spotlight/blacklight_configuration.rb +12 -12
  105. data/app/models/spotlight/bulk_update.rb +1 -0
  106. data/app/models/spotlight/contact_email.rb +1 -1
  107. data/app/models/spotlight/contact_form.rb +1 -1
  108. data/app/models/spotlight/exhibit.rb +1 -1
  109. data/app/models/spotlight/featured_image.rb +1 -2
  110. data/app/models/spotlight/lock.rb +1 -1
  111. data/app/models/spotlight/main_navigation.rb +1 -5
  112. data/app/models/spotlight/page.rb +1 -1
  113. data/app/models/spotlight/resources/iiif_manifest.rb +4 -4
  114. data/app/models/spotlight/resources/iiif_service.rb +1 -1
  115. data/app/models/spotlight/resources/upload.rb +3 -6
  116. data/app/models/spotlight/search.rb +6 -2
  117. data/app/models/translation.rb +2 -0
  118. data/app/presenters/spotlight/iiif_manifest_presenter.rb +2 -1
  119. data/app/services/spotlight/iiif_resource_resolver.rb +10 -10
  120. data/app/uploaders/spotlight/bulk_updates_uploader.rb +1 -0
  121. data/app/views/layouts/spotlight/base.html.erb +1 -0
  122. data/app/views/shared/_exhibit_navbar.html.erb +6 -1
  123. data/app/views/spotlight/admin_users/index.html.erb +9 -3
  124. data/app/views/spotlight/browse/show.html.erb +2 -2
  125. data/app/views/spotlight/catalog/_admin_header.html.erb +3 -1
  126. data/app/views/spotlight/catalog/_document_visibility_control.html.erb +21 -2
  127. data/app/views/spotlight/catalog/_index_compact_default.html.erb +1 -1
  128. data/app/views/spotlight/exhibits/_confirmation_status.html.erb +3 -1
  129. data/app/views/spotlight/exhibits/_contact.html.erb +5 -1
  130. data/app/views/spotlight/shared/_exhibit_sidebar.html.erb +2 -0
  131. data/app/views/spotlight/shared/_report_a_problem.html.erb +1 -1
  132. data/app/views/spotlight/sir_trevor/blocks/_search_results_block.html.erb +2 -2
  133. data/app/views/spotlight/translations/_page.html.erb +6 -1
  134. data/config/locales/spotlight.en.yml +3 -8
  135. data/lib/generators/spotlight/install_generator.rb +15 -23
  136. data/lib/generators/spotlight/scaffold_resource_generator.rb +12 -12
  137. data/lib/generators/spotlight/templates/config/initializers/spotlight_initializer.rb +3 -0
  138. data/lib/generators/spotlight/templates/solr/conf/_rest_managed.json +3 -0
  139. data/lib/generators/spotlight/templates/solr/conf/admin-extra.html +31 -0
  140. data/lib/generators/spotlight/templates/solr/conf/elevate.xml +36 -0
  141. data/lib/generators/spotlight/templates/solr/conf/mapping-ISOLatin1Accent.txt +246 -0
  142. data/lib/generators/spotlight/templates/solr/conf/protwords.txt +21 -0
  143. data/lib/generators/spotlight/templates/solr/{config → conf}/schema.xml +17 -0
  144. data/lib/generators/spotlight/templates/solr/conf/scripts.conf +24 -0
  145. data/lib/generators/spotlight/templates/solr/{config → conf}/solrconfig.xml +55 -24
  146. data/lib/generators/spotlight/templates/solr/conf/spellings.txt +2 -0
  147. data/lib/generators/spotlight/templates/solr/conf/stopwords.txt +58 -0
  148. data/lib/generators/spotlight/templates/solr/conf/stopwords_en.txt +58 -0
  149. data/lib/generators/spotlight/templates/solr/conf/synonyms.txt +31 -0
  150. data/lib/generators/spotlight/templates/solr/conf/xslt/example.xsl +132 -0
  151. data/lib/generators/spotlight/templates/solr/conf/xslt/example_atom.xsl +67 -0
  152. data/lib/generators/spotlight/templates/solr/conf/xslt/example_rss.xsl +66 -0
  153. data/lib/generators/spotlight/templates/solr/conf/xslt/luke.xsl +337 -0
  154. data/lib/generators/spotlight/templates/spotlight.js +1 -1
  155. data/lib/migration/iiif.rb +3 -7
  156. data/lib/spotlight/engine.rb +18 -16
  157. data/lib/spotlight/riiif_service.rb +31 -0
  158. data/lib/spotlight/search_state.rb +19 -0
  159. data/lib/spotlight/upload_field_config.rb +1 -1
  160. data/lib/spotlight/version.rb +1 -1
  161. data/lib/tasks/spotlight_tasks.rake +1 -1
  162. data/spec/fixtures/iiif_responses.rb +64 -64
  163. data/vendor/assets/javascripts/nestable.js +1 -1
  164. data/vendor/assets/javascripts/parameterize.js +2 -2
  165. data/vendor/assets/javascripts/sir-trevor.js +22460 -20591
  166. data/vendor/assets/stylesheets/sir-trevor/_icons.scss +0 -0
  167. data/vendor/assets/stylesheets/sir-trevor/_variables.scss +16 -18
  168. data/vendor/assets/stylesheets/sir-trevor/base.scss +11 -0
  169. data/vendor/assets/stylesheets/sir-trevor/block-addition-top.scss +4 -1
  170. data/vendor/assets/stylesheets/sir-trevor/block-addition.scss +3 -2
  171. data/vendor/assets/stylesheets/sir-trevor/block-controls.scss +4 -0
  172. data/vendor/assets/stylesheets/sir-trevor/block-positioner.scss +0 -0
  173. data/vendor/assets/stylesheets/sir-trevor/block-replacer.scss +0 -0
  174. data/vendor/assets/stylesheets/sir-trevor/block-ui.scss +10 -0
  175. data/vendor/assets/stylesheets/sir-trevor/block.scss +19 -5
  176. data/vendor/assets/stylesheets/sir-trevor/errors.scss +0 -0
  177. data/vendor/assets/stylesheets/sir-trevor/format-bar.scss +0 -0
  178. data/vendor/assets/stylesheets/sir-trevor/inputs.scss +0 -0
  179. data/vendor/assets/stylesheets/sir-trevor/main.scss +0 -0
  180. data/vendor/assets/stylesheets/sir-trevor/patterns/ui-popup.scss +0 -0
  181. data/vendor/assets/stylesheets/sir-trevor/utils.scss +0 -0
  182. metadata +104 -117
  183. data/app/assets/javascripts/spotlight/admin/add_another.js +0 -22
  184. data/app/assets/javascripts/spotlight/admin/add_new_button.js +0 -81
  185. data/app/assets/javascripts/spotlight/admin/appearance.js +0 -24
  186. data/app/assets/javascripts/spotlight/admin/attachments.js +0 -2
  187. data/app/assets/javascripts/spotlight/admin/blacklight_configuration.js +0 -63
  188. data/app/assets/javascripts/spotlight/admin/block_mixins/plustextable.js +0 -57
  189. data/app/assets/javascripts/spotlight/admin/blocks/browse_block.js +0 -87
  190. data/app/assets/javascripts/spotlight/admin/blocks/browse_group_categories_block.js +0 -88
  191. data/app/assets/javascripts/spotlight/admin/blocks/oembed_block.js +0 -40
  192. data/app/assets/javascripts/spotlight/admin/blocks/uploaded_items_block.js +0 -145
  193. data/app/assets/javascripts/spotlight/admin/catalog_edit.js +0 -16
  194. data/app/assets/javascripts/spotlight/admin/copy_email_addresses.js +0 -9
  195. data/app/assets/javascripts/spotlight/admin/croppable.js +0 -25
  196. data/app/assets/javascripts/spotlight/admin/exhibit_tag_autocomplete.js +0 -37
  197. data/app/assets/javascripts/spotlight/admin/exhibits.js +0 -58
  198. data/app/assets/javascripts/spotlight/admin/index.js +0 -16
  199. data/app/assets/javascripts/spotlight/admin/locks.js +0 -12
  200. data/app/assets/javascripts/spotlight/admin/pages.js.erb +0 -40
  201. data/app/assets/javascripts/spotlight/admin/readonly_checkbox.js +0 -6
  202. data/app/assets/javascripts/spotlight/admin/tabs.js +0 -6
  203. data/app/assets/javascripts/spotlight/user/carousel.js +0 -3
  204. data/app/assets/javascripts/spotlight/user/index.js +0 -8
  205. data/app/assets/javascripts/spotlight/user/zpr_links.js.erb +0 -45
  206. data/vendor/assets/javascripts/MutationObserver.js +0 -625
  207. data/vendor/assets/javascripts/eventable.js +0 -205
  208. data/vendor/assets/javascripts/polyfill.min.js +0 -4
  209. /data/app/{assets/javascripts → javascript}/spotlight/admin/blocks/solr_documents_embed_block.js +0 -0
  210. /data/app/{assets/javascripts → javascript}/spotlight/admin/blocks/solr_documents_features_block.js +0 -0
  211. /data/app/{assets/javascripts → javascript}/spotlight/admin/blocks/solr_documents_grid_block.js +0 -0
  212. /data/app/{assets/javascripts/spotlight/admin/iiif.es6 → javascript/spotlight/admin/iiif.js} +0 -0
  213. /data/app/{assets/javascripts → javascript}/spotlight/admin/sir-trevor/locales.js +0 -0
@@ -1,625 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
4
- * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
5
- * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6
- * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
7
- * Code distributed by Google as part of the polymer project is also
8
- * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
9
- */
10
-
11
-
12
- if (!Function.prototype.bind) {
13
- Function.prototype.bind = function(scope) {
14
- var self = this;
15
- var args = Array.prototype.slice.call(arguments, 1);
16
- return function() {
17
- var args2 = args.slice();
18
- args2.push.apply(args2, arguments);
19
- return self.apply(scope, args2);
20
- };
21
- };
22
- }
23
-
24
- (function(global) {
25
-
26
- if (typeof WeakMap === 'undefined') {
27
- (function() {
28
- var defineProperty = Object.defineProperty;
29
- var counter = Date.now() % 1e9;
30
-
31
- var WeakMap = function() {
32
- this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ +'__');
33
- };
34
-
35
- WeakMap.prototype = {
36
- set: function(key, value) {
37
- var entry = key[this.name];
38
- if (entry && entry[0] === key)
39
- entry[1] = value;
40
- else
41
- defineProperty(key, this.name, {
42
- value: [key, value],
43
- writable: true
44
- });
45
- return this;
46
- },
47
- get: function(key) {
48
- var entry;
49
- return (entry = key[this.name]) && entry[0] === key ?
50
- entry[1] : undefined;
51
- },
52
- delete: function(key) {
53
- var entry = key[this.name];
54
- if (!entry || entry[0] !== key) return false;
55
- entry[0] = entry[1] = undefined;
56
- return true;
57
- },
58
- has: function(key) {
59
- var entry = key[this.name];
60
- if (!entry) return false;
61
- return entry[0] === key;
62
- }
63
- };
64
-
65
- window.WeakMap = WeakMap;
66
- })();
67
- }
68
-
69
- var registrationsTable = new WeakMap();
70
-
71
- var setImmediate;
72
-
73
- // As much as we would like to use the native implementation, IE
74
- // (all versions) suffers a rather annoying bug where it will drop or defer
75
- // callbacks when heavy DOM operations are being performed concurrently.
76
- //
77
- // For a thorough discussion on this, see:
78
- // http://codeforhire.com/2013/09/21/setimmediate-and-messagechannel-broken-on-internet-explorer-10/
79
- if (/Trident|Edge/.test(navigator.userAgent)) {
80
- // Sadly, this bug also affects postMessage and MessageQueues.
81
- //
82
- // We would like to use the onreadystatechange hack for IE <= 10, but it is
83
- // dangerous in the polyfilled environment due to requiring that the
84
- // observed script element be in the document.
85
- setImmediate = setTimeout;
86
-
87
- // If some other browser ever implements it, let's prefer their native
88
- // implementation:
89
- } else if (window.setImmediate) {
90
- setImmediate = window.setImmediate;
91
-
92
- // Otherwise, we fall back to postMessage as a means of emulating the next
93
- // task semantics of setImmediate.
94
- } else {
95
- var setImmediateQueue = [];
96
- var sentinel = String(Math.random());
97
- window.addEventListener('message', function(e) {
98
- if (e.data === sentinel) {
99
- var queue = setImmediateQueue;
100
- setImmediateQueue = [];
101
- queue.forEach(function(func) {
102
- func();
103
- });
104
- }
105
- });
106
- setImmediate = function(func) {
107
- setImmediateQueue.push(func);
108
- window.postMessage(sentinel, '*');
109
- };
110
- }
111
-
112
- // This is used to ensure that we never schedule 2 callas to setImmediate
113
- var isScheduled = false;
114
-
115
- // Keep track of observers that needs to be notified next time.
116
- var scheduledObservers = [];
117
-
118
- /**
119
- * Schedules |dispatchCallback| to be called in the future.
120
- * @param {MutationObserver} observer
121
- */
122
- function scheduleCallback(observer) {
123
- scheduledObservers.push(observer);
124
- if (!isScheduled) {
125
- isScheduled = true;
126
- setImmediate(dispatchCallbacks);
127
- }
128
- }
129
-
130
- function wrapIfNeeded(node) {
131
- return window.ShadowDOMPolyfill &&
132
- window.ShadowDOMPolyfill.wrapIfNeeded(node) ||
133
- node;
134
- }
135
-
136
- function dispatchCallbacks() {
137
- // http://dom.spec.whatwg.org/#mutation-observers
138
-
139
- isScheduled = false; // Used to allow a new setImmediate call above.
140
-
141
- var observers = scheduledObservers;
142
- scheduledObservers = [];
143
- // Sort observers based on their creation UID (incremental).
144
- observers.sort(function(o1, o2) {
145
- return o1.uid_ - o2.uid_;
146
- });
147
-
148
- var anyNonEmpty = false;
149
- observers.forEach(function(observer) {
150
-
151
- // 2.1, 2.2
152
- var queue = observer.takeRecords();
153
- // 2.3. Remove all transient registered observers whose observer is mo.
154
- removeTransientObserversFor(observer);
155
-
156
- // 2.4
157
- if (queue.length) {
158
- observer.callback_(queue, observer);
159
- anyNonEmpty = true;
160
- }
161
- });
162
-
163
- // 3.
164
- if (anyNonEmpty)
165
- dispatchCallbacks();
166
- }
167
-
168
- function removeTransientObserversFor(observer) {
169
- observer.nodes_.forEach(function(node) {
170
- var registrations = registrationsTable.get(node);
171
- if (!registrations)
172
- return;
173
- registrations.forEach(function(registration) {
174
- if (registration.observer === observer)
175
- registration.removeTransientObservers();
176
- });
177
- });
178
- }
179
-
180
- /**
181
- * This function is used for the "For each registered observer observer (with
182
- * observer's options as options) in target's list of registered observers,
183
- * run these substeps:" and the "For each ancestor ancestor of target, and for
184
- * each registered observer observer (with options options) in ancestor's list
185
- * of registered observers, run these substeps:" part of the algorithms. The
186
- * |options.subtree| is checked to ensure that the callback is called
187
- * correctly.
188
- *
189
- * @param {Node} target
190
- * @param {function(MutationObserverInit):MutationRecord} callback
191
- */
192
- function forEachAncestorAndObserverEnqueueRecord(target, callback) {
193
- for (var node = target; node; node = node.parentNode) {
194
- var registrations = registrationsTable.get(node);
195
-
196
- if (registrations) {
197
- for (var j = 0; j < registrations.length; j++) {
198
- var registration = registrations[j];
199
- var options = registration.options;
200
-
201
- // Only target ignores subtree.
202
- if (node !== target && !options.subtree)
203
- continue;
204
-
205
- var record = callback(options);
206
- if (record)
207
- registration.enqueue(record);
208
- }
209
- }
210
- }
211
- }
212
-
213
- var uidCounter = 0;
214
-
215
- /**
216
- * The class that maps to the DOM MutationObserver interface.
217
- * @param {Function} callback.
218
- * @constructor
219
- */
220
- function JsMutationObserver(callback) {
221
- this.callback_ = callback;
222
- this.nodes_ = [];
223
- this.records_ = [];
224
- this.uid_ = ++uidCounter;
225
- }
226
-
227
- JsMutationObserver.prototype = {
228
- observe: function(target, options) {
229
- target = wrapIfNeeded(target);
230
-
231
- // 1.1
232
- if (!options.childList && !options.attributes && !options.characterData ||
233
-
234
- // 1.2
235
- options.attributeOldValue && !options.attributes ||
236
-
237
- // 1.3
238
- options.attributeFilter && options.attributeFilter.length &&
239
- !options.attributes ||
240
-
241
- // 1.4
242
- options.characterDataOldValue && !options.characterData) {
243
-
244
- throw new SyntaxError();
245
- }
246
-
247
- var registrations = registrationsTable.get(target);
248
- if (!registrations)
249
- registrationsTable.set(target, registrations = []);
250
-
251
- // 2
252
- // If target's list of registered observers already includes a registered
253
- // observer associated with the context object, replace that registered
254
- // observer's options with options.
255
- var registration;
256
- for (var i = 0; i < registrations.length; i++) {
257
- if (registrations[i].observer === this) {
258
- registration = registrations[i];
259
- registration.removeListeners();
260
- registration.options = options;
261
- break;
262
- }
263
- }
264
-
265
- // 3.
266
- // Otherwise, add a new registered observer to target's list of registered
267
- // observers with the context object as the observer and options as the
268
- // options, and add target to context object's list of nodes on which it
269
- // is registered.
270
- if (!registration) {
271
- registration = new Registration(this, target, options);
272
- registrations.push(registration);
273
- this.nodes_.push(target);
274
- }
275
-
276
- registration.addListeners();
277
- },
278
-
279
- disconnect: function() {
280
- this.nodes_.forEach(function(node) {
281
- var registrations = registrationsTable.get(node);
282
- for (var i = 0; i < registrations.length; i++) {
283
- var registration = registrations[i];
284
- if (registration.observer === this) {
285
- registration.removeListeners();
286
- registrations.splice(i, 1);
287
- // Each node can only have one registered observer associated with
288
- // this observer.
289
- break;
290
- }
291
- }
292
- }, this);
293
- this.records_ = [];
294
- },
295
-
296
- takeRecords: function() {
297
- var copyOfRecords = this.records_;
298
- this.records_ = [];
299
- return copyOfRecords;
300
- }
301
- };
302
-
303
- /**
304
- * @param {string} type
305
- * @param {Node} target
306
- * @constructor
307
- */
308
- function MutationRecord(type, target) {
309
- this.type = type;
310
- this.target = target;
311
- this.addedNodes = [];
312
- this.removedNodes = [];
313
- this.previousSibling = null;
314
- this.nextSibling = null;
315
- this.attributeName = null;
316
- this.attributeNamespace = null;
317
- this.oldValue = null;
318
- }
319
-
320
- function copyMutationRecord(original) {
321
- var record = new MutationRecord(original.type, original.target);
322
- record.addedNodes = original.addedNodes.slice();
323
- record.removedNodes = original.removedNodes.slice();
324
- record.previousSibling = original.previousSibling;
325
- record.nextSibling = original.nextSibling;
326
- record.attributeName = original.attributeName;
327
- record.attributeNamespace = original.attributeNamespace;
328
- record.oldValue = original.oldValue;
329
- return record;
330
- };
331
-
332
- // We keep track of the two (possibly one) records used in a single mutation.
333
- var currentRecord, recordWithOldValue;
334
-
335
- /**
336
- * Creates a record without |oldValue| and caches it as |currentRecord| for
337
- * later use.
338
- * @param {string} oldValue
339
- * @return {MutationRecord}
340
- */
341
- function getRecord(type, target) {
342
- return currentRecord = new MutationRecord(type, target);
343
- }
344
-
345
- /**
346
- * Gets or creates a record with |oldValue| based in the |currentRecord|
347
- * @param {string} oldValue
348
- * @return {MutationRecord}
349
- */
350
- function getRecordWithOldValue(oldValue) {
351
- if (recordWithOldValue)
352
- return recordWithOldValue;
353
- recordWithOldValue = copyMutationRecord(currentRecord);
354
- recordWithOldValue.oldValue = oldValue;
355
- return recordWithOldValue;
356
- }
357
-
358
- function clearRecords() {
359
- currentRecord = recordWithOldValue = undefined;
360
- }
361
-
362
- /**
363
- * @param {MutationRecord} record
364
- * @return {boolean} Whether the record represents a record from the current
365
- * mutation event.
366
- */
367
- function recordRepresentsCurrentMutation(record) {
368
- return record === recordWithOldValue || record === currentRecord;
369
- }
370
-
371
- /**
372
- * Selects which record, if any, to replace the last record in the queue.
373
- * This returns |null| if no record should be replaced.
374
- *
375
- * @param {MutationRecord} lastRecord
376
- * @param {MutationRecord} newRecord
377
- * @param {MutationRecord}
378
- */
379
- function selectRecord(lastRecord, newRecord) {
380
- if (lastRecord === newRecord)
381
- return lastRecord;
382
-
383
- // Check if the the record we are adding represents the same record. If
384
- // so, we keep the one with the oldValue in it.
385
- if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord))
386
- return recordWithOldValue;
387
-
388
- return null;
389
- }
390
-
391
- /**
392
- * Class used to represent a registered observer.
393
- * @param {MutationObserver} observer
394
- * @param {Node} target
395
- * @param {MutationObserverInit} options
396
- * @constructor
397
- */
398
- function Registration(observer, target, options) {
399
- this.observer = observer;
400
- this.target = target;
401
- this.options = options;
402
- this.transientObservedNodes = [];
403
- }
404
-
405
- Registration.prototype = {
406
- enqueue: function(record) {
407
- var records = this.observer.records_;
408
- var length = records.length;
409
-
410
- // There are cases where we replace the last record with the new record.
411
- // For example if the record represents the same mutation we need to use
412
- // the one with the oldValue. If we get same record (this can happen as we
413
- // walk up the tree) we ignore the new record.
414
- if (records.length > 0) {
415
- var lastRecord = records[length - 1];
416
- var recordToReplaceLast = selectRecord(lastRecord, record);
417
- if (recordToReplaceLast) {
418
- records[length - 1] = recordToReplaceLast;
419
- return;
420
- }
421
- } else {
422
- scheduleCallback(this.observer);
423
- }
424
-
425
- records[length] = record;
426
- },
427
-
428
- addListeners: function() {
429
- this.addListeners_(this.target);
430
- },
431
-
432
- addListeners_: function(node) {
433
- var options = this.options;
434
- if (options.attributes)
435
- node.addEventListener('DOMAttrModified', this, true);
436
-
437
- if (options.characterData)
438
- node.addEventListener('DOMCharacterDataModified', this, true);
439
-
440
- if (options.childList)
441
- node.addEventListener('DOMNodeInserted', this, true);
442
-
443
- if (options.childList || options.subtree)
444
- node.addEventListener('DOMNodeRemoved', this, true);
445
- },
446
-
447
- removeListeners: function() {
448
- this.removeListeners_(this.target);
449
- },
450
-
451
- removeListeners_: function(node) {
452
- var options = this.options;
453
- if (options.attributes)
454
- node.removeEventListener('DOMAttrModified', this, true);
455
-
456
- if (options.characterData)
457
- node.removeEventListener('DOMCharacterDataModified', this, true);
458
-
459
- if (options.childList)
460
- node.removeEventListener('DOMNodeInserted', this, true);
461
-
462
- if (options.childList || options.subtree)
463
- node.removeEventListener('DOMNodeRemoved', this, true);
464
- },
465
-
466
- /**
467
- * Adds a transient observer on node. The transient observer gets removed
468
- * next time we deliver the change records.
469
- * @param {Node} node
470
- */
471
- addTransientObserver: function(node) {
472
- // Don't add transient observers on the target itself. We already have all
473
- // the required listeners set up on the target.
474
- if (node === this.target)
475
- return;
476
-
477
- this.addListeners_(node);
478
- this.transientObservedNodes.push(node);
479
- var registrations = registrationsTable.get(node);
480
- if (!registrations)
481
- registrationsTable.set(node, registrations = []);
482
-
483
- // We know that registrations does not contain this because we already
484
- // checked if node === this.target.
485
- registrations.push(this);
486
- },
487
-
488
- removeTransientObservers: function() {
489
- var transientObservedNodes = this.transientObservedNodes;
490
- this.transientObservedNodes = [];
491
-
492
- transientObservedNodes.forEach(function(node) {
493
- // Transient observers are never added to the target.
494
- this.removeListeners_(node);
495
-
496
- var registrations = registrationsTable.get(node);
497
- for (var i = 0; i < registrations.length; i++) {
498
- if (registrations[i] === this) {
499
- registrations.splice(i, 1);
500
- // Each node can only have one registered observer associated with
501
- // this observer.
502
- break;
503
- }
504
- }
505
- }, this);
506
- },
507
-
508
- handleEvent: function(e) {
509
- // Stop propagation since we are managing the propagation manually.
510
- // This means that other mutation events on the page will not work
511
- // correctly but that is by design.
512
- e.stopImmediatePropagation();
513
-
514
- switch (e.type) {
515
- case 'DOMAttrModified':
516
- // http://dom.spec.whatwg.org/#concept-mo-queue-attributes
517
-
518
- var name = e.attrName;
519
- var namespace = e.relatedNode.namespaceURI;
520
- var target = e.target;
521
-
522
- // 1.
523
- var record = new getRecord('attributes', target);
524
- record.attributeName = name;
525
- record.attributeNamespace = namespace;
526
-
527
- // 2.
528
- var oldValue =
529
- e.attrChange === MutationEvent.ADDITION ? null : e.prevValue;
530
-
531
- forEachAncestorAndObserverEnqueueRecord(target, function(options) {
532
- // 3.1, 4.2
533
- if (!options.attributes)
534
- return;
535
-
536
- // 3.2, 4.3
537
- if (options.attributeFilter && options.attributeFilter.length &&
538
- options.attributeFilter.indexOf(name) === -1 &&
539
- options.attributeFilter.indexOf(namespace) === -1) {
540
- return;
541
- }
542
- // 3.3, 4.4
543
- if (options.attributeOldValue)
544
- return getRecordWithOldValue(oldValue);
545
-
546
- // 3.4, 4.5
547
- return record;
548
- });
549
-
550
- break;
551
-
552
- case 'DOMCharacterDataModified':
553
- // http://dom.spec.whatwg.org/#concept-mo-queue-characterdata
554
- var target = e.target;
555
-
556
- // 1.
557
- var record = getRecord('characterData', target);
558
-
559
- // 2.
560
- var oldValue = e.prevValue;
561
-
562
-
563
- forEachAncestorAndObserverEnqueueRecord(target, function(options) {
564
- // 3.1, 4.2
565
- if (!options.characterData)
566
- return;
567
-
568
- // 3.2, 4.3
569
- if (options.characterDataOldValue)
570
- return getRecordWithOldValue(oldValue);
571
-
572
- // 3.3, 4.4
573
- return record;
574
- });
575
-
576
- break;
577
-
578
- case 'DOMNodeRemoved':
579
- this.addTransientObserver(e.target);
580
- // Fall through.
581
- case 'DOMNodeInserted':
582
- // http://dom.spec.whatwg.org/#concept-mo-queue-childlist
583
- var target = e.relatedNode;
584
- var changedNode = e.target;
585
- var addedNodes, removedNodes;
586
- if (e.type === 'DOMNodeInserted') {
587
- addedNodes = [changedNode];
588
- removedNodes = [];
589
- } else {
590
-
591
- addedNodes = [];
592
- removedNodes = [changedNode];
593
- }
594
- var previousSibling = changedNode.previousSibling;
595
- var nextSibling = changedNode.nextSibling;
596
-
597
- // 1.
598
- var record = getRecord('childList', target);
599
- record.addedNodes = addedNodes;
600
- record.removedNodes = removedNodes;
601
- record.previousSibling = previousSibling;
602
- record.nextSibling = nextSibling;
603
-
604
- forEachAncestorAndObserverEnqueueRecord(target, function(options) {
605
- // 2.1, 3.2
606
- if (!options.childList)
607
- return;
608
-
609
- // 2.2, 3.3
610
- return record;
611
- });
612
-
613
- }
614
-
615
- clearRecords();
616
- }
617
- };
618
-
619
- global.JsMutationObserver = JsMutationObserver;
620
-
621
- if (!global.MutationObserver)
622
- global.MutationObserver = JsMutationObserver;
623
-
624
-
625
- })(this);