blacklight-spotlight 5.3.2 → 6.0.0.rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +41 -4
  3. data/Rakefile +1 -2
  4. data/app/assets/javascripts/spotlight/spotlight.esm.js +2168 -4560
  5. data/app/assets/javascripts/spotlight/spotlight.esm.js.map +1 -1
  6. data/app/assets/javascripts/spotlight/spotlight.js +2167 -4559
  7. data/app/assets/javascripts/spotlight/spotlight.js.map +1 -1
  8. data/app/assets/stylesheets/spotlight/_blacklight_overrides.scss +4 -0
  9. data/app/assets/stylesheets/spotlight/_browse.scss +0 -4
  10. data/app/assets/stylesheets/spotlight/{_collapse_toggle.scss → _collapse_toggle.css} +2 -2
  11. data/app/assets/stylesheets/spotlight/_exhibit_admin.scss +8 -0
  12. data/app/assets/stylesheets/spotlight/_exhibits_index.scss +2 -1
  13. data/app/assets/stylesheets/spotlight/_footer.scss +2 -2
  14. data/app/assets/stylesheets/spotlight/_header.scss +8 -8
  15. data/app/assets/stylesheets/spotlight/_pages.scss +1 -1
  16. data/app/assets/stylesheets/spotlight/_slideshow_block.scss +15 -0
  17. data/app/assets/stylesheets/spotlight/_spotlight.scss +1 -1
  18. data/app/assets/stylesheets/spotlight/_translations.scss +3 -3
  19. data/app/assets/stylesheets/spotlight/_uploaded_items_block.css +7 -0
  20. data/app/assets/stylesheets/spotlight/_variables.css +15 -0
  21. data/app/assets/stylesheets/spotlight/browse_group_categories_block.scss +0 -76
  22. data/app/components/blacklight/icons/pause_component.rb +15 -0
  23. data/app/components/blacklight/icons/play_arrow_component.rb +15 -0
  24. data/app/components/spotlight/analytics/dashboard_component.html.erb +1 -1
  25. data/app/components/spotlight/custom_field_form_group_component.rb +40 -0
  26. data/app/components/spotlight/document_admin_table_component.html.erb +2 -2
  27. data/app/components/spotlight/edit_sidecar_component.html.erb +18 -0
  28. data/app/components/spotlight/edit_sidecar_component.rb +41 -0
  29. data/app/components/spotlight/masthead_component.html.erb +18 -0
  30. data/app/components/spotlight/masthead_component.rb +46 -0
  31. data/app/components/spotlight/save_search_component.html.erb +1 -1
  32. data/app/components/spotlight/sidecar_form_field_component.html.erb +18 -0
  33. data/app/components/spotlight/sidecar_form_field_component.rb +71 -0
  34. data/app/components/spotlight/solr_document_legacy_embed_component.html.erb +0 -4
  35. data/app/components/spotlight/solr_document_legacy_embed_component.rb +2 -2
  36. data/app/components/spotlight/tag_selector_component.html.erb +1 -1
  37. data/app/components/spotlight/tag_selector_component.rb +3 -2
  38. data/app/components/spotlight/upload_field_form_group_component.rb +33 -0
  39. data/app/controllers/concerns/spotlight/controller.rb +15 -14
  40. data/app/controllers/concerns/spotlight/search_helper.rb +2 -5
  41. data/app/controllers/spotlight/browse_controller.rb +1 -6
  42. data/app/controllers/spotlight/catalog_controller.rb +2 -3
  43. data/app/controllers/spotlight/concerns/application_controller.rb +4 -6
  44. data/app/controllers/spotlight/exhibits_controller.rb +22 -10
  45. data/app/controllers/spotlight/lock_controller.rb +1 -1
  46. data/app/controllers/spotlight/pages_controller.rb +11 -11
  47. data/app/controllers/spotlight/resources/upload_controller.rb +1 -1
  48. data/app/controllers/spotlight/resources_controller.rb +1 -1
  49. data/app/controllers/spotlight/solr_controller.rb +5 -1
  50. data/app/helpers/spotlight/application_helper.rb +14 -26
  51. data/app/helpers/spotlight/crud_link_helpers.rb +0 -12
  52. data/app/helpers/spotlight/main_app_helpers.rb +2 -2
  53. data/app/javascript/spotlight/admin/add_another.js +37 -25
  54. data/app/javascript/spotlight/admin/add_image_selector.js +43 -26
  55. data/app/javascript/spotlight/admin/add_new_button.js +51 -36
  56. data/app/javascript/spotlight/admin/blacklight_configuration.js +76 -54
  57. data/app/javascript/spotlight/admin/block_mixins/autocompleteable.js +102 -101
  58. data/app/javascript/spotlight/admin/block_mixins/formable.js +91 -75
  59. data/app/javascript/spotlight/admin/block_mixins/plustextable.js +46 -48
  60. data/app/javascript/spotlight/admin/blocks/block.js +27 -28
  61. data/app/javascript/spotlight/admin/blocks/browse_block.js +14 -10
  62. data/app/javascript/spotlight/admin/blocks/browse_group_categories_block.js +14 -10
  63. data/app/javascript/spotlight/admin/blocks/pages_block.js +5 -4
  64. data/app/javascript/spotlight/admin/blocks/resources_block.js +61 -41
  65. data/app/javascript/spotlight/admin/blocks/search_result_block.js +24 -7
  66. data/app/javascript/spotlight/admin/blocks/solr_documents_base_block.js +103 -50
  67. data/app/javascript/spotlight/admin/blocks/solr_documents_carousel_block.js +50 -26
  68. data/app/javascript/spotlight/admin/blocks/solr_documents_features_block.js +47 -23
  69. data/app/javascript/spotlight/admin/blocks/uploaded_items_block.js +35 -19
  70. data/app/javascript/spotlight/admin/crop.js +146 -66
  71. data/app/javascript/spotlight/admin/croppable.js +5 -4
  72. data/app/javascript/spotlight/admin/croppable_modal.js +67 -32
  73. data/app/javascript/spotlight/admin/edit_in_place.js +69 -54
  74. data/app/javascript/spotlight/admin/exhibits.js +92 -45
  75. data/app/javascript/spotlight/admin/form_observer.js +92 -78
  76. data/app/javascript/spotlight/admin/multi_image_selector.js +201 -153
  77. data/app/javascript/spotlight/admin/pages.js +13 -7
  78. data/app/javascript/spotlight/admin/progress_monitor.js +65 -50
  79. data/app/javascript/spotlight/admin/readonly_checkbox.js +7 -3
  80. data/app/javascript/spotlight/admin/search_typeahead.js +20 -11
  81. data/app/javascript/spotlight/admin/select_related_input.js +23 -23
  82. data/app/javascript/spotlight/admin/serialize_json.js +120 -0
  83. data/app/javascript/spotlight/admin/sir-trevor/block_controls.js +24 -11
  84. data/app/javascript/spotlight/admin/sir-trevor/block_limits.js +9 -6
  85. data/app/javascript/spotlight/admin/sir-trevor/locales.js +2 -2
  86. data/app/javascript/spotlight/admin/spotlight_nestable.js +2 -5
  87. data/app/javascript/spotlight/admin/translation_progress.js +18 -13
  88. data/app/javascript/spotlight/admin/users.js +151 -64
  89. data/app/javascript/spotlight/user/carousel.js +104 -32
  90. data/app/javascript/spotlight/user/clear_form_button.js +24 -14
  91. data/app/javascript/spotlight/user/index.js +0 -2
  92. data/app/javascript/spotlight/user/zpr_links.js +99 -40
  93. data/app/jobs/concerns/spotlight/gather_documents.rb +1 -1
  94. data/app/jobs/spotlight/add_uploads_from_csv.rb +31 -8
  95. data/app/jobs/spotlight/cleanup_job_trackers_job.rb +5 -3
  96. data/app/models/concerns/spotlight/access_controls_enforcement_search_builder.rb +13 -2
  97. data/app/models/concerns/spotlight/browse_category_search_builder.rb +3 -3
  98. data/app/models/concerns/spotlight/exhibit_documents.rb +2 -2
  99. data/app/models/concerns/spotlight/sitemap.rb +2 -2
  100. data/app/models/concerns/spotlight/solr_document/finder.rb +2 -2
  101. data/app/models/concerns/spotlight/solr_document.rb +1 -47
  102. data/app/models/sir_trevor_rails/blocks/browse_block.rb +0 -4
  103. data/app/models/sir_trevor_rails/blocks/solr_documents_block.rb +2 -1
  104. data/app/models/spotlight/blacklight_configuration.rb +5 -3
  105. data/app/models/spotlight/contact_email.rb +2 -2
  106. data/app/models/spotlight/custom_field.rb +17 -0
  107. data/app/models/spotlight/exhibit.rb +28 -0
  108. data/app/models/spotlight/featured_image.rb +1 -1
  109. data/app/models/spotlight/field_metadata.rb +10 -5
  110. data/app/models/spotlight/job_tracker.rb +0 -18
  111. data/app/models/spotlight/main_navigation.rb +2 -2
  112. data/app/models/spotlight/page.rb +3 -3
  113. data/app/models/spotlight/resources/iiif_harvester.rb +7 -4
  114. data/app/models/spotlight/resources/iiif_manifest.rb +0 -4
  115. data/app/models/spotlight/resources/iiif_manifest_metadata.rb +1 -3
  116. data/app/models/spotlight/resources/iiif_service.rb +21 -6
  117. data/app/models/spotlight/resources/upload.rb +6 -0
  118. data/app/models/spotlight/search.rb +5 -9
  119. data/app/models/spotlight/solr_document_sidecar.rb +18 -0
  120. data/app/services/spotlight/bulk_updates_csv_template_service.rb +1 -1
  121. data/app/services/spotlight/etl/pipeline.rb +2 -2
  122. data/app/services/spotlight/etl/step.rb +2 -2
  123. data/app/views/catalog/_remove_tags.html.erb +2 -2
  124. data/app/views/layouts/spotlight/base.html.erb +3 -6
  125. data/app/views/layouts/spotlight/spotlight.html.erb +2 -2
  126. data/app/views/shared/_analytics.html.erb +4 -3
  127. data/app/views/shared/_masthead.html.erb +2 -18
  128. data/app/views/spotlight/about_pages/_empty.html.erb +1 -1
  129. data/app/views/spotlight/about_pages/_sidebar.html.erb +10 -8
  130. data/app/views/spotlight/browse/_search.html.erb +2 -2
  131. data/app/views/spotlight/browse/_search_box.html.erb +6 -14
  132. data/app/views/spotlight/browse/index.html.erb +1 -1
  133. data/app/views/spotlight/browse/show.html.erb +1 -1
  134. data/app/views/spotlight/catalog/_document_admin_table.html.erb +1 -1
  135. data/app/views/spotlight/catalog/_edit_default.html.erb +1 -1
  136. data/app/views/spotlight/catalog/edit.html.erb +1 -1
  137. data/app/views/spotlight/dashboards/_page.html.erb +1 -1
  138. data/app/views/spotlight/exhibits/_exhibit_card.html.erb +3 -1
  139. data/app/views/spotlight/exhibits/_export.html.erb +17 -1
  140. data/app/views/spotlight/exhibits/_form.html.erb +20 -4
  141. data/app/views/spotlight/exhibits/_missing_exhibits.html.erb +3 -3
  142. data/app/views/spotlight/exhibits/index.html.erb +21 -8
  143. data/app/views/spotlight/feature_pages/_empty.html.erb +1 -1
  144. data/app/views/spotlight/feature_pages/_sidebar.html.erb +17 -15
  145. data/app/views/spotlight/home_pages/_empty.html.erb +7 -7
  146. data/app/views/spotlight/pages/show.html.erb +1 -0
  147. data/app/views/spotlight/resources/upload/_form.html.erb +2 -2
  148. data/app/views/spotlight/sir_trevor/blocks/_browse_group_categories_block.html.erb +5 -16
  149. data/app/views/spotlight/sir_trevor/blocks/_embedded_document.html.erb +3 -5
  150. data/app/views/spotlight/sir_trevor/blocks/_link_to_search_block.html.erb +1 -1
  151. data/app/views/spotlight/sir_trevor/blocks/_solr_documents_carousel_block.html.erb +11 -2
  152. data/app/views/spotlight/sites/_exhibit.html.erb +1 -1
  153. data/config/i18n-tasks.yml +1 -1
  154. data/config/locales/spotlight.ar.yml +1 -2
  155. data/config/locales/spotlight.de.yml +1 -2
  156. data/config/locales/spotlight.en.yml +39 -10
  157. data/config/locales/spotlight.es.yml +1 -2
  158. data/config/locales/spotlight.fr.yml +1 -2
  159. data/config/locales/spotlight.it.yml +1 -2
  160. data/config/locales/spotlight.ja.yml +39 -0
  161. data/config/locales/spotlight.zh.yml +1 -2
  162. data/db/migrate/20261007133748_add_discovery_enabled_to_spotlight_exhibits.rb +5 -0
  163. data/lib/generators/spotlight/assets/importmap_generator.rb +2 -10
  164. data/lib/generators/spotlight/assets/propshaft_generator.rb +5 -4
  165. data/lib/generators/spotlight/install_generator.rb +2 -4
  166. data/lib/generators/spotlight/templates/catalog_controller.rb +0 -1
  167. data/lib/generators/spotlight/templates/config/initializers/spotlight_initializer.rb +26 -4
  168. data/lib/generators/spotlight/templates/solr/conf/schema.xml +4 -3
  169. data/lib/generators/spotlight/templates/solr/conf/solrconfig.xml +3 -8
  170. data/lib/migration/page_language.rb +0 -2
  171. data/lib/spotlight/engine.rb +28 -9
  172. data/lib/spotlight/search_state.rb +7 -11
  173. data/lib/spotlight/upload_field_config.rb +19 -1
  174. data/lib/spotlight/version.rb +1 -1
  175. data/lib/spotlight.rb +1 -1
  176. data/spec/support/features/capybara_wait_metadata_helper.rb +3 -1
  177. data/spec/support/features/test_features_helpers.rb +24 -1
  178. data/spec/support/iiif_manifest_fixtures.rb +33 -0
  179. data/spec/support/stub_dns_resolution.rb +12 -0
  180. metadata +50 -80
  181. data/app/assets/stylesheets/spotlight/_uploaded_items_block.scss +0 -7
  182. data/app/assets/stylesheets/spotlight/_variables.scss +0 -13
  183. data/app/components/blacklight/icons/arrow_alt_circle_left_component.rb +0 -15
  184. data/app/components/blacklight/icons/arrow_alt_circle_right_component.rb +0 -15
  185. data/app/components/blacklight/icons/info_component.rb +0 -15
  186. data/app/components/blacklight/icons/zoom_in_component.rb +0 -15
  187. data/app/components/blacklight/icons/zoom_out_component.rb +0 -15
  188. data/app/components/spotlight/icon_component.rb +0 -13
  189. data/app/javascript/spotlight/user/browse_group_categories.js +0 -54
  190. data/app/mailers/spotlight/invitation_mailer.rb +0 -21
  191. data/app/models/concerns/spotlight/resources/web.rb +0 -38
  192. data/app/services/spotlight/iiif_resource_resolver.rb +0 -78
  193. data/app/views/catalog/_image_default.html.erb +0 -6
  194. data/app/views/shared/_exhibit_navbar.html.erb +0 -2
  195. data/app/views/shared/_header_navbar.html.erb +0 -6
  196. data/app/views/spotlight/catalog/_admin_index_header_default.html.erb +0 -23
  197. data/app/views/spotlight/catalog/_admin_thumbnail_default.html.erb +0 -7
  198. data/app/views/spotlight/catalog/_curation_mode_toggle_default.html.erb +0 -1
  199. data/app/views/spotlight/catalog/_document_row.html.erb +0 -2
  200. data/app/views/spotlight/catalog/_edit_sidecar.html.erb +0 -24
  201. data/app/views/spotlight/catalog/_index_compact_default.html.erb +0 -21
  202. data/app/views/spotlight/custom_fields/form_group/_text.html.erb +0 -23
  203. data/app/views/spotlight/custom_fields/form_group/_vocab.html.erb +0 -23
  204. data/app/views/spotlight/invitation_mailer/exhibit_invitation_notification.html.erb +0 -12
  205. data/lib/generators/spotlight/templates/javascript/jquery-shim.js +0 -1
  206. data/vendor/assets/javascripts/tiny-slider.js +0 -3221
  207. data/vendor/assets/stylesheets/tiny-slider.css +0 -1
  208. /data/app/assets/stylesheets/spotlight/{_breadcrumbs.scss → _breadcrumbs.css} +0 -0
  209. /data/app/assets/stylesheets/spotlight/{_croppable.scss → _croppable.css} +0 -0
  210. /data/app/assets/stylesheets/spotlight/{_modals.scss → _modals.css} +0 -0
  211. /data/app/assets/stylesheets/spotlight/{_utilities.scss → _utilities.css} +0 -0
@@ -1,3221 +0,0 @@
1
- // Includes an unreleased RTL support pull request: https://github.com/ganlanyuan/tiny-slider/pull/658
2
- // Includes "export default tns" at the end of the file for spotlight/user/browse_group_categories.js
3
- var tns = (function (){
4
- var win = window;
5
-
6
- var raf = win.requestAnimationFrame
7
- || win.webkitRequestAnimationFrame
8
- || win.mozRequestAnimationFrame
9
- || win.msRequestAnimationFrame
10
- || function(cb) { return setTimeout(cb, 16); };
11
-
12
- var win$1 = window;
13
-
14
- var caf = win$1.cancelAnimationFrame
15
- || win$1.mozCancelAnimationFrame
16
- || function(id){ clearTimeout(id); };
17
-
18
- function extend() {
19
- var obj, name, copy,
20
- target = arguments[0] || {},
21
- i = 1,
22
- length = arguments.length;
23
-
24
- for (; i < length; i++) {
25
- if ((obj = arguments[i]) !== null) {
26
- for (name in obj) {
27
- copy = obj[name];
28
-
29
- if (target === copy) {
30
- continue;
31
- } else if (copy !== undefined) {
32
- target[name] = copy;
33
- }
34
- }
35
- }
36
- }
37
- return target;
38
- }
39
-
40
- function checkStorageValue (value) {
41
- return ['true', 'false'].indexOf(value) >= 0 ? JSON.parse(value) : value;
42
- }
43
-
44
- function setLocalStorage(storage, key, value, access) {
45
- if (access) {
46
- try { storage.setItem(key, value); } catch (e) {}
47
- }
48
- return value;
49
- }
50
-
51
- function getSlideId() {
52
- var id = window.tnsId;
53
- window.tnsId = !id ? 1 : id + 1;
54
-
55
- return 'tns' + window.tnsId;
56
- }
57
-
58
- function getBody () {
59
- var doc = document,
60
- body = doc.body;
61
-
62
- if (!body) {
63
- body = doc.createElement('body');
64
- body.fake = true;
65
- }
66
-
67
- return body;
68
- }
69
-
70
- var docElement = document.documentElement;
71
-
72
- function setFakeBody (body) {
73
- var docOverflow = '';
74
- if (body.fake) {
75
- docOverflow = docElement.style.overflow;
76
- //avoid crashing IE8, if background image is used
77
- body.style.background = '';
78
- //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
79
- body.style.overflow = docElement.style.overflow = 'hidden';
80
- docElement.appendChild(body);
81
- }
82
-
83
- return docOverflow;
84
- }
85
-
86
- function resetFakeBody (body, docOverflow) {
87
- if (body.fake) {
88
- body.remove();
89
- docElement.style.overflow = docOverflow;
90
- // Trigger layout so kinetic scrolling isn't disabled in iOS6+
91
- // eslint-disable-next-line
92
- docElement.offsetHeight;
93
- }
94
- }
95
-
96
- // get css-calc
97
-
98
- function calc() {
99
- var doc = document,
100
- body = getBody(),
101
- docOverflow = setFakeBody(body),
102
- div = doc.createElement('div'),
103
- result = false;
104
-
105
- body.appendChild(div);
106
- try {
107
- var str = '(10px * 10)',
108
- vals = ['calc' + str, '-moz-calc' + str, '-webkit-calc' + str],
109
- val;
110
- for (var i = 0; i < 3; i++) {
111
- val = vals[i];
112
- div.style.width = val;
113
- if (div.offsetWidth === 100) {
114
- result = val.replace(str, '');
115
- break;
116
- }
117
- }
118
- } catch (e) {}
119
-
120
- body.fake ? resetFakeBody(body, docOverflow) : div.remove();
121
-
122
- return result;
123
- }
124
-
125
- // get subpixel support value
126
-
127
- function percentageLayout() {
128
- // check subpixel layout supporting
129
- var doc = document,
130
- body = getBody(),
131
- docOverflow = setFakeBody(body),
132
- wrapper = doc.createElement('div'),
133
- outer = doc.createElement('div'),
134
- str = '',
135
- count = 70,
136
- perPage = 3,
137
- supported = false;
138
-
139
- wrapper.className = "tns-t-subp2";
140
- outer.className = "tns-t-ct";
141
-
142
- for (var i = 0; i < count; i++) {
143
- str += '<div></div>';
144
- }
145
-
146
- outer.innerHTML = str;
147
- wrapper.appendChild(outer);
148
- body.appendChild(wrapper);
149
-
150
- supported = Math.abs(wrapper.getBoundingClientRect().left - outer.children[count - perPage].getBoundingClientRect().left) < 2;
151
-
152
- body.fake ? resetFakeBody(body, docOverflow) : wrapper.remove();
153
-
154
- return supported;
155
- }
156
-
157
- function mediaquerySupport () {
158
- if (window.matchMedia || window.msMatchMedia) {
159
- return true;
160
- }
161
-
162
- var doc = document,
163
- body = getBody(),
164
- docOverflow = setFakeBody(body),
165
- div = doc.createElement('div'),
166
- style = doc.createElement('style'),
167
- rule = '@media all and (min-width:1px){.tns-mq-test{position:absolute}}',
168
- position;
169
-
170
- style.type = 'text/css';
171
- div.className = 'tns-mq-test';
172
-
173
- body.appendChild(style);
174
- body.appendChild(div);
175
-
176
- if (style.styleSheet) {
177
- style.styleSheet.cssText = rule;
178
- } else {
179
- style.appendChild(doc.createTextNode(rule));
180
- }
181
-
182
- position = window.getComputedStyle ? window.getComputedStyle(div).position : div.currentStyle['position'];
183
-
184
- body.fake ? resetFakeBody(body, docOverflow) : div.remove();
185
-
186
- return position === "absolute";
187
- }
188
-
189
- // create and append style sheet
190
- function createStyleSheet (media, nonce) {
191
- // Create the <style> tag
192
- var style = document.createElement("style");
193
- // style.setAttribute("type", "text/css");
194
-
195
- // Add a media (and/or media query) here if you'd like!
196
- // style.setAttribute("media", "screen")
197
- // style.setAttribute("media", "only screen and (max-width : 1024px)")
198
- if (media) { style.setAttribute("media", media); }
199
-
200
- // Add nonce attribute for Content Security Policy
201
- if (nonce) { style.setAttribute("nonce", nonce); }
202
-
203
- // WebKit hack :(
204
- // style.appendChild(document.createTextNode(""));
205
-
206
- // Add the <style> element to the page
207
- document.querySelector('head').appendChild(style);
208
-
209
- return style.sheet ? style.sheet : style.styleSheet;
210
- }
211
-
212
- // cross browsers addRule method
213
- function addCSSRule(sheet, selector, rules, index) {
214
- // return raf(function() {
215
- 'insertRule' in sheet ?
216
- sheet.insertRule(selector + '{' + rules + '}', index) :
217
- sheet.addRule(selector, rules, index);
218
- // });
219
- }
220
-
221
- // cross browsers addRule method
222
- function removeCSSRule(sheet, index) {
223
- // return raf(function() {
224
- 'deleteRule' in sheet ?
225
- sheet.deleteRule(index) :
226
- sheet.removeRule(index);
227
- // });
228
- }
229
-
230
- function getCssRulesLength(sheet) {
231
- var rule = ('insertRule' in sheet) ? sheet.cssRules : sheet.rules;
232
- return rule.length;
233
- }
234
-
235
- function toDegree (y, x) {
236
- return Math.atan2(y, x) * (180 / Math.PI);
237
- }
238
-
239
- function getTouchDirection(angle, range) {
240
- var direction = false,
241
- gap = Math.abs(90 - Math.abs(angle));
242
-
243
- if (gap >= 90 - range) {
244
- direction = 'horizontal';
245
- } else if (gap <= range) {
246
- direction = 'vertical';
247
- }
248
-
249
- return direction;
250
- }
251
-
252
- // https://toddmotto.com/ditch-the-array-foreach-call-nodelist-hack/
253
- function forEach (arr, callback, scope) {
254
- for (var i = 0, l = arr.length; i < l; i++) {
255
- callback.call(scope, arr[i], i);
256
- }
257
- }
258
-
259
- var classListSupport = 'classList' in document.createElement('_');
260
-
261
- var hasClass = classListSupport ?
262
- function (el, str) { return el.classList.contains(str); } :
263
- function (el, str) { return el.className.indexOf(str) >= 0; };
264
-
265
- var addClass = classListSupport ?
266
- function (el, str) {
267
- if (!hasClass(el, str)) { el.classList.add(str); }
268
- } :
269
- function (el, str) {
270
- if (!hasClass(el, str)) { el.className += ' ' + str; }
271
- };
272
-
273
- var removeClass = classListSupport ?
274
- function (el, str) {
275
- if (hasClass(el, str)) { el.classList.remove(str); }
276
- } :
277
- function (el, str) {
278
- if (hasClass(el, str)) { el.className = el.className.replace(str, ''); }
279
- };
280
-
281
- function hasAttr(el, attr) {
282
- return el.hasAttribute(attr);
283
- }
284
-
285
- function getAttr(el, attr) {
286
- return el.getAttribute(attr);
287
- }
288
-
289
- function isNodeList(el) {
290
- // Only NodeList has the "item()" function
291
- return typeof el.item !== "undefined";
292
- }
293
-
294
- function setAttrs(els, attrs) {
295
- els = (isNodeList(els) || els instanceof Array) ? els : [els];
296
- if (Object.prototype.toString.call(attrs) !== '[object Object]') { return; }
297
-
298
- for (var i = els.length; i--;) {
299
- for(var key in attrs) {
300
- els[i].setAttribute(key, attrs[key]);
301
- }
302
- }
303
- }
304
-
305
- function removeAttrs(els, attrs) {
306
- els = (isNodeList(els) || els instanceof Array) ? els : [els];
307
- attrs = (attrs instanceof Array) ? attrs : [attrs];
308
-
309
- var attrLength = attrs.length;
310
- for (var i = els.length; i--;) {
311
- for (var j = attrLength; j--;) {
312
- els[i].removeAttribute(attrs[j]);
313
- }
314
- }
315
- }
316
-
317
- function arrayFromNodeList (nl) {
318
- var arr = [];
319
- for (var i = 0, l = nl.length; i < l; i++) {
320
- arr.push(nl[i]);
321
- }
322
- return arr;
323
- }
324
-
325
- function hideElement(el, forceHide) {
326
- if (el.style.display !== 'none') { el.style.display = 'none'; }
327
- }
328
-
329
- function showElement(el, forceHide) {
330
- if (el.style.display === 'none') { el.style.display = ''; }
331
- }
332
-
333
- function isVisible(el) {
334
- return window.getComputedStyle(el).display !== 'none';
335
- }
336
-
337
- function whichProperty(props){
338
- if (typeof props === 'string') {
339
- var arr = [props],
340
- Props = props.charAt(0).toUpperCase() + props.substr(1),
341
- prefixes = ['Webkit', 'Moz', 'ms', 'O'];
342
-
343
- prefixes.forEach(function(prefix) {
344
- if (prefix !== 'ms' || props === 'transform') {
345
- arr.push(prefix + Props);
346
- }
347
- });
348
-
349
- props = arr;
350
- }
351
-
352
- var el = document.createElement('fakeelement'),
353
- len = props.length;
354
- for(var i = 0; i < props.length; i++){
355
- var prop = props[i];
356
- if( el.style[prop] !== undefined ){ return prop; }
357
- }
358
-
359
- return false; // explicit for ie9-
360
- }
361
-
362
- function has3DTransforms(tf){
363
- if (!tf) { return false; }
364
- if (!window.getComputedStyle) { return false; }
365
-
366
- var doc = document,
367
- body = getBody(),
368
- docOverflow = setFakeBody(body),
369
- el = doc.createElement('p'),
370
- has3d,
371
- cssTF = tf.length > 9 ? '-' + tf.slice(0, -9).toLowerCase() + '-' : '';
372
-
373
- cssTF += 'transform';
374
-
375
- // Add it to the body to get the computed style
376
- body.insertBefore(el, null);
377
-
378
- el.style[tf] = 'translate3d(1px,1px,1px)';
379
- has3d = window.getComputedStyle(el).getPropertyValue(cssTF);
380
-
381
- body.fake ? resetFakeBody(body, docOverflow) : el.remove();
382
-
383
- return (has3d !== undefined && has3d.length > 0 && has3d !== "none");
384
- }
385
-
386
- // get transitionend, animationend based on transitionDuration
387
- // @propin: string
388
- // @propOut: string, first-letter uppercase
389
- // Usage: getEndProperty('WebkitTransitionDuration', 'Transition') => webkitTransitionEnd
390
- function getEndProperty(propIn, propOut) {
391
- var endProp = false;
392
- if (/^Webkit/.test(propIn)) {
393
- endProp = 'webkit' + propOut + 'End';
394
- } else if (/^O/.test(propIn)) {
395
- endProp = 'o' + propOut + 'End';
396
- } else if (propIn) {
397
- endProp = propOut.toLowerCase() + 'end';
398
- }
399
- return endProp;
400
- }
401
-
402
- // Test via a getter in the options object to see if the passive property is accessed
403
- var supportsPassive = false;
404
- try {
405
- var opts = Object.defineProperty({}, 'passive', {
406
- get: function() {
407
- supportsPassive = true;
408
- }
409
- });
410
- window.addEventListener("test", null, opts);
411
- } catch (e) {}
412
- var passiveOption = supportsPassive ? { passive: true } : false;
413
-
414
- function addEvents(el, obj, preventScrolling) {
415
- for (var prop in obj) {
416
- var option = ['touchstart', 'touchmove'].indexOf(prop) >= 0 && !preventScrolling ? passiveOption : false;
417
- el.addEventListener(prop, obj[prop], option);
418
- }
419
- }
420
-
421
- function removeEvents(el, obj) {
422
- for (var prop in obj) {
423
- var option = ['touchstart', 'touchmove'].indexOf(prop) >= 0 ? passiveOption : false;
424
- el.removeEventListener(prop, obj[prop], option);
425
- }
426
- }
427
-
428
- function Events() {
429
- return {
430
- topics: {},
431
- on: function (eventName, fn) {
432
- this.topics[eventName] = this.topics[eventName] || [];
433
- this.topics[eventName].push(fn);
434
- },
435
- off: function(eventName, fn) {
436
- if (this.topics[eventName]) {
437
- for (var i = 0; i < this.topics[eventName].length; i++) {
438
- if (this.topics[eventName][i] === fn) {
439
- this.topics[eventName].splice(i, 1);
440
- break;
441
- }
442
- }
443
- }
444
- },
445
- emit: function (eventName, data) {
446
- data.type = eventName;
447
- if (this.topics[eventName]) {
448
- this.topics[eventName].forEach(function(fn) {
449
- fn(data, eventName);
450
- });
451
- }
452
- }
453
- };
454
- }
455
-
456
- function jsTransform(element, attr, prefix, postfix, to, duration, callback) {
457
- var tick = Math.min(duration, 10),
458
- unit = (to.indexOf('%') >= 0) ? '%' : 'px',
459
- to = to.replace(unit, ''),
460
- from = Number(element.style[attr].replace(prefix, '').replace(postfix, '').replace(unit, '')),
461
- positionTick = (to - from) / duration * tick,
462
- running;
463
-
464
- setTimeout(moveElement, tick);
465
- function moveElement() {
466
- duration -= tick;
467
- from += positionTick;
468
- element.style[attr] = prefix + from + unit + postfix;
469
- if (duration > 0) {
470
- setTimeout(moveElement, tick);
471
- } else {
472
- callback();
473
- }
474
- }
475
- }
476
-
477
- // Object.keys
478
- if (!Object.keys) {
479
- Object.keys = function(object) {
480
- var keys = [];
481
- for (var name in object) {
482
- if (Object.prototype.hasOwnProperty.call(object, name)) {
483
- keys.push(name);
484
- }
485
- }
486
- return keys;
487
- };
488
- }
489
-
490
- // ChildNode.remove
491
- if(!("remove" in Element.prototype)){
492
- Element.prototype.remove = function(){
493
- if(this.parentNode) {
494
- this.parentNode.removeChild(this);
495
- }
496
- };
497
- }
498
-
499
- var tns = function(options) {
500
- options = extend({
501
- container: '.slider',
502
- mode: 'carousel',
503
- axis: 'horizontal',
504
- items: 1,
505
- gutter: 0,
506
- edgePadding: 0,
507
- fixedWidth: false,
508
- autoWidth: false,
509
- viewportMax: false,
510
- slideBy: 1,
511
- center: false,
512
- controls: true,
513
- controlsPosition: 'top',
514
- controlsText: ['prev', 'next'],
515
- controlsContainer: false,
516
- prevButton: false,
517
- nextButton: false,
518
- nav: true,
519
- navPosition: 'top',
520
- navContainer: false,
521
- navAsThumbnails: false,
522
- arrowKeys: false,
523
- speed: 300,
524
- autoplay: false,
525
- autoplayPosition: 'top',
526
- autoplayTimeout: 5000,
527
- autoplayDirection: 'forward',
528
- autoplayText: ['start', 'stop'],
529
- autoplayHoverPause: false,
530
- autoplayButton: false,
531
- autoplayButtonOutput: true,
532
- autoplayResetOnVisibility: true,
533
- animateIn: 'tns-fadeIn',
534
- animateOut: 'tns-fadeOut',
535
- animateNormal: 'tns-normal',
536
- animateDelay: false,
537
- loop: true,
538
- rewind: false,
539
- autoHeight: false,
540
- responsive: false,
541
- lazyload: false,
542
- lazyloadSelector: '.tns-lazy-img',
543
- touch: true,
544
- mouseDrag: false,
545
- swipeAngle: 15,
546
- nested: false,
547
- preventActionWhenRunning: false,
548
- preventScrollOnTouch: false,
549
- freezable: true,
550
- onInit: false,
551
- useLocalStorage: true,
552
- textDirection: 'ltr',
553
- nonce: false
554
- }, options || {});
555
-
556
- var doc = document,
557
- win = window,
558
- KEYS = {
559
- ENTER: 13,
560
- SPACE: 32,
561
- LEFT: 37,
562
- RIGHT: 39
563
- },
564
- tnsStorage = {},
565
- localStorageAccess = options.useLocalStorage;
566
-
567
- if (localStorageAccess) {
568
- // check browser version and local storage access
569
- var browserInfo = navigator.userAgent;
570
- var uid = new Date;
571
-
572
- try {
573
- tnsStorage = win.localStorage;
574
- if (tnsStorage) {
575
- tnsStorage.setItem(uid, uid);
576
- localStorageAccess = tnsStorage.getItem(uid) == uid;
577
- tnsStorage.removeItem(uid);
578
- } else {
579
- localStorageAccess = false;
580
- }
581
- if (!localStorageAccess) { tnsStorage = {}; }
582
- } catch(e) {
583
- localStorageAccess = false;
584
- }
585
-
586
- if (localStorageAccess) {
587
- // remove storage when browser version changes
588
- if (tnsStorage['tnsApp'] && tnsStorage['tnsApp'] !== browserInfo) {
589
- ['tC', 'tPL', 'tMQ', 'tTf', 't3D', 'tTDu', 'tTDe', 'tADu', 'tADe', 'tTE', 'tAE'].forEach(function(item) { tnsStorage.removeItem(item); });
590
- }
591
- // update browserInfo
592
- localStorage['tnsApp'] = browserInfo;
593
- }
594
- }
595
-
596
- var CALC = tnsStorage['tC'] ? checkStorageValue(tnsStorage['tC']) : setLocalStorage(tnsStorage, 'tC', calc(), localStorageAccess),
597
- PERCENTAGELAYOUT = tnsStorage['tPL'] ? checkStorageValue(tnsStorage['tPL']) : setLocalStorage(tnsStorage, 'tPL', percentageLayout(), localStorageAccess),
598
- CSSMQ = tnsStorage['tMQ'] ? checkStorageValue(tnsStorage['tMQ']) : setLocalStorage(tnsStorage, 'tMQ', mediaquerySupport(), localStorageAccess),
599
- TRANSFORM = tnsStorage['tTf'] ? checkStorageValue(tnsStorage['tTf']) : setLocalStorage(tnsStorage, 'tTf', whichProperty('transform'), localStorageAccess),
600
- HAS3DTRANSFORMS = tnsStorage['t3D'] ? checkStorageValue(tnsStorage['t3D']) : setLocalStorage(tnsStorage, 't3D', has3DTransforms(TRANSFORM), localStorageAccess),
601
- TRANSITIONDURATION = tnsStorage['tTDu'] ? checkStorageValue(tnsStorage['tTDu']) : setLocalStorage(tnsStorage, 'tTDu', whichProperty('transitionDuration'), localStorageAccess),
602
- TRANSITIONDELAY = tnsStorage['tTDe'] ? checkStorageValue(tnsStorage['tTDe']) : setLocalStorage(tnsStorage, 'tTDe', whichProperty('transitionDelay'), localStorageAccess),
603
- ANIMATIONDURATION = tnsStorage['tADu'] ? checkStorageValue(tnsStorage['tADu']) : setLocalStorage(tnsStorage, 'tADu', whichProperty('animationDuration'), localStorageAccess),
604
- ANIMATIONDELAY = tnsStorage['tADe'] ? checkStorageValue(tnsStorage['tADe']) : setLocalStorage(tnsStorage, 'tADe', whichProperty('animationDelay'), localStorageAccess),
605
- TRANSITIONEND = tnsStorage['tTE'] ? checkStorageValue(tnsStorage['tTE']) : setLocalStorage(tnsStorage, 'tTE', getEndProperty(TRANSITIONDURATION, 'Transition'), localStorageAccess),
606
- ANIMATIONEND = tnsStorage['tAE'] ? checkStorageValue(tnsStorage['tAE']) : setLocalStorage(tnsStorage, 'tAE', getEndProperty(ANIMATIONDURATION, 'Animation'), localStorageAccess);
607
-
608
- // get element nodes from selectors
609
- var supportConsoleWarn = win.console && typeof win.console.warn === "function",
610
- tnsList = ['container', 'controlsContainer', 'prevButton', 'nextButton', 'navContainer', 'autoplayButton'],
611
- optionsElements = {};
612
-
613
- tnsList.forEach(function(item) {
614
- if (typeof options[item] === 'string') {
615
- var str = options[item],
616
- el = doc.querySelector(str);
617
- optionsElements[item] = str;
618
-
619
- if (el && el.nodeName) {
620
- options[item] = el;
621
- } else {
622
- if (supportConsoleWarn) { console.warn('Can\'t find', options[item]); }
623
- return;
624
- }
625
- }
626
- });
627
-
628
- // make sure at least 1 slide
629
- if (options.container.children.length < 1) {
630
- if (supportConsoleWarn) { console.warn('No slides found in', options.container); }
631
- return;
632
- }
633
-
634
- // update options
635
- var responsive = options.responsive,
636
- nested = options.nested,
637
- carousel = options.mode === 'carousel' ? true : false;
638
-
639
- if (responsive) {
640
- // apply responsive[0] to options and remove it
641
- if (0 in responsive) {
642
- options = extend(options, responsive[0]);
643
- delete responsive[0];
644
- }
645
-
646
- var responsiveTem = {};
647
- for (var key in responsive) {
648
- var val = responsive[key];
649
- // update responsive
650
- // from: 300: 2
651
- // to:
652
- // 300: {
653
- // items: 2
654
- // }
655
- val = typeof val === 'number' ? {items: val} : val;
656
- responsiveTem[key] = val;
657
- }
658
- responsive = responsiveTem;
659
- responsiveTem = null;
660
- }
661
-
662
- // update options
663
- function updateOptions (obj) {
664
- for (var key in obj) {
665
- if (!carousel) {
666
- if (key === 'slideBy') { obj[key] = 'page'; }
667
- if (key === 'edgePadding') { obj[key] = false; }
668
- if (key === 'autoHeight') { obj[key] = false; }
669
- }
670
-
671
- // update responsive options
672
- if (key === 'responsive') { updateOptions(obj[key]); }
673
- }
674
- }
675
- if (!carousel) { updateOptions(options); }
676
-
677
-
678
- // === define and set variables ===
679
- if (!carousel) {
680
- options.axis = 'horizontal';
681
- options.slideBy = 'page';
682
- options.edgePadding = false;
683
-
684
- var animateIn = options.animateIn,
685
- animateOut = options.animateOut,
686
- animateDelay = options.animateDelay,
687
- animateNormal = options.animateNormal;
688
- }
689
-
690
- var horizontal = options.axis === 'horizontal' ? true : false,
691
- outerWrapper = doc.createElement('div'),
692
- innerWrapper = doc.createElement('div'),
693
- middleWrapper,
694
- container = options.container,
695
- containerParent = container.parentNode,
696
- containerHTML = container.outerHTML,
697
- slideItems = container.children,
698
- slideCount = slideItems.length,
699
- breakpointZone,
700
- windowWidth = getWindowWidth(),
701
- isOn = false;
702
- if (responsive) { setBreakpointZone(); }
703
- if (carousel) { container.className += ' tns-vpfix'; }
704
-
705
- // fixedWidth: viewport > rightBoundary > indexMax
706
- var autoWidth = options.autoWidth,
707
- fixedWidth = getOption('fixedWidth'),
708
- edgePadding = getOption('edgePadding'),
709
- gutter = getOption('gutter'),
710
- viewport = getViewportWidth(),
711
- center = getOption('center'),
712
- items = !autoWidth ? Math.floor(getOption('items')) : 1,
713
- slideBy = getOption('slideBy'),
714
- viewportMax = options.viewportMax || options.fixedWidthViewportWidth,
715
- arrowKeys = getOption('arrowKeys'),
716
- speed = getOption('speed'),
717
- rewind = options.rewind,
718
- loop = rewind ? false : options.loop,
719
- autoHeight = getOption('autoHeight'),
720
- controls = getOption('controls'),
721
- controlsText = getOption('controlsText'),
722
- textDirection = getOption('textDirection'),
723
- nav = getOption('nav'),
724
- touch = getOption('touch'),
725
- mouseDrag = getOption('mouseDrag'),
726
- autoplay = getOption('autoplay'),
727
- autoplayTimeout = getOption('autoplayTimeout'),
728
- autoplayText = getOption('autoplayText'),
729
- autoplayHoverPause = getOption('autoplayHoverPause'),
730
- autoplayResetOnVisibility = getOption('autoplayResetOnVisibility'),
731
- sheet = createStyleSheet(null, getOption('nonce')),
732
- lazyload = options.lazyload,
733
- lazyloadSelector = options.lazyloadSelector,
734
- slidePositions, // collection of slide positions
735
- slideItemsOut = [],
736
- cloneCount = loop ? getCloneCountForLoop() : 0,
737
- slideCountNew = !carousel ? slideCount + cloneCount : slideCount + cloneCount * 2,
738
- hasRightDeadZone = (fixedWidth || autoWidth) && !loop ? true : false,
739
- rightBoundary = fixedWidth ? getRightBoundary() : null,
740
- updateIndexBeforeTransform = (!carousel || !loop) ? true : false,
741
- // transform
742
- transformAttr = horizontal ? 'left' : 'top',
743
- transformPrefix = '',
744
- transformPostfix = '',
745
- // index
746
- getIndexMax = (function () {
747
- if (fixedWidth) {
748
- return function() { return center && !loop ? slideCount - 1 : Math.ceil(- rightBoundary / (fixedWidth + gutter)); };
749
- } else if (autoWidth) {
750
- return function() {
751
- for (var i = 0; i < slideCountNew; i++) {
752
- if (slidePositions[i] >= - rightBoundary) { return i; }
753
- }
754
- };
755
- } else {
756
- return function() {
757
- if (center && carousel && !loop) {
758
- return slideCount - 1;
759
- } else {
760
- return loop || carousel ? Math.max(0, slideCountNew - Math.ceil(items)) : slideCountNew - 1;
761
- }
762
- };
763
- }
764
- })(),
765
- index = getStartIndex(getOption('startIndex')),
766
- indexCached = index,
767
- displayIndex = getCurrentSlide(),
768
- indexMin = 0,
769
- indexMax = !autoWidth ? getIndexMax() : null,
770
- // resize
771
- resizeTimer,
772
- preventActionWhenRunning = options.preventActionWhenRunning,
773
- swipeAngle = options.swipeAngle,
774
- moveDirectionExpected = swipeAngle ? '?' : true,
775
- running = false,
776
- onInit = options.onInit,
777
- events = new Events(),
778
- // id, class
779
- newContainerClasses = ' tns-slider tns-' + options.mode,
780
- slideId = container.id || getSlideId(),
781
- disable = getOption('disable'),
782
- disabled = false,
783
- freezable = options.freezable,
784
- freeze = freezable && !autoWidth ? getFreeze() : false,
785
- frozen = false,
786
- controlsEvents = {
787
- 'click': onControlsClick,
788
- 'keydown': onControlsKeydown
789
- },
790
- navEvents = {
791
- 'click': onNavClick,
792
- 'keydown': onNavKeydown
793
- },
794
- hoverEvents = {
795
- 'mouseover': mouseoverPause,
796
- 'mouseout': mouseoutRestart
797
- },
798
- visibilityEvent = {'visibilitychange': onVisibilityChange},
799
- docmentKeydownEvent = {'keydown': onDocumentKeydown},
800
- touchEvents = {
801
- 'touchstart': onPanStart,
802
- 'touchmove': onPanMove,
803
- 'touchend': onPanEnd,
804
- 'touchcancel': onPanEnd
805
- }, dragEvents = {
806
- 'mousedown': onPanStart,
807
- 'mousemove': onPanMove,
808
- 'mouseup': onPanEnd,
809
- 'mouseleave': onPanEnd
810
- },
811
- hasControls = hasOption('controls'),
812
- hasNav = hasOption('nav'),
813
- navAsThumbnails = autoWidth ? true : options.navAsThumbnails,
814
- hasAutoplay = hasOption('autoplay'),
815
- hasTouch = hasOption('touch'),
816
- hasMouseDrag = hasOption('mouseDrag'),
817
- slideActiveClass = 'tns-slide-active',
818
- slideClonedClass = 'tns-slide-cloned',
819
- imgCompleteClass = 'tns-complete',
820
- imgEvents = {
821
- 'load': onImgLoaded,
822
- 'error': onImgFailed
823
- },
824
- imgsComplete,
825
- liveregionCurrent,
826
- preventScroll = options.preventScrollOnTouch === 'force' ? true : false;
827
-
828
- // controls
829
- if (hasControls) {
830
- var controlsContainer = options.controlsContainer,
831
- controlsContainerHTML = options.controlsContainer ? options.controlsContainer.outerHTML : '',
832
- prevButton = options.prevButton,
833
- nextButton = options.nextButton,
834
- prevButtonHTML = options.prevButton ? options.prevButton.outerHTML : '',
835
- nextButtonHTML = options.nextButton ? options.nextButton.outerHTML : '',
836
- prevIsButton,
837
- nextIsButton;
838
- }
839
-
840
- // nav
841
- if (hasNav) {
842
- var navContainer = options.navContainer,
843
- navContainerHTML = options.navContainer ? options.navContainer.outerHTML : '',
844
- navItems,
845
- pages = autoWidth ? slideCount : getPages(),
846
- pagesCached = 0,
847
- navClicked = -1,
848
- navCurrentIndex = getCurrentNavIndex(),
849
- navCurrentIndexCached = navCurrentIndex,
850
- navActiveClass = 'tns-nav-active',
851
- navStr = 'Carousel Page ',
852
- navStrCurrent = ' (Current Slide)';
853
- }
854
-
855
- // autoplay
856
- if (hasAutoplay) {
857
- var autoplayDirection = options.autoplayDirection === 'forward' ? 1 : -1,
858
- autoplayButton = options.autoplayButton,
859
- autoplayButtonHTML = options.autoplayButton ? options.autoplayButton.outerHTML : '',
860
- autoplayHtmlStrings = ['<span class=\'tns-visually-hidden\'>', ' animation</span>'],
861
- autoplayTimer,
862
- animating,
863
- autoplayHoverPaused,
864
- autoplayUserPaused,
865
- autoplayVisibilityPaused;
866
- }
867
-
868
- if (hasTouch || hasMouseDrag) {
869
- var initPosition = {},
870
- lastPosition = {},
871
- translateInit,
872
- disX,
873
- disY,
874
- panStart = false,
875
- rafIndex,
876
- getDist = horizontal ?
877
- function(a, b) { return a.x - b.x; } :
878
- function(a, b) { return a.y - b.y; };
879
- }
880
-
881
- // disable slider when slidecount <= items
882
- if (!autoWidth) { resetVariblesWhenDisable(disable || freeze); }
883
-
884
- if (TRANSFORM) {
885
- transformAttr = TRANSFORM;
886
- transformPrefix = 'translate';
887
-
888
- if (HAS3DTRANSFORMS) {
889
- transformPrefix += horizontal ? '3d(' : '3d(0px, ';
890
- transformPostfix = horizontal ? ', 0px, 0px)' : ', 0px)';
891
- } else {
892
- transformPrefix += horizontal ? 'X(' : 'Y(';
893
- transformPostfix = ')';
894
- }
895
-
896
- }
897
-
898
- if (carousel) { container.className = container.className.replace('tns-vpfix', ''); }
899
- initStructure();
900
- initSheet();
901
- initSliderTransform();
902
-
903
- // === COMMON FUNCTIONS === //
904
- function resetVariblesWhenDisable (condition) {
905
- if (condition) {
906
- controls = nav = touch = mouseDrag = arrowKeys = autoplay = autoplayHoverPause = autoplayResetOnVisibility = false;
907
- }
908
- }
909
-
910
- function getCurrentSlide () {
911
- var tem = carousel ? index - cloneCount : index;
912
- while (tem < 0) { tem += slideCount; }
913
- return tem%slideCount + 1;
914
- }
915
-
916
- function getStartIndex (ind) {
917
- ind = ind ? Math.max(0, Math.min(loop ? slideCount - 1 : slideCount - items, ind)) : 0;
918
- return carousel ? ind + cloneCount : ind;
919
- }
920
-
921
- function getAbsIndex (i) {
922
- if (i == null) { i = index; }
923
-
924
- if (carousel) { i -= cloneCount; }
925
- while (i < 0) { i += slideCount; }
926
-
927
- return Math.floor(i%slideCount);
928
- }
929
-
930
- function getCurrentNavIndex () {
931
- var absIndex = getAbsIndex(),
932
- result;
933
-
934
- result = navAsThumbnails ? absIndex :
935
- fixedWidth || autoWidth ? Math.ceil((absIndex + 1) * pages / slideCount - 1) :
936
- Math.floor(absIndex / items);
937
-
938
- // set active nav to the last one when reaches the right edge
939
- if (!loop && carousel && index === indexMax) { result = pages - 1; }
940
-
941
- return result;
942
- }
943
-
944
- function getItemsMax () {
945
- // fixedWidth or autoWidth while viewportMax is not available
946
- if (autoWidth || (fixedWidth && !viewportMax)) {
947
- return slideCount - 1;
948
- // most cases
949
- } else {
950
- var str = fixedWidth ? 'fixedWidth' : 'items',
951
- arr = [];
952
-
953
- if (fixedWidth || options[str] < slideCount) { arr.push(options[str]); }
954
-
955
- if (responsive) {
956
- for (var bp in responsive) {
957
- var tem = responsive[bp][str];
958
- if (tem && (fixedWidth || tem < slideCount)) { arr.push(tem); }
959
- }
960
- }
961
-
962
- if (!arr.length) { arr.push(0); }
963
-
964
- return Math.ceil(fixedWidth ? viewportMax / Math.min.apply(null, arr) : Math.max.apply(null, arr));
965
- }
966
- }
967
-
968
- function getCloneCountForLoop () {
969
- var itemsMax = getItemsMax(),
970
- result = carousel ? Math.ceil((itemsMax * 5 - slideCount)/2) : (itemsMax * 4 - slideCount);
971
- result = Math.max(itemsMax, result);
972
-
973
- return hasOption('edgePadding') ? result + 1 : result;
974
- }
975
-
976
- function getWindowWidth () {
977
- return win.innerWidth || doc.documentElement.clientWidth || doc.body.clientWidth;
978
- }
979
-
980
- function getInsertPosition (pos) {
981
- return pos === 'top' ? 'afterbegin' : 'beforeend';
982
- }
983
-
984
- function getClientWidth (el) {
985
- if (el == null) { return; }
986
- var div = doc.createElement('div'), rect, width;
987
- el.appendChild(div);
988
- rect = div.getBoundingClientRect();
989
- width = rect.right - rect.left;
990
- div.remove();
991
- return width || getClientWidth(el.parentNode);
992
- }
993
-
994
- function getViewportWidth () {
995
- var gap = edgePadding ? edgePadding * 2 - gutter : 0;
996
- return getClientWidth(containerParent) - gap;
997
- }
998
-
999
- function hasOption (item) {
1000
- if (options[item]) {
1001
- return true;
1002
- } else {
1003
- if (responsive) {
1004
- for (var bp in responsive) {
1005
- if (responsive[bp][item]) { return true; }
1006
- }
1007
- }
1008
- return false;
1009
- }
1010
- }
1011
-
1012
- // get option:
1013
- // fixed width: viewport, fixedWidth, gutter => items
1014
- // others: window width => all variables
1015
- // all: items => slideBy
1016
- function getOption (item, ww) {
1017
- if (ww == null) { ww = windowWidth; }
1018
-
1019
- if (item === 'items' && fixedWidth) {
1020
- return Math.floor((viewport + gutter) / (fixedWidth + gutter)) || 1;
1021
-
1022
- } else {
1023
- var result = options[item];
1024
-
1025
- if (responsive) {
1026
- for (var bp in responsive) {
1027
- // bp: convert string to number
1028
- if (ww >= parseInt(bp)) {
1029
- if (item in responsive[bp]) { result = responsive[bp][item]; }
1030
- }
1031
- }
1032
- }
1033
-
1034
- if (item === 'slideBy' && result === 'page') { result = getOption('items'); }
1035
- if (!carousel && (item === 'slideBy' || item === 'items')) { result = Math.floor(result); }
1036
-
1037
- return result;
1038
- }
1039
- }
1040
-
1041
- function getSlideMarginLeft (i) {
1042
- return CALC ?
1043
- CALC + '(' + i * 100 + '% / ' + slideCountNew + ')' :
1044
- i * 100 / slideCountNew + '%';
1045
- }
1046
-
1047
- function getInnerWrapperStyles (edgePaddingTem, gutterTem, fixedWidthTem, speedTem, autoHeightBP) {
1048
- var str = '';
1049
-
1050
- if (edgePaddingTem !== undefined) {
1051
- var gap = edgePaddingTem;
1052
- if (gutterTem) { gap -= gutterTem; }
1053
- str = horizontal ?
1054
- 'margin: 0 ' + gap + 'px 0 ' + edgePaddingTem + 'px;' :
1055
- 'margin: ' + edgePaddingTem + 'px 0 ' + gap + 'px 0;';
1056
- } else if (gutterTem && !fixedWidthTem) {
1057
- var gutterTemUnit = '-' + gutterTem + 'px',
1058
- dir = horizontal ? gutterTemUnit + ' 0 0' : '0 ' + gutterTemUnit + ' 0';
1059
- str = 'margin: 0 ' + dir + ';';
1060
- }
1061
-
1062
- if (!carousel && autoHeightBP && TRANSITIONDURATION && speedTem) { str += getTransitionDurationStyle(speedTem); }
1063
- return str;
1064
- }
1065
-
1066
- function getContainerWidth (fixedWidthTem, gutterTem, itemsTem) {
1067
- if (fixedWidthTem) {
1068
- return (fixedWidthTem + gutterTem) * slideCountNew + 'px';
1069
- } else {
1070
- return CALC ?
1071
- CALC + '(' + slideCountNew * 100 + '% / ' + itemsTem + ')' :
1072
- slideCountNew * 100 / itemsTem + '%';
1073
- }
1074
- }
1075
-
1076
- function getSlideWidthStyle (fixedWidthTem, gutterTem, itemsTem) {
1077
- var width;
1078
-
1079
- if (fixedWidthTem) {
1080
- width = (fixedWidthTem + gutterTem) + 'px';
1081
- } else {
1082
- if (!carousel) { itemsTem = Math.floor(itemsTem); }
1083
- var dividend = carousel ? slideCountNew : itemsTem;
1084
- width = CALC ?
1085
- CALC + '(100% / ' + dividend + ')' :
1086
- 100 / dividend + '%';
1087
- }
1088
-
1089
- width = 'width:' + width;
1090
-
1091
- // inner slider: overwrite outer slider styles
1092
- return nested !== 'inner' ? width + ';' : width + ' !important;';
1093
- }
1094
-
1095
- function getSlideGutterStyle (gutterTem) {
1096
- var str = '';
1097
-
1098
- // gutter maybe interger || 0
1099
- // so can't use 'if (gutter)'
1100
- if (gutterTem !== false) {
1101
- var prop = horizontal ? 'padding-' : 'margin-',
1102
- dir = horizontal ? 'right' : 'bottom';
1103
- str = prop + dir + ': ' + gutterTem + 'px;';
1104
- }
1105
-
1106
- return str;
1107
- }
1108
-
1109
- function getCSSPrefix (name, num) {
1110
- var prefix = name.substring(0, name.length - num).toLowerCase();
1111
- if (prefix) { prefix = '-' + prefix + '-'; }
1112
-
1113
- return prefix;
1114
- }
1115
-
1116
- function getTransitionDurationStyle (speed) {
1117
- return getCSSPrefix(TRANSITIONDURATION, 18) + 'transition-duration:' + speed / 1000 + 's;';
1118
- }
1119
-
1120
- function getAnimationDurationStyle (speed) {
1121
- return getCSSPrefix(ANIMATIONDURATION, 17) + 'animation-duration:' + speed / 1000 + 's;';
1122
- }
1123
-
1124
- function initStructure () {
1125
- var classOuter = 'tns-outer',
1126
- classInner = 'tns-inner',
1127
- hasGutter = hasOption('gutter');
1128
-
1129
- outerWrapper.className = classOuter;
1130
- innerWrapper.className = classInner;
1131
- outerWrapper.id = slideId + '-ow';
1132
- innerWrapper.id = slideId + '-iw';
1133
-
1134
- // set container properties
1135
- if (container.id === '') { container.id = slideId; }
1136
- newContainerClasses += PERCENTAGELAYOUT || autoWidth ? ' tns-subpixel' : ' tns-no-subpixel';
1137
- newContainerClasses += CALC ? ' tns-calc' : ' tns-no-calc';
1138
- if (autoWidth) { newContainerClasses += ' tns-autowidth'; }
1139
- newContainerClasses += ' tns-' + options.axis;
1140
- container.className += newContainerClasses;
1141
-
1142
- // add constrain layer for carousel
1143
- if (carousel) {
1144
- middleWrapper = doc.createElement('div');
1145
- middleWrapper.id = slideId + '-mw';
1146
- middleWrapper.className = 'tns-ovh';
1147
-
1148
- outerWrapper.appendChild(middleWrapper);
1149
- middleWrapper.appendChild(innerWrapper);
1150
- } else {
1151
- outerWrapper.appendChild(innerWrapper);
1152
- }
1153
-
1154
- if (autoHeight) {
1155
- var wp = middleWrapper ? middleWrapper : innerWrapper;
1156
- wp.className += ' tns-ah';
1157
- }
1158
-
1159
- containerParent.insertBefore(outerWrapper, container);
1160
- innerWrapper.appendChild(container);
1161
-
1162
- // add id, class, aria attributes
1163
- // before clone slides
1164
- forEach(slideItems, function(item, i) {
1165
- addClass(item, 'tns-item');
1166
- if (!item.id) { item.id = slideId + '-item' + i; }
1167
- if (!carousel && animateNormal) { addClass(item, animateNormal); }
1168
- setAttrs(item, {
1169
- 'aria-hidden': 'true',
1170
- 'tabindex': '-1'
1171
- });
1172
- });
1173
-
1174
- // ## clone slides
1175
- // carousel: n + slides + n
1176
- // gallery: slides + n
1177
- if (cloneCount) {
1178
- var fragmentBefore = doc.createDocumentFragment(),
1179
- fragmentAfter = doc.createDocumentFragment();
1180
-
1181
- for (var j = cloneCount; j--;) {
1182
- var num = j%slideCount,
1183
- cloneFirst = slideItems[num].cloneNode(true);
1184
- addClass(cloneFirst, slideClonedClass);
1185
- removeAttrs(cloneFirst, 'id');
1186
- fragmentAfter.insertBefore(cloneFirst, fragmentAfter.firstChild);
1187
-
1188
- if (carousel) {
1189
- var cloneLast = slideItems[slideCount - 1 - num].cloneNode(true);
1190
- addClass(cloneLast, slideClonedClass);
1191
- removeAttrs(cloneLast, 'id');
1192
- fragmentBefore.appendChild(cloneLast);
1193
- }
1194
- }
1195
-
1196
- container.insertBefore(fragmentBefore, container.firstChild);
1197
- container.appendChild(fragmentAfter);
1198
- slideItems = container.children;
1199
- }
1200
-
1201
- }
1202
-
1203
- function initSliderTransform () {
1204
- // ## images loaded/failed
1205
- if (hasOption('autoHeight') || autoWidth || !horizontal) {
1206
- var imgs = container.querySelectorAll('img');
1207
-
1208
- // add img load event listener
1209
- forEach(imgs, function(img) {
1210
- var src = img.src;
1211
-
1212
- if (!lazyload) {
1213
- // not data img
1214
- if (src && src.indexOf('data:image') < 0) {
1215
- img.src = '';
1216
- addEvents(img, imgEvents);
1217
- addClass(img, 'loading');
1218
-
1219
- img.src = src;
1220
- // data img
1221
- } else {
1222
- imgLoaded(img);
1223
- }
1224
- }
1225
- });
1226
-
1227
- // set imgsComplete
1228
- raf(function(){ imgsLoadedCheck(arrayFromNodeList(imgs), function() { imgsComplete = true; }); });
1229
-
1230
- // reset imgs for auto height: check visible imgs only
1231
- if (hasOption('autoHeight')) { imgs = getImageArray(index, Math.min(index + items - 1, slideCountNew - 1)); }
1232
-
1233
- lazyload ? initSliderTransformStyleCheck() : raf(function(){ imgsLoadedCheck(arrayFromNodeList(imgs), initSliderTransformStyleCheck); });
1234
-
1235
- } else {
1236
- // set container transform property
1237
- if (carousel) { doContainerTransformSilent(); }
1238
-
1239
- // update slider tools and events
1240
- initTools();
1241
- initEvents();
1242
- }
1243
- }
1244
-
1245
- function initSliderTransformStyleCheck () {
1246
- if (autoWidth && slideCount > 1) {
1247
- // check styles application
1248
- var num = loop ? index : slideCount - 1;
1249
-
1250
- (function stylesApplicationCheck() {
1251
- var left = slideItems[num].getBoundingClientRect().left;
1252
- var right = slideItems[num - 1].getBoundingClientRect().right;
1253
-
1254
- (Math.abs(left - right) <= 1) ?
1255
- initSliderTransformCore() :
1256
- setTimeout(function(){ stylesApplicationCheck(); }, 16);
1257
- })();
1258
-
1259
- } else {
1260
- initSliderTransformCore();
1261
- }
1262
- }
1263
-
1264
-
1265
- function initSliderTransformCore () {
1266
- // run Fn()s which are rely on image loading
1267
- if (!horizontal || autoWidth) {
1268
- setSlidePositions();
1269
-
1270
- if (autoWidth) {
1271
- rightBoundary = getRightBoundary();
1272
- if (freezable) { freeze = getFreeze(); }
1273
- indexMax = getIndexMax(); // <= slidePositions, rightBoundary <=
1274
- resetVariblesWhenDisable(disable || freeze);
1275
- } else {
1276
- updateContentWrapperHeight();
1277
- }
1278
- }
1279
-
1280
- // set container transform property
1281
- if (carousel) { doContainerTransformSilent(); }
1282
-
1283
- // update slider tools and events
1284
- initTools();
1285
- initEvents();
1286
- }
1287
-
1288
- function initSheet () {
1289
- // gallery:
1290
- // set animation classes and left value for gallery slider
1291
- if (!carousel) {
1292
- for (var i = index, l = index + Math.min(slideCount, items); i < l; i++) {
1293
- var item = slideItems[i];
1294
- item.style.left = (i - index) * 100 / items + '%';
1295
- addClass(item, animateIn);
1296
- removeClass(item, animateNormal);
1297
- }
1298
- }
1299
-
1300
- // #### LAYOUT
1301
-
1302
- // ## INLINE-BLOCK VS FLOAT
1303
-
1304
- // ## PercentageLayout:
1305
- // slides: inline-block
1306
- // remove blank space between slides by set font-size: 0
1307
-
1308
- // ## Non PercentageLayout:
1309
- // slides: float
1310
- // margin-right: -100%
1311
- // margin-left: ~
1312
-
1313
- // Resource: https://docs.google.com/spreadsheets/d/147up245wwTXeQYve3BRSAD4oVcvQmuGsFteJOeA5xNQ/edit?usp=sharing
1314
- if (horizontal) {
1315
- if (PERCENTAGELAYOUT || autoWidth) {
1316
- addCSSRule(sheet, '#' + slideId + ' > .tns-item', 'font-size:' + win.getComputedStyle(slideItems[0]).fontSize + ';', getCssRulesLength(sheet));
1317
- addCSSRule(sheet, '#' + slideId, 'font-size:0;', getCssRulesLength(sheet));
1318
- } else if (carousel) {
1319
- forEach(slideItems, function (slide, i) {
1320
- slide.style.marginLeft = getSlideMarginLeft(i);
1321
- });
1322
- }
1323
- }
1324
-
1325
-
1326
- // ## BASIC STYLES
1327
- if (CSSMQ) {
1328
- // middle wrapper style
1329
- if (TRANSITIONDURATION) {
1330
- var str = middleWrapper && options.autoHeight ? getTransitionDurationStyle(options.speed) : '';
1331
- addCSSRule(sheet, '#' + slideId + '-mw', str, getCssRulesLength(sheet));
1332
- }
1333
-
1334
- // inner wrapper styles
1335
- str = getInnerWrapperStyles(options.edgePadding, options.gutter, options.fixedWidth, options.speed, options.autoHeight);
1336
- addCSSRule(sheet, '#' + slideId + '-iw', str, getCssRulesLength(sheet));
1337
-
1338
- // container styles
1339
- if (carousel) {
1340
- str = horizontal && !autoWidth ? 'width:' + getContainerWidth(options.fixedWidth, options.gutter, options.items) + ';' : '';
1341
- if (TRANSITIONDURATION) { str += getTransitionDurationStyle(speed); }
1342
- addCSSRule(sheet, '#' + slideId, str, getCssRulesLength(sheet));
1343
- }
1344
-
1345
- // slide styles
1346
- str = horizontal && !autoWidth ? getSlideWidthStyle(options.fixedWidth, options.gutter, options.items) : '';
1347
- if (options.gutter) { str += getSlideGutterStyle(options.gutter); }
1348
- // set gallery items transition-duration
1349
- if (!carousel) {
1350
- if (TRANSITIONDURATION) { str += getTransitionDurationStyle(speed); }
1351
- if (ANIMATIONDURATION) { str += getAnimationDurationStyle(speed); }
1352
- }
1353
- if (str) { addCSSRule(sheet, '#' + slideId + ' > .tns-item', str, getCssRulesLength(sheet)); }
1354
-
1355
- // non CSS mediaqueries: IE8
1356
- // ## update inner wrapper, container, slides if needed
1357
- // set inline styles for inner wrapper & container
1358
- // insert stylesheet (one line) for slides only (since slides are many)
1359
- } else {
1360
- // middle wrapper styles
1361
- update_carousel_transition_duration();
1362
-
1363
- // inner wrapper styles
1364
- innerWrapper.style.cssText = getInnerWrapperStyles(edgePadding, gutter, fixedWidth, autoHeight);
1365
-
1366
- // container styles
1367
- if (carousel && horizontal && !autoWidth) {
1368
- container.style.width = getContainerWidth(fixedWidth, gutter, items);
1369
- }
1370
-
1371
- // slide styles
1372
- var str = horizontal && !autoWidth ? getSlideWidthStyle(fixedWidth, gutter, items) : '';
1373
- if (gutter) { str += getSlideGutterStyle(gutter); }
1374
-
1375
- // append to the last line
1376
- if (str) { addCSSRule(sheet, '#' + slideId + ' > .tns-item', str, getCssRulesLength(sheet)); }
1377
- }
1378
-
1379
- // ## MEDIAQUERIES
1380
- if (responsive && CSSMQ) {
1381
- for (var bp in responsive) {
1382
- // bp: convert string to number
1383
- bp = parseInt(bp);
1384
-
1385
- var opts = responsive[bp],
1386
- str = '',
1387
- middleWrapperStr = '',
1388
- innerWrapperStr = '',
1389
- containerStr = '',
1390
- slideStr = '',
1391
- itemsBP = !autoWidth ? getOption('items', bp) : null,
1392
- fixedWidthBP = getOption('fixedWidth', bp),
1393
- speedBP = getOption('speed', bp),
1394
- edgePaddingBP = getOption('edgePadding', bp),
1395
- autoHeightBP = getOption('autoHeight', bp),
1396
- gutterBP = getOption('gutter', bp);
1397
-
1398
- // middle wrapper string
1399
- if (TRANSITIONDURATION && middleWrapper && getOption('autoHeight', bp) && 'speed' in opts) {
1400
- middleWrapperStr = '#' + slideId + '-mw{' + getTransitionDurationStyle(speedBP) + '}';
1401
- }
1402
-
1403
- // inner wrapper string
1404
- if ('edgePadding' in opts || 'gutter' in opts) {
1405
- innerWrapperStr = '#' + slideId + '-iw{' + getInnerWrapperStyles(edgePaddingBP, gutterBP, fixedWidthBP, speedBP, autoHeightBP) + '}';
1406
- }
1407
-
1408
- // container string
1409
- if (carousel && horizontal && !autoWidth && ('fixedWidth' in opts || 'items' in opts || (fixedWidth && 'gutter' in opts))) {
1410
- containerStr = 'width:' + getContainerWidth(fixedWidthBP, gutterBP, itemsBP) + ';';
1411
- }
1412
- if (TRANSITIONDURATION && 'speed' in opts) {
1413
- containerStr += getTransitionDurationStyle(speedBP);
1414
- }
1415
- if (containerStr) {
1416
- containerStr = '#' + slideId + '{' + containerStr + '}';
1417
- }
1418
-
1419
- // slide string
1420
- if ('fixedWidth' in opts || (fixedWidth && 'gutter' in opts) || !carousel && 'items' in opts) {
1421
- slideStr += getSlideWidthStyle(fixedWidthBP, gutterBP, itemsBP);
1422
- }
1423
- if ('gutter' in opts) {
1424
- slideStr += getSlideGutterStyle(gutterBP);
1425
- }
1426
- // set gallery items transition-duration
1427
- if (!carousel && 'speed' in opts) {
1428
- if (TRANSITIONDURATION) { slideStr += getTransitionDurationStyle(speedBP); }
1429
- if (ANIMATIONDURATION) { slideStr += getAnimationDurationStyle(speedBP); }
1430
- }
1431
- if (slideStr) { slideStr = '#' + slideId + ' > .tns-item{' + slideStr + '}'; }
1432
-
1433
- // add up
1434
- str = middleWrapperStr + innerWrapperStr + containerStr + slideStr;
1435
-
1436
- if (str) {
1437
- sheet.insertRule('@media (min-width: ' + bp / 16 + 'em) {' + str + '}', sheet.cssRules.length);
1438
- }
1439
- }
1440
- }
1441
- }
1442
-
1443
- function initTools () {
1444
- // == slides ==
1445
- updateSlideStatus();
1446
-
1447
- // == live region ==
1448
- outerWrapper.insertAdjacentHTML('afterbegin', '<div class="tns-liveregion tns-visually-hidden" aria-live="polite" aria-atomic="true">slide <span class="current">' + getLiveRegionStr() + '</span> of ' + slideCount + '</div>');
1449
- liveregionCurrent = outerWrapper.querySelector('.tns-liveregion .current');
1450
-
1451
- // == autoplayInit ==
1452
- if (hasAutoplay) {
1453
- var txt = autoplay ? 'stop' : 'start';
1454
- if (autoplayButton) {
1455
- setAttrs(autoplayButton, {'data-action': txt});
1456
- } else if (options.autoplayButtonOutput) {
1457
- outerWrapper.insertAdjacentHTML(getInsertPosition(options.autoplayPosition), '<button type="button" data-action="' + txt + '">' + autoplayHtmlStrings[0] + txt + autoplayHtmlStrings[1] + autoplayText[0] + '</button>');
1458
- autoplayButton = outerWrapper.querySelector('[data-action]');
1459
- }
1460
-
1461
- // add event
1462
- if (autoplayButton) {
1463
- addEvents(autoplayButton, {'click': toggleAutoplay});
1464
- }
1465
-
1466
- if (autoplay) {
1467
- startAutoplay();
1468
- if (autoplayHoverPause) { addEvents(container, hoverEvents); }
1469
- if (autoplayResetOnVisibility) { addEvents(container, visibilityEvent); }
1470
- }
1471
- }
1472
-
1473
- // == navInit ==
1474
- if (hasNav) {
1475
- var initIndex = !carousel ? 0 : cloneCount;
1476
- // customized nav
1477
- // will not hide the navs in case they're thumbnails
1478
- if (navContainer) {
1479
- setAttrs(navContainer, {'aria-label': 'Carousel Pagination'});
1480
- navItems = navContainer.children;
1481
- forEach(navItems, function(item, i) {
1482
- setAttrs(item, {
1483
- 'data-nav': i,
1484
- 'tabindex': '-1',
1485
- 'aria-label': navStr + (i + 1),
1486
- 'aria-controls': slideId,
1487
- });
1488
- });
1489
-
1490
- // generated nav
1491
- } else {
1492
- var navHtml = '',
1493
- hiddenStr = navAsThumbnails ? '' : 'style="display:none"';
1494
- for (var i = 0; i < slideCount; i++) {
1495
- // hide nav items by default
1496
- navHtml += '<button type="button" data-nav="' + i +'" tabindex="-1" aria-controls="' + slideId + '" ' + hiddenStr + ' aria-label="' + navStr + (i + 1) +'"></button>';
1497
- }
1498
- navHtml = '<div class="tns-nav" aria-label="Carousel Pagination">' + navHtml + '</div>';
1499
- outerWrapper.insertAdjacentHTML(getInsertPosition(options.navPosition), navHtml);
1500
-
1501
- navContainer = outerWrapper.querySelector('.tns-nav');
1502
- navItems = navContainer.children;
1503
- }
1504
-
1505
- updateNavVisibility();
1506
-
1507
- // add transition
1508
- if (TRANSITIONDURATION) {
1509
- var prefix = TRANSITIONDURATION.substring(0, TRANSITIONDURATION.length - 18).toLowerCase(),
1510
- str = 'transition: all ' + speed / 1000 + 's';
1511
-
1512
- if (prefix) {
1513
- str = '-' + prefix + '-' + str;
1514
- }
1515
-
1516
- addCSSRule(sheet, '[aria-controls^=' + slideId + '-item]', str, getCssRulesLength(sheet));
1517
- }
1518
-
1519
- setAttrs(navItems[navCurrentIndex], {'aria-label': navStr + (navCurrentIndex + 1) + navStrCurrent});
1520
- removeAttrs(navItems[navCurrentIndex], 'tabindex');
1521
- addClass(navItems[navCurrentIndex], navActiveClass);
1522
-
1523
- // add events
1524
- addEvents(navContainer, navEvents);
1525
- }
1526
-
1527
-
1528
-
1529
- // == controlsInit ==
1530
- if (hasControls) {
1531
- if (!controlsContainer && (!prevButton || !nextButton)) {
1532
- outerWrapper.insertAdjacentHTML(getInsertPosition(options.controlsPosition), '<div class="tns-controls" aria-label="Carousel Navigation" tabindex="0"><button type="button" data-controls="prev" tabindex="-1" aria-controls="' + slideId +'">' + controlsText[0] + '</button><button type="button" data-controls="next" tabindex="-1" aria-controls="' + slideId +'">' + controlsText[1] + '</button></div>');
1533
-
1534
- controlsContainer = outerWrapper.querySelector('.tns-controls');
1535
- }
1536
-
1537
- if (!prevButton || !nextButton) {
1538
- prevButton = controlsContainer.children[0];
1539
- nextButton = controlsContainer.children[1];
1540
- }
1541
-
1542
- if (options.controlsContainer) {
1543
- setAttrs(controlsContainer, {
1544
- 'aria-label': 'Carousel Navigation',
1545
- 'tabindex': '0'
1546
- });
1547
- }
1548
-
1549
- if (options.controlsContainer || (options.prevButton && options.nextButton)) {
1550
- setAttrs([prevButton, nextButton], {
1551
- 'aria-controls': slideId,
1552
- 'tabindex': '-1',
1553
- });
1554
- }
1555
-
1556
- if (options.controlsContainer || (options.prevButton && options.nextButton)) {
1557
- setAttrs(prevButton, {'data-controls' : 'prev'});
1558
- setAttrs(nextButton, {'data-controls' : 'next'});
1559
- }
1560
-
1561
- prevIsButton = isButton(prevButton);
1562
- nextIsButton = isButton(nextButton);
1563
-
1564
- updateControlsStatus();
1565
-
1566
- // add events
1567
- if (controlsContainer) {
1568
- addEvents(controlsContainer, controlsEvents);
1569
- } else {
1570
- addEvents(prevButton, controlsEvents);
1571
- addEvents(nextButton, controlsEvents);
1572
- }
1573
- }
1574
-
1575
- // hide tools if needed
1576
- disableUI();
1577
- }
1578
-
1579
- function initEvents () {
1580
- // add events
1581
- if (carousel && TRANSITIONEND) {
1582
- var eve = {};
1583
- eve[TRANSITIONEND] = onTransitionEnd;
1584
- addEvents(container, eve);
1585
- }
1586
-
1587
- if (touch) { addEvents(container, touchEvents, options.preventScrollOnTouch); }
1588
- if (mouseDrag) { addEvents(container, dragEvents); }
1589
- if (arrowKeys) { addEvents(doc, docmentKeydownEvent); }
1590
-
1591
- if (nested === 'inner') {
1592
- events.on('outerResized', function () {
1593
- resizeTasks();
1594
- events.emit('innerLoaded', info());
1595
- });
1596
- } else if (responsive || fixedWidth || autoWidth || autoHeight || !horizontal) {
1597
- addEvents(win, {'resize': onResize});
1598
- }
1599
-
1600
- if (autoHeight) {
1601
- if (nested === 'outer') {
1602
- events.on('innerLoaded', doAutoHeight);
1603
- } else if (!disable) { doAutoHeight(); }
1604
- }
1605
-
1606
- doLazyLoad();
1607
- if (disable) { disableSlider(); } else if (freeze) { freezeSlider(); }
1608
-
1609
- events.on('indexChanged', additionalUpdates);
1610
- if (nested === 'inner') { events.emit('innerLoaded', info()); }
1611
- if (typeof onInit === 'function') { onInit(info()); }
1612
- isOn = true;
1613
- }
1614
-
1615
- function destroy () {
1616
- // sheet
1617
- sheet.disabled = true;
1618
- if (sheet.ownerNode) { sheet.ownerNode.remove(); }
1619
-
1620
- // remove win event listeners
1621
- removeEvents(win, {'resize': onResize});
1622
-
1623
- // arrowKeys, controls, nav
1624
- if (arrowKeys) { removeEvents(doc, docmentKeydownEvent); }
1625
- if (controlsContainer) { removeEvents(controlsContainer, controlsEvents); }
1626
- if (navContainer) { removeEvents(navContainer, navEvents); }
1627
-
1628
- // autoplay
1629
- removeEvents(container, hoverEvents);
1630
- removeEvents(container, visibilityEvent);
1631
- if (autoplayButton) { removeEvents(autoplayButton, {'click': toggleAutoplay}); }
1632
- if (autoplay) { clearInterval(autoplayTimer); }
1633
-
1634
- // container
1635
- if (carousel && TRANSITIONEND) {
1636
- var eve = {};
1637
- eve[TRANSITIONEND] = onTransitionEnd;
1638
- removeEvents(container, eve);
1639
- }
1640
- if (touch) { removeEvents(container, touchEvents); }
1641
- if (mouseDrag) { removeEvents(container, dragEvents); }
1642
-
1643
- // cache Object values in options && reset HTML
1644
- var htmlList = [containerHTML, controlsContainerHTML, prevButtonHTML, nextButtonHTML, navContainerHTML, autoplayButtonHTML];
1645
-
1646
- tnsList.forEach(function(item, i) {
1647
- var el = item === 'container' ? outerWrapper : options[item];
1648
-
1649
- if (typeof el === 'object' && el) {
1650
- var prevEl = el.previousElementSibling ? el.previousElementSibling : false,
1651
- parentEl = el.parentNode;
1652
- el.outerHTML = htmlList[i];
1653
- options[item] = prevEl ? prevEl.nextElementSibling : parentEl.firstElementChild;
1654
- }
1655
- });
1656
-
1657
-
1658
- // reset variables
1659
- tnsList = animateIn = animateOut = animateDelay = animateNormal = horizontal = outerWrapper = innerWrapper = container = containerParent = containerHTML = slideItems = slideCount = breakpointZone = windowWidth = autoWidth = fixedWidth = edgePadding = gutter = viewport = items = slideBy = viewportMax = arrowKeys = speed = rewind = loop = autoHeight = sheet = lazyload = slidePositions = slideItemsOut = cloneCount = slideCountNew = hasRightDeadZone = rightBoundary = updateIndexBeforeTransform = transformAttr = transformPrefix = transformPostfix = getIndexMax = index = indexCached = indexMin = indexMax = resizeTimer = swipeAngle = moveDirectionExpected = running = onInit = events = newContainerClasses = slideId = disable = disabled = freezable = freeze = frozen = controlsEvents = navEvents = hoverEvents = visibilityEvent = docmentKeydownEvent = touchEvents = dragEvents = hasControls = hasNav = navAsThumbnails = hasAutoplay = hasTouch = hasMouseDrag = slideActiveClass = imgCompleteClass = imgEvents = imgsComplete = controls = controlsText = controlsContainer = controlsContainerHTML = prevButton = nextButton = prevIsButton = nextIsButton = nav = navContainer = navContainerHTML = navItems = pages = pagesCached = navClicked = navCurrentIndex = navCurrentIndexCached = navActiveClass = navStr = navStrCurrent = autoplay = autoplayTimeout = autoplayDirection = autoplayText = autoplayHoverPause = autoplayButton = autoplayButtonHTML = autoplayResetOnVisibility = autoplayHtmlStrings = autoplayTimer = animating = autoplayHoverPaused = autoplayUserPaused = autoplayVisibilityPaused = initPosition = lastPosition = translateInit = disX = disY = panStart = rafIndex = getDist = touch = mouseDrag = null;
1660
- // check variables
1661
- // [animateIn, animateOut, animateDelay, animateNormal, horizontal, outerWrapper, innerWrapper, container, containerParent, containerHTML, slideItems, slideCount, breakpointZone, windowWidth, autoWidth, fixedWidth, edgePadding, gutter, viewport, items, slideBy, viewportMax, arrowKeys, speed, rewind, loop, autoHeight, sheet, lazyload, slidePositions, slideItemsOut, cloneCount, slideCountNew, hasRightDeadZone, rightBoundary, updateIndexBeforeTransform, transformAttr, transformPrefix, transformPostfix, getIndexMax, index, indexCached, indexMin, indexMax, resizeTimer, swipeAngle, moveDirectionExpected, running, onInit, events, newContainerClasses, slideId, disable, disabled, freezable, freeze, frozen, controlsEvents, navEvents, hoverEvents, visibilityEvent, docmentKeydownEvent, touchEvents, dragEvents, hasControls, hasNav, navAsThumbnails, hasAutoplay, hasTouch, hasMouseDrag, slideActiveClass, imgCompleteClass, imgEvents, imgsComplete, controls, controlsText, controlsContainer, controlsContainerHTML, prevButton, nextButton, prevIsButton, nextIsButton, nav, navContainer, navContainerHTML, navItems, pages, pagesCached, navClicked, navCurrentIndex, navCurrentIndexCached, navActiveClass, navStr, navStrCurrent, autoplay, autoplayTimeout, autoplayDirection, autoplayText, autoplayHoverPause, autoplayButton, autoplayButtonHTML, autoplayResetOnVisibility, autoplayHtmlStrings, autoplayTimer, animating, autoplayHoverPaused, autoplayUserPaused, autoplayVisibilityPaused, initPosition, lastPosition, translateInit, disX, disY, panStart, rafIndex, getDist, touch, mouseDrag ].forEach(function(item) { if (item !== null) { console.log(item); } });
1662
-
1663
- for (var a in this) {
1664
- if (a !== 'rebuild') { this[a] = null; }
1665
- }
1666
- isOn = false;
1667
- }
1668
-
1669
- // === ON RESIZE ===
1670
- // responsive || fixedWidth || autoWidth || !horizontal
1671
- function onResize (e) {
1672
- raf(function(){ resizeTasks(getEvent(e)); });
1673
- }
1674
-
1675
- function resizeTasks (e) {
1676
- if (!isOn) { return; }
1677
- if (nested === 'outer') { events.emit('outerResized', info(e)); }
1678
- windowWidth = getWindowWidth();
1679
- var bpChanged,
1680
- breakpointZoneTem = breakpointZone,
1681
- needContainerTransform = false;
1682
-
1683
- if (responsive) {
1684
- setBreakpointZone();
1685
- bpChanged = breakpointZoneTem !== breakpointZone;
1686
- // if (hasRightDeadZone) { needContainerTransform = true; } // *?
1687
- if (bpChanged) { events.emit('newBreakpointStart', info(e)); }
1688
- }
1689
-
1690
- var indChanged,
1691
- itemsChanged,
1692
- itemsTem = items,
1693
- disableTem = disable,
1694
- freezeTem = freeze,
1695
- arrowKeysTem = arrowKeys,
1696
- controlsTem = controls,
1697
- navTem = nav,
1698
- touchTem = touch,
1699
- mouseDragTem = mouseDrag,
1700
- autoplayTem = autoplay,
1701
- autoplayHoverPauseTem = autoplayHoverPause,
1702
- autoplayResetOnVisibilityTem = autoplayResetOnVisibility,
1703
- indexTem = index;
1704
-
1705
- if (bpChanged) {
1706
- var fixedWidthTem = fixedWidth,
1707
- autoHeightTem = autoHeight,
1708
- controlsTextTem = controlsText,
1709
- centerTem = center,
1710
- autoplayTextTem = autoplayText;
1711
-
1712
- if (!CSSMQ) {
1713
- var gutterTem = gutter,
1714
- edgePaddingTem = edgePadding;
1715
- }
1716
- }
1717
-
1718
- // get option:
1719
- // fixed width: viewport, fixedWidth, gutter => items
1720
- // others: window width => all variables
1721
- // all: items => slideBy
1722
- arrowKeys = getOption('arrowKeys');
1723
- controls = getOption('controls');
1724
- nav = getOption('nav');
1725
- touch = getOption('touch');
1726
- center = getOption('center');
1727
- mouseDrag = getOption('mouseDrag');
1728
- autoplay = getOption('autoplay');
1729
- autoplayHoverPause = getOption('autoplayHoverPause');
1730
- autoplayResetOnVisibility = getOption('autoplayResetOnVisibility');
1731
-
1732
- if (bpChanged) {
1733
- disable = getOption('disable');
1734
- fixedWidth = getOption('fixedWidth');
1735
- speed = getOption('speed');
1736
- autoHeight = getOption('autoHeight');
1737
- controlsText = getOption('controlsText');
1738
- autoplayText = getOption('autoplayText');
1739
- autoplayTimeout = getOption('autoplayTimeout');
1740
-
1741
- if (!CSSMQ) {
1742
- edgePadding = getOption('edgePadding');
1743
- gutter = getOption('gutter');
1744
- }
1745
- }
1746
- // update options
1747
- resetVariblesWhenDisable(disable);
1748
-
1749
- viewport = getViewportWidth(); // <= edgePadding, gutter
1750
- if ((!horizontal || autoWidth) && !disable) {
1751
- setSlidePositions();
1752
- if (!horizontal) {
1753
- updateContentWrapperHeight(); // <= setSlidePositions
1754
- needContainerTransform = true;
1755
- }
1756
- }
1757
- if (fixedWidth || autoWidth) {
1758
- rightBoundary = getRightBoundary(); // autoWidth: <= viewport, slidePositions, gutter
1759
- // fixedWidth: <= viewport, fixedWidth, gutter
1760
- indexMax = getIndexMax(); // autoWidth: <= rightBoundary, slidePositions
1761
- // fixedWidth: <= rightBoundary, fixedWidth, gutter
1762
- }
1763
-
1764
- if (bpChanged || fixedWidth) {
1765
- items = getOption('items');
1766
- slideBy = getOption('slideBy');
1767
- itemsChanged = items !== itemsTem;
1768
-
1769
- if (itemsChanged) {
1770
- if (!fixedWidth && !autoWidth) { indexMax = getIndexMax(); } // <= items
1771
- // check index before transform in case
1772
- // slider reach the right edge then items become bigger
1773
- updateIndex();
1774
- }
1775
- }
1776
-
1777
- if (bpChanged) {
1778
- if (disable !== disableTem) {
1779
- if (disable) {
1780
- disableSlider();
1781
- } else {
1782
- enableSlider(); // <= slidePositions, rightBoundary, indexMax
1783
- }
1784
- }
1785
- }
1786
-
1787
- if (freezable && (bpChanged || fixedWidth || autoWidth)) {
1788
- freeze = getFreeze(); // <= autoWidth: slidePositions, gutter, viewport, rightBoundary
1789
- // <= fixedWidth: fixedWidth, gutter, rightBoundary
1790
- // <= others: items
1791
-
1792
- if (freeze !== freezeTem) {
1793
- if (freeze) {
1794
- doContainerTransform(getContainerTransformValue(getStartIndex(0)));
1795
- freezeSlider();
1796
- } else {
1797
- unfreezeSlider();
1798
- needContainerTransform = true;
1799
- }
1800
- }
1801
- }
1802
-
1803
- resetVariblesWhenDisable(disable || freeze); // controls, nav, touch, mouseDrag, arrowKeys, autoplay, autoplayHoverPause, autoplayResetOnVisibility
1804
- if (!autoplay) { autoplayHoverPause = autoplayResetOnVisibility = false; }
1805
-
1806
- if (arrowKeys !== arrowKeysTem) {
1807
- arrowKeys ?
1808
- addEvents(doc, docmentKeydownEvent) :
1809
- removeEvents(doc, docmentKeydownEvent);
1810
- }
1811
- if (controls !== controlsTem) {
1812
- if (controls) {
1813
- if (controlsContainer) {
1814
- showElement(controlsContainer);
1815
- } else {
1816
- if (prevButton) { showElement(prevButton); }
1817
- if (nextButton) { showElement(nextButton); }
1818
- }
1819
- } else {
1820
- if (controlsContainer) {
1821
- hideElement(controlsContainer);
1822
- } else {
1823
- if (prevButton) { hideElement(prevButton); }
1824
- if (nextButton) { hideElement(nextButton); }
1825
- }
1826
- }
1827
- }
1828
- if (nav !== navTem) {
1829
- if (nav) {
1830
- showElement(navContainer);
1831
- updateNavVisibility();
1832
- } else {
1833
- hideElement(navContainer);
1834
- }
1835
- }
1836
- if (touch !== touchTem) {
1837
- touch ?
1838
- addEvents(container, touchEvents, options.preventScrollOnTouch) :
1839
- removeEvents(container, touchEvents);
1840
- }
1841
- if (mouseDrag !== mouseDragTem) {
1842
- mouseDrag ?
1843
- addEvents(container, dragEvents) :
1844
- removeEvents(container, dragEvents);
1845
- }
1846
- if (autoplay !== autoplayTem) {
1847
- if (autoplay) {
1848
- if (autoplayButton) { showElement(autoplayButton); }
1849
- if (!animating && !autoplayUserPaused) { startAutoplay(); }
1850
- } else {
1851
- if (autoplayButton) { hideElement(autoplayButton); }
1852
- if (animating) { stopAutoplay(); }
1853
- }
1854
- }
1855
- if (autoplayHoverPause !== autoplayHoverPauseTem) {
1856
- autoplayHoverPause ?
1857
- addEvents(container, hoverEvents) :
1858
- removeEvents(container, hoverEvents);
1859
- }
1860
- if (autoplayResetOnVisibility !== autoplayResetOnVisibilityTem) {
1861
- autoplayResetOnVisibility ?
1862
- addEvents(doc, visibilityEvent) :
1863
- removeEvents(doc, visibilityEvent);
1864
- }
1865
-
1866
- if (bpChanged) {
1867
- if (fixedWidth !== fixedWidthTem || center !== centerTem) { needContainerTransform = true; }
1868
-
1869
- if (autoHeight !== autoHeightTem) {
1870
- if (!autoHeight) { innerWrapper.style.height = ''; }
1871
- }
1872
-
1873
- if (controls && controlsText !== controlsTextTem) {
1874
- prevButton.innerHTML = controlsText[0];
1875
- nextButton.innerHTML = controlsText[1];
1876
- }
1877
-
1878
- if (autoplayButton && autoplayText !== autoplayTextTem) {
1879
- var i = autoplay ? 1 : 0,
1880
- html = autoplayButton.innerHTML,
1881
- len = html.length - autoplayTextTem[i].length;
1882
- if (html.substring(len) === autoplayTextTem[i]) {
1883
- autoplayButton.innerHTML = html.substring(0, len) + autoplayText[i];
1884
- }
1885
- }
1886
- } else {
1887
- if (center && (fixedWidth || autoWidth)) { needContainerTransform = true; }
1888
- }
1889
-
1890
- if (itemsChanged || fixedWidth && !autoWidth) {
1891
- pages = getPages();
1892
- updateNavVisibility();
1893
- }
1894
-
1895
- indChanged = index !== indexTem;
1896
- if (indChanged) {
1897
- events.emit('indexChanged', info());
1898
- needContainerTransform = true;
1899
- } else if (itemsChanged) {
1900
- if (!indChanged) { additionalUpdates(); }
1901
- } else if (fixedWidth || autoWidth) {
1902
- doLazyLoad();
1903
- updateSlideStatus();
1904
- updateLiveRegion();
1905
- }
1906
-
1907
- if (itemsChanged && !carousel) { updateGallerySlidePositions(); }
1908
-
1909
- if (!disable && !freeze) {
1910
- // non-mediaqueries: IE8
1911
- if (bpChanged && !CSSMQ) {
1912
- // middle wrapper styles
1913
-
1914
- // inner wrapper styles
1915
- if (edgePadding !== edgePaddingTem || gutter !== gutterTem) {
1916
- innerWrapper.style.cssText = getInnerWrapperStyles(edgePadding, gutter, fixedWidth, speed, autoHeight);
1917
- }
1918
-
1919
- if (horizontal) {
1920
- // container styles
1921
- if (carousel) {
1922
- container.style.width = getContainerWidth(fixedWidth, gutter, items);
1923
- }
1924
-
1925
- // slide styles
1926
- var str = getSlideWidthStyle(fixedWidth, gutter, items) +
1927
- getSlideGutterStyle(gutter);
1928
-
1929
- // remove the last line and
1930
- // add new styles
1931
- removeCSSRule(sheet, getCssRulesLength(sheet) - 1);
1932
- addCSSRule(sheet, '#' + slideId + ' > .tns-item', str, getCssRulesLength(sheet));
1933
- }
1934
- }
1935
-
1936
- // auto height
1937
- if (autoHeight) { doAutoHeight(); }
1938
-
1939
- if (needContainerTransform) {
1940
- doContainerTransformSilent();
1941
- indexCached = index;
1942
- }
1943
- }
1944
-
1945
- if (bpChanged) { events.emit('newBreakpointEnd', info(e)); }
1946
- }
1947
-
1948
-
1949
-
1950
-
1951
-
1952
- // === INITIALIZATION FUNCTIONS === //
1953
- function getFreeze () {
1954
- if (!fixedWidth && !autoWidth) {
1955
- var a = center ? items - (items - 1) / 2 : items;
1956
- return slideCount <= a;
1957
- }
1958
-
1959
- var width = fixedWidth ? (fixedWidth + gutter) * slideCount : slidePositions[slideCount],
1960
- vp = edgePadding ? viewport + edgePadding * 2 : viewport + gutter;
1961
-
1962
- if (center) {
1963
- vp -= fixedWidth ? (viewport - fixedWidth) / 2 : (viewport - (slidePositions[index + 1] - slidePositions[index] - gutter)) / 2;
1964
- }
1965
-
1966
- return width <= vp;
1967
- }
1968
-
1969
- function setBreakpointZone () {
1970
- breakpointZone = 0;
1971
- for (var bp in responsive) {
1972
- bp = parseInt(bp); // convert string to number
1973
- if (windowWidth >= bp) { breakpointZone = bp; }
1974
- }
1975
- }
1976
-
1977
- // (slideBy, indexMin, indexMax) => index
1978
- var updateIndex = (function () {
1979
- return loop ?
1980
- carousel ?
1981
- // loop + carousel
1982
- function () {
1983
- var leftEdge = indexMin,
1984
- rightEdge = indexMax;
1985
-
1986
- leftEdge += slideBy;
1987
- rightEdge -= slideBy;
1988
-
1989
- // adjust edges when has edge paddings
1990
- // or fixed-width slider with extra space on the right side
1991
- if (edgePadding) {
1992
- leftEdge += 1;
1993
- rightEdge -= 1;
1994
- } else if (fixedWidth) {
1995
- if ((viewport + gutter)%(fixedWidth + gutter)) { rightEdge -= 1; }
1996
- }
1997
-
1998
- if (cloneCount) {
1999
- if (index > rightEdge) {
2000
- index -= slideCount;
2001
- } else if (index < leftEdge) {
2002
- index += slideCount;
2003
- }
2004
- }
2005
- } :
2006
- // loop + gallery
2007
- function() {
2008
- if (index > indexMax) {
2009
- while (index >= indexMin + slideCount) { index -= slideCount; }
2010
- } else if (index < indexMin) {
2011
- while (index <= indexMax - slideCount) { index += slideCount; }
2012
- }
2013
- } :
2014
- // non-loop
2015
- function() {
2016
- index = Math.max(indexMin, Math.min(indexMax, index));
2017
- };
2018
- })();
2019
-
2020
- function disableUI () {
2021
- if (!autoplay && autoplayButton) { hideElement(autoplayButton); }
2022
- if (!nav && navContainer) { hideElement(navContainer); }
2023
- if (!controls) {
2024
- if (controlsContainer) {
2025
- hideElement(controlsContainer);
2026
- } else {
2027
- if (prevButton) { hideElement(prevButton); }
2028
- if (nextButton) { hideElement(nextButton); }
2029
- }
2030
- }
2031
- }
2032
-
2033
- function enableUI () {
2034
- if (autoplay && autoplayButton) { showElement(autoplayButton); }
2035
- if (nav && navContainer) { showElement(navContainer); }
2036
- if (controls) {
2037
- if (controlsContainer) {
2038
- showElement(controlsContainer);
2039
- } else {
2040
- if (prevButton) { showElement(prevButton); }
2041
- if (nextButton) { showElement(nextButton); }
2042
- }
2043
- }
2044
- }
2045
-
2046
- function freezeSlider () {
2047
- if (frozen) { return; }
2048
-
2049
- // remove edge padding from inner wrapper
2050
- if (edgePadding) { innerWrapper.style.margin = '0px'; }
2051
-
2052
- // add class tns-transparent to cloned slides
2053
- if (cloneCount) {
2054
- var str = 'tns-transparent';
2055
- for (var i = cloneCount; i--;) {
2056
- if (carousel) { addClass(slideItems[i], str); }
2057
- addClass(slideItems[slideCountNew - i - 1], str);
2058
- }
2059
- }
2060
-
2061
- // update tools
2062
- disableUI();
2063
-
2064
- frozen = true;
2065
- }
2066
-
2067
- function unfreezeSlider () {
2068
- if (!frozen) { return; }
2069
-
2070
- // restore edge padding for inner wrapper
2071
- // for mordern browsers
2072
- if (edgePadding && CSSMQ) { innerWrapper.style.margin = ''; }
2073
-
2074
- // remove class tns-transparent to cloned slides
2075
- if (cloneCount) {
2076
- var str = 'tns-transparent';
2077
- for (var i = cloneCount; i--;) {
2078
- if (carousel) { removeClass(slideItems[i], str); }
2079
- removeClass(slideItems[slideCountNew - i - 1], str);
2080
- }
2081
- }
2082
-
2083
- // update tools
2084
- enableUI();
2085
-
2086
- frozen = false;
2087
- }
2088
-
2089
- function disableSlider () {
2090
- if (disabled) { return; }
2091
-
2092
- sheet.disabled = true;
2093
- container.className = container.className.replace(newContainerClasses.substring(1), '');
2094
- removeAttrs(container, ['style']);
2095
- if (loop) {
2096
- for (var j = cloneCount; j--;) {
2097
- if (carousel) { hideElement(slideItems[j]); }
2098
- hideElement(slideItems[slideCountNew - j - 1]);
2099
- }
2100
- }
2101
-
2102
- // vertical slider
2103
- if (!horizontal || !carousel) { removeAttrs(innerWrapper, ['style']); }
2104
-
2105
- // gallery
2106
- if (!carousel) {
2107
- for (var i = index, l = index + slideCount; i < l; i++) {
2108
- var item = slideItems[i];
2109
- removeAttrs(item, ['style']);
2110
- removeClass(item, animateIn);
2111
- removeClass(item, animateNormal);
2112
- }
2113
- }
2114
-
2115
- // update tools
2116
- disableUI();
2117
-
2118
- disabled = true;
2119
- }
2120
-
2121
- function enableSlider () {
2122
- if (!disabled) { return; }
2123
-
2124
- sheet.disabled = false;
2125
- container.className += newContainerClasses;
2126
- doContainerTransformSilent();
2127
-
2128
- if (loop) {
2129
- for (var j = cloneCount; j--;) {
2130
- if (carousel) { showElement(slideItems[j]); }
2131
- showElement(slideItems[slideCountNew - j - 1]);
2132
- }
2133
- }
2134
-
2135
- // gallery
2136
- if (!carousel) {
2137
- for (var i = index, l = index + slideCount; i < l; i++) {
2138
- var item = slideItems[i],
2139
- classN = i < index + items ? animateIn : animateNormal;
2140
- item.style.left = (i - index) * 100 / items + '%';
2141
- addClass(item, classN);
2142
- }
2143
- }
2144
-
2145
- // update tools
2146
- enableUI();
2147
-
2148
- disabled = false;
2149
- }
2150
-
2151
- function updateLiveRegion () {
2152
- var str = getLiveRegionStr();
2153
- if (liveregionCurrent.innerHTML !== str) { liveregionCurrent.innerHTML = str; }
2154
- }
2155
-
2156
- function getLiveRegionStr () {
2157
- var arr = getVisibleSlideRange(),
2158
- start = arr[0] + 1,
2159
- end = arr[1] + 1;
2160
- return start === end ? start + '' : start + ' to ' + end;
2161
- }
2162
-
2163
- function getVisibleSlideRange (val) {
2164
- if (val == null) { val = getContainerTransformValue(); }
2165
- var start = index, end, rangestart, rangeend;
2166
-
2167
- // get range start, range end for autoWidth and fixedWidth
2168
- if (center || edgePadding) {
2169
- if (autoWidth || fixedWidth) {
2170
- rangestart = - (parseFloat(val) + edgePadding);
2171
- rangeend = rangestart + viewport + edgePadding * 2;
2172
- }
2173
- } else {
2174
- if (autoWidth) {
2175
- rangestart = slidePositions[index];
2176
- rangeend = rangestart + viewport;
2177
- }
2178
- }
2179
-
2180
- // get start, end
2181
- // - check auto width
2182
- if (autoWidth) {
2183
- slidePositions.forEach(function(point, i) {
2184
- if (i < slideCountNew) {
2185
- if ((center || edgePadding) && point <= rangestart + 0.5) { start = i; }
2186
- if (rangeend - point >= 0.5) { end = i; }
2187
- }
2188
- });
2189
-
2190
- // - check percentage width, fixed width
2191
- } else {
2192
-
2193
- if (fixedWidth) {
2194
- var cell = fixedWidth + gutter;
2195
- if (center || edgePadding) {
2196
- start = Math.floor(rangestart/cell);
2197
- end = Math.ceil(rangeend/cell - 1);
2198
- } else {
2199
- end = start + Math.ceil(viewport/cell) - 1;
2200
- }
2201
-
2202
- } else {
2203
- if (center || edgePadding) {
2204
- var a = items - 1;
2205
- if (center) {
2206
- start -= a / 2;
2207
- end = index + a / 2;
2208
- } else {
2209
- end = index + a;
2210
- }
2211
-
2212
- if (edgePadding) {
2213
- var b = edgePadding * items / viewport;
2214
- start -= b;
2215
- end += b;
2216
- }
2217
-
2218
- start = Math.floor(start);
2219
- end = Math.ceil(end);
2220
- } else {
2221
- end = start + items - 1;
2222
- }
2223
- }
2224
-
2225
- start = Math.max(start, 0);
2226
- end = Math.min(end, slideCountNew - 1);
2227
- }
2228
-
2229
- return [start, end];
2230
- }
2231
-
2232
- function doLazyLoad () {
2233
- if (lazyload && !disable) {
2234
- var arg = getVisibleSlideRange();
2235
- arg.push(lazyloadSelector);
2236
-
2237
- getImageArray.apply(null, arg).forEach(function (img) {
2238
- if (!hasClass(img, imgCompleteClass)) {
2239
- // stop propagation transitionend event to container
2240
- var eve = {};
2241
- eve[TRANSITIONEND] = function (e) { e.stopPropagation(); };
2242
- addEvents(img, eve);
2243
-
2244
- addEvents(img, imgEvents);
2245
-
2246
- // update src
2247
- img.src = getAttr(img, 'data-src');
2248
-
2249
- // update srcset
2250
- var srcset = getAttr(img, 'data-srcset');
2251
- if (srcset) { img.srcset = srcset; }
2252
-
2253
- addClass(img, 'loading');
2254
- }
2255
- });
2256
- }
2257
- }
2258
-
2259
- function onImgLoaded (e) {
2260
- imgLoaded(getTarget(e));
2261
- }
2262
-
2263
- function onImgFailed (e) {
2264
- imgFailed(getTarget(e));
2265
- }
2266
-
2267
- function imgLoaded (img) {
2268
- addClass(img, 'loaded');
2269
- imgCompleted(img);
2270
- }
2271
-
2272
- function imgFailed (img) {
2273
- addClass(img, 'failed');
2274
- imgCompleted(img);
2275
- }
2276
-
2277
- function imgCompleted (img) {
2278
- addClass(img, imgCompleteClass);
2279
- removeClass(img, 'loading');
2280
- removeEvents(img, imgEvents);
2281
- }
2282
-
2283
- function getImageArray (start, end, imgSelector) {
2284
- var imgs = [];
2285
- if (!imgSelector) { imgSelector = 'img'; }
2286
-
2287
- while (start <= end) {
2288
- forEach(slideItems[start].querySelectorAll(imgSelector), function (img) { imgs.push(img); });
2289
- start++;
2290
- }
2291
-
2292
- return imgs;
2293
- }
2294
-
2295
- // check if all visible images are loaded
2296
- // and update container height if it's done
2297
- function doAutoHeight () {
2298
- var imgs = getImageArray.apply(null, getVisibleSlideRange());
2299
- raf(function(){ imgsLoadedCheck(imgs, updateInnerWrapperHeight); });
2300
- }
2301
-
2302
- function imgsLoadedCheck (imgs, cb) {
2303
- // execute callback function if all images are complete
2304
- if (imgsComplete) { return cb(); }
2305
-
2306
- // check image classes
2307
- imgs.forEach(function (img, index) {
2308
- if (!lazyload && img.complete) { imgCompleted(img); } // Check image.complete
2309
- if (hasClass(img, imgCompleteClass)) { imgs.splice(index, 1); }
2310
- });
2311
-
2312
- // execute callback function if selected images are all complete
2313
- if (!imgs.length) { return cb(); }
2314
-
2315
- // otherwise execute this functiona again
2316
- raf(function(){ imgsLoadedCheck(imgs, cb); });
2317
- }
2318
-
2319
- function additionalUpdates () {
2320
- doLazyLoad();
2321
- updateSlideStatus();
2322
- updateLiveRegion();
2323
- updateControlsStatus();
2324
- updateNavStatus();
2325
- }
2326
-
2327
-
2328
- function update_carousel_transition_duration () {
2329
- if (carousel && autoHeight) {
2330
- middleWrapper.style[TRANSITIONDURATION] = speed / 1000 + 's';
2331
- }
2332
- }
2333
-
2334
- function getMaxSlideHeight (slideStart, slideRange) {
2335
- var heights = [];
2336
- for (var i = slideStart, l = Math.min(slideStart + slideRange, slideCountNew); i < l; i++) {
2337
- heights.push(slideItems[i].offsetHeight);
2338
- }
2339
-
2340
- return Math.max.apply(null, heights);
2341
- }
2342
-
2343
- // update inner wrapper height
2344
- // 1. get the max-height of the visible slides
2345
- // 2. set transitionDuration to speed
2346
- // 3. update inner wrapper height to max-height
2347
- // 4. set transitionDuration to 0s after transition done
2348
- function updateInnerWrapperHeight () {
2349
- var maxHeight = autoHeight ? getMaxSlideHeight(index, items) : getMaxSlideHeight(cloneCount, slideCount),
2350
- wp = middleWrapper ? middleWrapper : innerWrapper;
2351
-
2352
- if (wp.style.height !== maxHeight) { wp.style.height = maxHeight + 'px'; }
2353
- }
2354
-
2355
- // get the distance from the top edge of the first slide to each slide
2356
- // (init) => slidePositions
2357
- function setSlidePositions () {
2358
- slidePositions = [0];
2359
- var attr = horizontal ? 'left' : 'top',
2360
- attr2 = horizontal ? 'right' : 'bottom',
2361
- base = slideItems[0].getBoundingClientRect()[attr];
2362
-
2363
- forEach(slideItems, function(item, i) {
2364
- // skip the first slide
2365
- if (i) { slidePositions.push(item.getBoundingClientRect()[attr] - base); }
2366
- // add the end edge
2367
- if (i === slideCountNew - 1) { slidePositions.push(item.getBoundingClientRect()[attr2] - base); }
2368
- });
2369
- }
2370
-
2371
- // update slide
2372
- function updateSlideStatus () {
2373
- var range = getVisibleSlideRange(),
2374
- start = range[0],
2375
- end = range[1];
2376
-
2377
- forEach(slideItems, function(item, i) {
2378
- // show slides
2379
- if (i >= start && i <= end) {
2380
- if (hasAttr(item, 'aria-hidden')) {
2381
- removeAttrs(item, ['aria-hidden', 'tabindex']);
2382
- addClass(item, slideActiveClass);
2383
- }
2384
- // hide slides
2385
- } else {
2386
- if (!hasAttr(item, 'aria-hidden')) {
2387
- setAttrs(item, {
2388
- 'aria-hidden': 'true',
2389
- 'tabindex': '-1'
2390
- });
2391
- removeClass(item, slideActiveClass);
2392
- }
2393
- }
2394
- });
2395
- }
2396
-
2397
- // gallery: update slide position
2398
- function updateGallerySlidePositions () {
2399
- var l = index + Math.min(slideCount, items);
2400
- for (var i = slideCountNew; i--;) {
2401
- var item = slideItems[i];
2402
-
2403
- if (i >= index && i < l) {
2404
- // add transitions to visible slides when adjusting their positions
2405
- addClass(item, 'tns-moving');
2406
-
2407
- item.style.left = (i - index) * 100 / items + '%';
2408
- addClass(item, animateIn);
2409
- removeClass(item, animateNormal);
2410
- } else if (item.style.left) {
2411
- item.style.left = '';
2412
- addClass(item, animateNormal);
2413
- removeClass(item, animateIn);
2414
- }
2415
-
2416
- // remove outlet animation
2417
- removeClass(item, animateOut);
2418
- }
2419
-
2420
- // removing '.tns-moving'
2421
- setTimeout(function() {
2422
- forEach(slideItems, function(el) {
2423
- removeClass(el, 'tns-moving');
2424
- });
2425
- }, 300);
2426
- }
2427
-
2428
- // set tabindex on Nav
2429
- function updateNavStatus () {
2430
- // get current nav
2431
- if (nav) {
2432
- navCurrentIndex = navClicked >= 0 ? navClicked : getCurrentNavIndex();
2433
- navClicked = -1;
2434
-
2435
- if (navCurrentIndex !== navCurrentIndexCached) {
2436
- var navPrev = navItems[navCurrentIndexCached],
2437
- navCurrent = navItems[navCurrentIndex];
2438
-
2439
- setAttrs(navPrev, {
2440
- 'tabindex': '-1',
2441
- 'aria-label': navStr + (navCurrentIndexCached + 1)
2442
- });
2443
- removeClass(navPrev, navActiveClass);
2444
-
2445
- setAttrs(navCurrent, {'aria-label': navStr + (navCurrentIndex + 1) + navStrCurrent});
2446
- removeAttrs(navCurrent, 'tabindex');
2447
- addClass(navCurrent, navActiveClass);
2448
-
2449
- navCurrentIndexCached = navCurrentIndex;
2450
- }
2451
- }
2452
- }
2453
-
2454
- function getLowerCaseNodeName (el) {
2455
- return el.nodeName.toLowerCase();
2456
- }
2457
-
2458
- function isButton (el) {
2459
- return getLowerCaseNodeName(el) === 'button';
2460
- }
2461
-
2462
- function isAriaDisabled (el) {
2463
- return el.getAttribute('aria-disabled') === 'true';
2464
- }
2465
-
2466
- function disEnableElement (isButton, el, val) {
2467
- if (isButton) {
2468
- el.disabled = val;
2469
- } else {
2470
- el.setAttribute('aria-disabled', val.toString());
2471
- }
2472
- }
2473
-
2474
- // set 'disabled' to true on controls when reach the edges
2475
- function updateControlsStatus () {
2476
- if (!controls || rewind || loop) { return; }
2477
-
2478
- var prevDisabled = (prevIsButton) ? prevButton.disabled : isAriaDisabled(prevButton),
2479
- nextDisabled = (nextIsButton) ? nextButton.disabled : isAriaDisabled(nextButton),
2480
- disablePrev = (index <= indexMin) ? true : false,
2481
- disableNext = (!rewind && index >= indexMax) ? true : false;
2482
-
2483
- if (disablePrev && !prevDisabled) {
2484
- disEnableElement(prevIsButton, prevButton, true);
2485
- }
2486
- if (!disablePrev && prevDisabled) {
2487
- disEnableElement(prevIsButton, prevButton, false);
2488
- }
2489
- if (disableNext && !nextDisabled) {
2490
- disEnableElement(nextIsButton, nextButton, true);
2491
- }
2492
- if (!disableNext && nextDisabled) {
2493
- disEnableElement(nextIsButton, nextButton, false);
2494
- }
2495
- }
2496
-
2497
- // set duration
2498
- function resetDuration (el, str) {
2499
- if (TRANSITIONDURATION) { el.style[TRANSITIONDURATION] = str; }
2500
- }
2501
-
2502
- function getSliderWidth () {
2503
- return fixedWidth ? (fixedWidth + gutter) * slideCountNew : slidePositions[slideCountNew];
2504
- }
2505
-
2506
- function getCenterGap (num) {
2507
- if (num == null) { num = index; }
2508
-
2509
- var gap = edgePadding ? gutter : 0;
2510
- return autoWidth ? ((viewport - gap) - (slidePositions[num + 1] - slidePositions[num] - gutter))/2 :
2511
- fixedWidth ? (viewport - fixedWidth) / 2 :
2512
- (items - 1) / 2;
2513
- }
2514
-
2515
- function getRightBoundary () {
2516
- var gap = edgePadding ? gutter : 0,
2517
- result = (viewport + gap) - getSliderWidth();
2518
-
2519
- if (center && !loop) {
2520
- result = fixedWidth ? - (fixedWidth + gutter) * (slideCountNew - 1) - getCenterGap() :
2521
- getCenterGap(slideCountNew - 1) - slidePositions[slideCountNew - 1];
2522
- }
2523
- if (result > 0) { result = 0; }
2524
-
2525
- return result;
2526
- }
2527
-
2528
- function getContainerTransformValue (num) {
2529
- if (num == null) { num = index; }
2530
-
2531
- var val;
2532
- if (horizontal && !autoWidth) {
2533
- if (fixedWidth) {
2534
- val = - (fixedWidth + gutter) * num;
2535
- if (center) { val += getCenterGap(); }
2536
- } else {
2537
- var denominator = TRANSFORM ? slideCountNew : items;
2538
- if (center) { num -= getCenterGap(); }
2539
- val = - num * 100 / denominator;
2540
- }
2541
- } else {
2542
- val = - slidePositions[num];
2543
- if (center && autoWidth) {
2544
- val += getCenterGap();
2545
- }
2546
- }
2547
-
2548
- if (hasRightDeadZone) { val = Math.max(val, rightBoundary); }
2549
-
2550
- val += (horizontal && !autoWidth && !fixedWidth) ? '%' : 'px';
2551
-
2552
- return val;
2553
- }
2554
-
2555
- function doContainerTransformSilent (val) {
2556
- resetDuration(container, '0s');
2557
- doContainerTransform(val);
2558
- }
2559
-
2560
- function doContainerTransform (val) {
2561
- if (val == null) { val = getContainerTransformValue(); }
2562
- if (textDirection === 'rtl' && val.charAt(0) === '-') {
2563
- val = val.substr(1);
2564
- }
2565
- container.style[transformAttr] = transformPrefix + val + transformPostfix;
2566
- }
2567
-
2568
- function animateSlide (number, classOut, classIn, isOut) {
2569
- var l = number + items;
2570
- if (!loop) { l = Math.min(l, slideCountNew); }
2571
-
2572
- for (var i = number; i < l; i++) {
2573
- var item = slideItems[i];
2574
-
2575
- // set item positions
2576
- if (!isOut) { item.style.left = (i - index) * 100 / items + '%'; }
2577
-
2578
- if (animateDelay && TRANSITIONDELAY) {
2579
- item.style[TRANSITIONDELAY] = item.style[ANIMATIONDELAY] = animateDelay * (i - number) / 1000 + 's';
2580
- }
2581
- removeClass(item, classOut);
2582
- addClass(item, classIn);
2583
-
2584
- if (isOut) { slideItemsOut.push(item); }
2585
- }
2586
- }
2587
-
2588
- // make transfer after click/drag:
2589
- // 1. change 'transform' property for mordern browsers
2590
- // 2. change 'left' property for legacy browsers
2591
- var transformCore = (function () {
2592
- return carousel ?
2593
- function () {
2594
- resetDuration(container, '');
2595
- if (TRANSITIONDURATION || !speed) {
2596
- // for morden browsers with non-zero duration or
2597
- // zero duration for all browsers
2598
- doContainerTransform();
2599
- // run fallback function manually
2600
- // when duration is 0 / container is hidden
2601
- if (!speed || !isVisible(container)) { onTransitionEnd(); }
2602
-
2603
- } else {
2604
- // for old browser with non-zero duration
2605
- jsTransform(container, transformAttr, transformPrefix, transformPostfix, getContainerTransformValue(), speed, onTransitionEnd);
2606
- }
2607
-
2608
- if (!horizontal) { updateContentWrapperHeight(); }
2609
- } :
2610
- function () {
2611
- slideItemsOut = [];
2612
-
2613
- var eve = {};
2614
- eve[TRANSITIONEND] = eve[ANIMATIONEND] = onTransitionEnd;
2615
- removeEvents(slideItems[indexCached], eve);
2616
- addEvents(slideItems[index], eve);
2617
-
2618
- animateSlide(indexCached, animateIn, animateOut, true);
2619
- animateSlide(index, animateNormal, animateIn);
2620
-
2621
- // run fallback function manually
2622
- // when transition or animation not supported / duration is 0
2623
- if (!TRANSITIONEND || !ANIMATIONEND || !speed || !isVisible(container)) { onTransitionEnd(); }
2624
- };
2625
- })();
2626
-
2627
- function render (e, sliderMoved) {
2628
- if (updateIndexBeforeTransform) { updateIndex(); }
2629
-
2630
- // render when slider was moved (touch or drag) even though index may not change
2631
- if (index !== indexCached || sliderMoved) {
2632
- // events
2633
- events.emit('indexChanged', info());
2634
- events.emit('transitionStart', info());
2635
- if (autoHeight) { doAutoHeight(); }
2636
-
2637
- // pause autoplay when click or keydown from user
2638
- if (animating && e && ['click', 'keydown'].indexOf(e.type) >= 0) { stopAutoplay(); }
2639
-
2640
- running = true;
2641
- transformCore();
2642
- }
2643
- }
2644
-
2645
- /*
2646
- * Transfer prefixed properties to the same format
2647
- * CSS: -Webkit-Transform => webkittransform
2648
- * JS: WebkitTransform => webkittransform
2649
- * @param {string} str - property
2650
- *
2651
- */
2652
- function strTrans (str) {
2653
- return str.toLowerCase().replace(/-/g, '');
2654
- }
2655
-
2656
- // AFTER TRANSFORM
2657
- // Things need to be done after a transfer:
2658
- // 1. check index
2659
- // 2. add classes to visible slide
2660
- // 3. disable controls buttons when reach the first/last slide in non-loop slider
2661
- // 4. update nav status
2662
- // 5. lazyload images
2663
- // 6. update container height
2664
- function onTransitionEnd (event) {
2665
- // check running on gallery mode
2666
- // make sure trantionend/animationend events run only once
2667
- if (carousel || running) {
2668
- events.emit('transitionEnd', info(event));
2669
-
2670
- if (!carousel && slideItemsOut.length > 0) {
2671
- for (var i = 0; i < slideItemsOut.length; i++) {
2672
- var item = slideItemsOut[i];
2673
- // set item positions
2674
- item.style.left = '';
2675
-
2676
- if (ANIMATIONDELAY && TRANSITIONDELAY) {
2677
- item.style[ANIMATIONDELAY] = '';
2678
- item.style[TRANSITIONDELAY] = '';
2679
- }
2680
- removeClass(item, animateOut);
2681
- addClass(item, animateNormal);
2682
- }
2683
- }
2684
-
2685
- /* update slides, nav, controls after checking ...
2686
- * => legacy browsers who don't support 'event'
2687
- * have to check event first, otherwise event.target will cause an error
2688
- * => or 'gallery' mode:
2689
- * + event target is slide item
2690
- * => or 'carousel' mode:
2691
- * + event target is container,
2692
- * + event.property is the same with transform attribute
2693
- */
2694
- if (!event ||
2695
- !carousel && event.target.parentNode === container ||
2696
- event.target === container && strTrans(event.propertyName) === strTrans(transformAttr)) {
2697
-
2698
- if (!updateIndexBeforeTransform) {
2699
- var indexTem = index;
2700
- updateIndex();
2701
- if (index !== indexTem) {
2702
- events.emit('indexChanged', info());
2703
-
2704
- doContainerTransformSilent();
2705
- }
2706
- }
2707
-
2708
- if (nested === 'inner') { events.emit('innerLoaded', info()); }
2709
- running = false;
2710
- indexCached = index;
2711
- }
2712
- }
2713
-
2714
- }
2715
-
2716
- // # ACTIONS
2717
- function goTo (targetIndex, e) {
2718
- if (freeze) { return; }
2719
-
2720
- // prev slideBy
2721
- if (targetIndex === 'prev') {
2722
- onControlsClick(e, -1);
2723
-
2724
- // next slideBy
2725
- } else if (targetIndex === 'next') {
2726
- onControlsClick(e, 1);
2727
-
2728
- // go to exact slide
2729
- } else {
2730
- if (running) {
2731
- if (preventActionWhenRunning) { return; } else { onTransitionEnd(); }
2732
- }
2733
-
2734
- var absIndex = getAbsIndex(),
2735
- indexGap = 0;
2736
-
2737
- if (targetIndex === 'first') {
2738
- indexGap = - absIndex;
2739
- } else if (targetIndex === 'last') {
2740
- indexGap = carousel ? slideCount - items - absIndex : slideCount - 1 - absIndex;
2741
- } else {
2742
- if (typeof targetIndex !== 'number') { targetIndex = parseInt(targetIndex); }
2743
-
2744
- if (!isNaN(targetIndex)) {
2745
- // from directly called goTo function
2746
- if (!e) { targetIndex = Math.max(0, Math.min(slideCount - 1, targetIndex)); }
2747
-
2748
- indexGap = targetIndex - absIndex;
2749
- }
2750
- }
2751
-
2752
- // gallery: make sure new page won't overlap with current page
2753
- if (!carousel && indexGap && Math.abs(indexGap) < items) {
2754
- var factor = indexGap > 0 ? 1 : -1;
2755
- indexGap += (index + indexGap - slideCount) >= indexMin ? slideCount * factor : slideCount * 2 * factor * -1;
2756
- }
2757
-
2758
- index += indexGap;
2759
-
2760
- // make sure index is in range
2761
- if (carousel && loop) {
2762
- if (index < indexMin) { index += slideCount; }
2763
- if (index > indexMax) { index -= slideCount; }
2764
- }
2765
-
2766
- // if index is changed, start rendering
2767
- if (getAbsIndex(index) !== getAbsIndex(indexCached)) {
2768
- render(e);
2769
- }
2770
-
2771
- }
2772
- }
2773
-
2774
- // on controls click
2775
- function onControlsClick (e, dir) {
2776
- if (running) {
2777
- if (preventActionWhenRunning) { return; } else { onTransitionEnd(); }
2778
- }
2779
- var passEventObject;
2780
-
2781
- if (!dir) {
2782
- e = getEvent(e);
2783
- var target = getTarget(e);
2784
-
2785
- while (target !== controlsContainer && [prevButton, nextButton].indexOf(target) < 0) { target = target.parentNode; }
2786
-
2787
- var targetIn = [prevButton, nextButton].indexOf(target);
2788
- if (targetIn >= 0) {
2789
- passEventObject = true;
2790
- dir = targetIn === 0 ? -1 : 1;
2791
- }
2792
- }
2793
-
2794
- if (rewind) {
2795
- if (index === indexMin && dir === -1) {
2796
- goTo('last', e);
2797
- return;
2798
- } else if (index === indexMax && dir === 1) {
2799
- goTo('first', e);
2800
- return;
2801
- }
2802
- }
2803
-
2804
- if (dir) {
2805
- index += slideBy * dir;
2806
- if (autoWidth) { index = Math.floor(index); }
2807
- // pass e when click control buttons or keydown
2808
- render((passEventObject || (e && e.type === 'keydown')) ? e : null);
2809
- }
2810
- }
2811
-
2812
- // on nav click
2813
- function onNavClick (e) {
2814
- if (running) {
2815
- if (preventActionWhenRunning) { return; } else { onTransitionEnd(); }
2816
- }
2817
-
2818
- e = getEvent(e);
2819
- var target = getTarget(e), navIndex;
2820
-
2821
- // find the clicked nav item
2822
- while (target !== navContainer && !hasAttr(target, 'data-nav')) { target = target.parentNode; }
2823
- if (hasAttr(target, 'data-nav')) {
2824
- var navIndex = navClicked = Number(getAttr(target, 'data-nav')),
2825
- targetIndexBase = fixedWidth || autoWidth ? navIndex * slideCount / pages : navIndex * items,
2826
- targetIndex = navAsThumbnails ? navIndex : Math.min(Math.ceil(targetIndexBase), slideCount - 1);
2827
- goTo(targetIndex, e);
2828
-
2829
- if (navCurrentIndex === navIndex) {
2830
- if (animating) { stopAutoplay(); }
2831
- navClicked = -1; // reset navClicked
2832
- }
2833
- }
2834
- }
2835
-
2836
- // autoplay functions
2837
- function setAutoplayTimer () {
2838
- autoplayTimer = setInterval(function () {
2839
- onControlsClick(null, autoplayDirection);
2840
- }, autoplayTimeout);
2841
-
2842
- animating = true;
2843
- }
2844
-
2845
- function stopAutoplayTimer () {
2846
- clearInterval(autoplayTimer);
2847
- animating = false;
2848
- }
2849
-
2850
- function updateAutoplayButton (action, txt) {
2851
- setAttrs(autoplayButton, {'data-action': action});
2852
- autoplayButton.innerHTML = autoplayHtmlStrings[0] + action + autoplayHtmlStrings[1] + txt;
2853
- }
2854
-
2855
- function startAutoplay () {
2856
- setAutoplayTimer();
2857
- if (autoplayButton) { updateAutoplayButton('stop', autoplayText[1]); }
2858
- }
2859
-
2860
- function stopAutoplay () {
2861
- stopAutoplayTimer();
2862
- if (autoplayButton) { updateAutoplayButton('start', autoplayText[0]); }
2863
- }
2864
-
2865
- // programaitcally play/pause the slider
2866
- function play () {
2867
- if (autoplay && !animating) {
2868
- startAutoplay();
2869
- autoplayUserPaused = false;
2870
- }
2871
- }
2872
- function pause () {
2873
- if (animating) {
2874
- stopAutoplay();
2875
- autoplayUserPaused = true;
2876
- }
2877
- }
2878
-
2879
- function toggleAutoplay () {
2880
- if (animating) {
2881
- stopAutoplay();
2882
- autoplayUserPaused = true;
2883
- } else {
2884
- startAutoplay();
2885
- autoplayUserPaused = false;
2886
- }
2887
- }
2888
-
2889
- function onVisibilityChange () {
2890
- if (doc.hidden) {
2891
- if (animating) {
2892
- stopAutoplayTimer();
2893
- autoplayVisibilityPaused = true;
2894
- }
2895
- } else if (autoplayVisibilityPaused) {
2896
- setAutoplayTimer();
2897
- autoplayVisibilityPaused = false;
2898
- }
2899
- }
2900
-
2901
- function mouseoverPause () {
2902
- if (animating) {
2903
- stopAutoplayTimer();
2904
- autoplayHoverPaused = true;
2905
- }
2906
- }
2907
-
2908
- function mouseoutRestart () {
2909
- if (autoplayHoverPaused) {
2910
- setAutoplayTimer();
2911
- autoplayHoverPaused = false;
2912
- }
2913
- }
2914
-
2915
- // keydown events on document
2916
- function onDocumentKeydown (e) {
2917
- e = getEvent(e);
2918
- var keyIndex = [KEYS.LEFT, KEYS.RIGHT].indexOf(e.keyCode);
2919
-
2920
- if (keyIndex >= 0) {
2921
- onControlsClick(e, keyIndex === 0 ? -1 : 1);
2922
- }
2923
- }
2924
-
2925
- // on key control
2926
- function onControlsKeydown (e) {
2927
- e = getEvent(e);
2928
- var keyIndex = [KEYS.LEFT, KEYS.RIGHT].indexOf(e.keyCode);
2929
-
2930
- if (keyIndex >= 0) {
2931
- if (keyIndex === 0) {
2932
- if (!prevButton.disabled) { onControlsClick(e, -1); }
2933
- } else if (!nextButton.disabled) {
2934
- onControlsClick(e, 1);
2935
- }
2936
- }
2937
- }
2938
-
2939
- // set focus
2940
- function setFocus (el) {
2941
- el.focus();
2942
- }
2943
-
2944
- // on key nav
2945
- function onNavKeydown (e) {
2946
- e = getEvent(e);
2947
- var curElement = doc.activeElement;
2948
- if (!hasAttr(curElement, 'data-nav')) { return; }
2949
-
2950
- // var code = e.keyCode,
2951
- var keyIndex = [KEYS.LEFT, KEYS.RIGHT, KEYS.ENTER, KEYS.SPACE].indexOf(e.keyCode),
2952
- navIndex = Number(getAttr(curElement, 'data-nav'));
2953
-
2954
- if (keyIndex >= 0) {
2955
- if (keyIndex === 0) {
2956
- if (navIndex > 0) { setFocus(navItems[navIndex - 1]); }
2957
- } else if (keyIndex === 1) {
2958
- if (navIndex < pages - 1) { setFocus(navItems[navIndex + 1]); }
2959
- } else {
2960
- navClicked = navIndex;
2961
- goTo(navIndex, e);
2962
- }
2963
- }
2964
- }
2965
-
2966
- function getEvent (e) {
2967
- e = e || win.event;
2968
- return isTouchEvent(e) ? e.changedTouches[0] : e;
2969
- }
2970
- function getTarget (e) {
2971
- return e.target || win.event.srcElement;
2972
- }
2973
-
2974
- function isTouchEvent (e) {
2975
- return e.type.indexOf('touch') >= 0;
2976
- }
2977
-
2978
- function preventDefaultBehavior (e) {
2979
- e.preventDefault ? e.preventDefault() : e.returnValue = false;
2980
- }
2981
-
2982
- function getMoveDirectionExpected () {
2983
- return getTouchDirection(toDegree(lastPosition.y - initPosition.y, lastPosition.x - initPosition.x), swipeAngle) === options.axis;
2984
- }
2985
-
2986
- function onPanStart (e) {
2987
- if (running) {
2988
- if (preventActionWhenRunning) { return; } else { onTransitionEnd(); }
2989
- }
2990
-
2991
- if (autoplay && animating) { stopAutoplayTimer(); }
2992
-
2993
- panStart = true;
2994
- if (rafIndex) {
2995
- caf(rafIndex);
2996
- rafIndex = null;
2997
- }
2998
-
2999
- var $ = getEvent(e);
3000
- events.emit(isTouchEvent(e) ? 'touchStart' : 'dragStart', info(e));
3001
-
3002
- if (!isTouchEvent(e) && ['img', 'a'].indexOf(getLowerCaseNodeName(getTarget(e))) >= 0) {
3003
- preventDefaultBehavior(e);
3004
- }
3005
-
3006
- lastPosition.x = initPosition.x = $.clientX;
3007
- lastPosition.y = initPosition.y = $.clientY;
3008
- if (carousel) {
3009
- translateInit = parseFloat(container.style[transformAttr].replace(transformPrefix, ''));
3010
- resetDuration(container, '0s');
3011
- }
3012
- }
3013
-
3014
- function onPanMove (e) {
3015
- if (panStart) {
3016
- var $ = getEvent(e);
3017
- lastPosition.x = $.clientX;
3018
- lastPosition.y = $.clientY;
3019
-
3020
- if (carousel) {
3021
- if (!rafIndex) { rafIndex = raf(function(){ panUpdate(e); }); }
3022
- } else {
3023
- if (moveDirectionExpected === '?') { moveDirectionExpected = getMoveDirectionExpected(); }
3024
- if (moveDirectionExpected) { preventScroll = true; }
3025
- }
3026
-
3027
- if ((typeof e.cancelable !== 'boolean' || e.cancelable) && preventScroll) {
3028
- e.preventDefault();
3029
- }
3030
- }
3031
- }
3032
-
3033
- function panUpdate (e) {
3034
- if (!moveDirectionExpected) {
3035
- panStart = false;
3036
- return;
3037
- }
3038
- caf(rafIndex);
3039
- if (panStart) { rafIndex = raf(function(){ panUpdate(e); }); }
3040
-
3041
- if (moveDirectionExpected === '?') { moveDirectionExpected = getMoveDirectionExpected(); }
3042
- if (moveDirectionExpected) {
3043
- if (!preventScroll && isTouchEvent(e)) { preventScroll = true; }
3044
-
3045
- try {
3046
- if (e.type) { events.emit(isTouchEvent(e) ? 'touchMove' : 'dragMove', info(e)); }
3047
- } catch(err) {}
3048
-
3049
- var x = translateInit,
3050
- dist = getDist(lastPosition, initPosition);
3051
- if (!horizontal || fixedWidth || autoWidth) {
3052
- x += dist;
3053
- x += 'px';
3054
- } else {
3055
- var percentageX = TRANSFORM ? dist * items * 100 / ((viewport + gutter) * slideCountNew): dist * 100 / (viewport + gutter);
3056
- x += percentageX;
3057
- x += '%';
3058
- }
3059
-
3060
- container.style[transformAttr] = transformPrefix + x + transformPostfix;
3061
- }
3062
- }
3063
-
3064
- function onPanEnd (e) {
3065
- if (panStart) {
3066
- if (rafIndex) {
3067
- caf(rafIndex);
3068
- rafIndex = null;
3069
- }
3070
- if (carousel) { resetDuration(container, ''); }
3071
- panStart = false;
3072
-
3073
- var $ = getEvent(e);
3074
- lastPosition.x = $.clientX;
3075
- lastPosition.y = $.clientY;
3076
- var dist = getDist(lastPosition, initPosition);
3077
-
3078
- if (Math.abs(dist)) {
3079
- // drag vs click
3080
- if (!isTouchEvent(e)) {
3081
- // prevent "click"
3082
- var target = getTarget(e);
3083
- addEvents(target, {'click': function preventClick (e) {
3084
- preventDefaultBehavior(e);
3085
- removeEvents(target, {'click': preventClick});
3086
- }});
3087
- }
3088
-
3089
- if (carousel) {
3090
- rafIndex = raf(function() {
3091
- if (horizontal && !autoWidth) {
3092
- var indexMoved = - dist * items / (viewport + gutter);
3093
- indexMoved = dist > 0 ? Math.floor(indexMoved) : Math.ceil(indexMoved);
3094
- if (textDirection === 'rtl') {
3095
- index += indexMoved * -1;
3096
- } else {
3097
- index += indexMoved;
3098
- }
3099
- } else {
3100
- var moved = - (translateInit + dist);
3101
- if (moved <= 0) {
3102
- index = indexMin;
3103
- } else if (moved >= slidePositions[slideCountNew - 1]) {
3104
- index = indexMax;
3105
- } else {
3106
- var i = 0;
3107
- while (i < slideCountNew && moved >= slidePositions[i]) {
3108
- index = i;
3109
- if (moved > slidePositions[i] && dist < 0) { index += 1; }
3110
- i++;
3111
- }
3112
- }
3113
- }
3114
-
3115
- render(e, dist);
3116
- events.emit(isTouchEvent(e) ? 'touchEnd' : 'dragEnd', info(e));
3117
- });
3118
- } else {
3119
- if (moveDirectionExpected) {
3120
- onControlsClick(e, dist > 0 ? -1 : 1);
3121
- }
3122
- }
3123
- }
3124
- }
3125
-
3126
- // reset
3127
- if (options.preventScrollOnTouch === 'auto') { preventScroll = false; }
3128
- if (swipeAngle) { moveDirectionExpected = '?'; }
3129
- if (autoplay && !animating) { setAutoplayTimer(); }
3130
- }
3131
-
3132
- // === RESIZE FUNCTIONS === //
3133
- // (slidePositions, index, items) => vertical_conentWrapper.height
3134
- function updateContentWrapperHeight () {
3135
- var wp = middleWrapper ? middleWrapper : innerWrapper;
3136
- wp.style.height = slidePositions[index + items] - slidePositions[index] + 'px';
3137
- }
3138
-
3139
- function getPages () {
3140
- var rough = fixedWidth ? (fixedWidth + gutter) * slideCount / viewport : slideCount / items;
3141
- return Math.min(Math.ceil(rough), slideCount);
3142
- }
3143
-
3144
- /*
3145
- * 1. update visible nav items list
3146
- * 2. add "hidden" attributes to previous visible nav items
3147
- * 3. remove "hidden" attrubutes to new visible nav items
3148
- */
3149
- function updateNavVisibility () {
3150
- if (!nav || navAsThumbnails) { return; }
3151
-
3152
- if (pages !== pagesCached) {
3153
- var min = pagesCached,
3154
- max = pages,
3155
- fn = showElement;
3156
-
3157
- if (pagesCached > pages) {
3158
- min = pages;
3159
- max = pagesCached;
3160
- fn = hideElement;
3161
- }
3162
-
3163
- while (min < max) {
3164
- fn(navItems[min]);
3165
- min++;
3166
- }
3167
-
3168
- // cache pages
3169
- pagesCached = pages;
3170
- }
3171
- }
3172
-
3173
- function info (e) {
3174
- return {
3175
- container: container,
3176
- slideItems: slideItems,
3177
- navContainer: navContainer,
3178
- navItems: navItems,
3179
- controlsContainer: controlsContainer,
3180
- hasControls: hasControls,
3181
- prevButton: prevButton,
3182
- nextButton: nextButton,
3183
- items: items,
3184
- slideBy: slideBy,
3185
- cloneCount: cloneCount,
3186
- slideCount: slideCount,
3187
- slideCountNew: slideCountNew,
3188
- index: index,
3189
- indexCached: indexCached,
3190
- displayIndex: getCurrentSlide(),
3191
- navCurrentIndex: navCurrentIndex,
3192
- navCurrentIndexCached: navCurrentIndexCached,
3193
- pages: pages,
3194
- pagesCached: pagesCached,
3195
- sheet: sheet,
3196
- isOn: isOn,
3197
- event: e || {},
3198
- };
3199
- }
3200
-
3201
- return {
3202
- version: '2.9.3',
3203
- getInfo: info,
3204
- events: events,
3205
- goTo: goTo,
3206
- play: play,
3207
- pause: pause,
3208
- isOn: isOn,
3209
- updateSliderHeight: updateInnerWrapperHeight,
3210
- refresh: initSliderTransform,
3211
- destroy: destroy,
3212
- rebuild: function() {
3213
- return tns(extend(options, optionsElements));
3214
- }
3215
- };
3216
- };
3217
-
3218
- return tns;
3219
- })();
3220
-
3221
- export default tns;