nexmo-oas-renderer 0.1.0

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 (158) hide show
  1. checksums.yaml +7 -0
  2. data/.env.example +1 -0
  3. data/.gitignore +5 -0
  4. data/CHANGELOG.md +2 -0
  5. data/CONTRIBUTING.md +46 -0
  6. data/Gemfile +4 -0
  7. data/Gemfile.lock +183 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +73 -0
  10. data/Rakefile +2 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/exe/nexmo-oas-renderer +5 -0
  14. data/lib/nexmo/oas/engine.rb +9 -0
  15. data/lib/nexmo/oas/renderer.rb +13 -0
  16. data/lib/nexmo/oas/renderer/app.rb +116 -0
  17. data/lib/nexmo/oas/renderer/config.ru +7 -0
  18. data/lib/nexmo/oas/renderer/config/code_languages.yml +138 -0
  19. data/lib/nexmo/oas/renderer/config/dynamic_content.yml +1 -0
  20. data/lib/nexmo/oas/renderer/config/redirects.yml +8 -0
  21. data/lib/nexmo/oas/renderer/constraints/open_api.rb +76 -0
  22. data/lib/nexmo/oas/renderer/constraints/redirector.rb +17 -0
  23. data/lib/nexmo/oas/renderer/decorators/response_parser_decorator.rb +55 -0
  24. data/lib/nexmo/oas/renderer/filters/anchor.rb +17 -0
  25. data/lib/nexmo/oas/renderer/filters/audio.rb +21 -0
  26. data/lib/nexmo/oas/renderer/filters/block_escape.rb +24 -0
  27. data/lib/nexmo/oas/renderer/filters/break.rb +13 -0
  28. data/lib/nexmo/oas/renderer/filters/code.rb +64 -0
  29. data/lib/nexmo/oas/renderer/filters/code_snippet.rb +194 -0
  30. data/lib/nexmo/oas/renderer/filters/code_snippet_list.rb +33 -0
  31. data/lib/nexmo/oas/renderer/filters/code_snippets.rb +158 -0
  32. data/lib/nexmo/oas/renderer/filters/collapsible.rb +27 -0
  33. data/lib/nexmo/oas/renderer/filters/columns.rb +50 -0
  34. data/lib/nexmo/oas/renderer/filters/concept_list.rb +33 -0
  35. data/lib/nexmo/oas/renderer/filters/dynamic_content.rb +30 -0
  36. data/lib/nexmo/oas/renderer/filters/external_link.rb +32 -0
  37. data/lib/nexmo/oas/renderer/filters/frontmatter.rb +14 -0
  38. data/lib/nexmo/oas/renderer/filters/heading.rb +61 -0
  39. data/lib/nexmo/oas/renderer/filters/icon.rb +22 -0
  40. data/lib/nexmo/oas/renderer/filters/indent.rb +20 -0
  41. data/lib/nexmo/oas/renderer/filters/inline_escape.rb +17 -0
  42. data/lib/nexmo/oas/renderer/filters/js_sequence_diagram.rb +21 -0
  43. data/lib/nexmo/oas/renderer/filters/label.rb +32 -0
  44. data/lib/nexmo/oas/renderer/filters/language.rb +15 -0
  45. data/lib/nexmo/oas/renderer/filters/markdown.rb +85 -0
  46. data/lib/nexmo/oas/renderer/filters/modal.rb +41 -0
  47. data/lib/nexmo/oas/renderer/filters/partial.rb +28 -0
  48. data/lib/nexmo/oas/renderer/filters/php_inliner.rb +15 -0
  49. data/lib/nexmo/oas/renderer/filters/screenshot.rb +26 -0
  50. data/lib/nexmo/oas/renderer/filters/tab.rb +250 -0
  51. data/lib/nexmo/oas/renderer/filters/techio.rb +24 -0
  52. data/lib/nexmo/oas/renderer/filters/tooltip.rb +22 -0
  53. data/lib/nexmo/oas/renderer/filters/tutorial_link.rb +27 -0
  54. data/lib/nexmo/oas/renderer/filters/tutorials.rb +28 -0
  55. data/lib/nexmo/oas/renderer/filters/unfreeze.rb +20 -0
  56. data/lib/nexmo/oas/renderer/filters/user_personalization.rb +43 -0
  57. data/lib/nexmo/oas/renderer/helpers/navigation.rb +66 -0
  58. data/lib/nexmo/oas/renderer/helpers/render.rb +24 -0
  59. data/lib/nexmo/oas/renderer/helpers/summary.rb +30 -0
  60. data/lib/nexmo/oas/renderer/helpers/url.rb +17 -0
  61. data/lib/nexmo/oas/renderer/lib/core_ext/string.rb +14 -0
  62. data/lib/nexmo/oas/renderer/lib/redcarpet.rb +14 -0
  63. data/lib/nexmo/oas/renderer/models/code_snippet.rb +75 -0
  64. data/lib/nexmo/oas/renderer/models/tutorial.rb +83 -0
  65. data/lib/nexmo/oas/renderer/pipelines/markdown_pipeline.rb +52 -0
  66. data/lib/nexmo/oas/renderer/presenters/api_specification.rb +42 -0
  67. data/lib/nexmo/oas/renderer/presenters/groups.rb +35 -0
  68. data/lib/nexmo/oas/renderer/presenters/navigation.rb +24 -0
  69. data/lib/nexmo/oas/renderer/presenters/open_api_specification.rb +68 -0
  70. data/lib/nexmo/oas/renderer/presenters/versions.rb +40 -0
  71. data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Black.woff +0 -0
  72. data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Black.woff2 +0 -0
  73. data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Heavy.woff +0 -0
  74. data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Heavy.woff2 +0 -0
  75. data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Regular.woff +0 -0
  76. data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Regular.woff2 +0 -0
  77. data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Semibold.woff +0 -0
  78. data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Semibold.woff2 +0 -0
  79. data/lib/nexmo/oas/renderer/public/assets/images/brands/android.svg +1 -0
  80. data/lib/nexmo/oas/renderer/public/assets/images/brands/curl.svg +1 -0
  81. data/lib/nexmo/oas/renderer/public/assets/images/brands/dotnet.svg +1 -0
  82. data/lib/nexmo/oas/renderer/public/assets/images/brands/ios.svg +1 -0
  83. data/lib/nexmo/oas/renderer/public/assets/images/brands/java.svg +1 -0
  84. data/lib/nexmo/oas/renderer/public/assets/images/brands/javascript.svg +1 -0
  85. data/lib/nexmo/oas/renderer/public/assets/images/brands/node.svg +1 -0
  86. data/lib/nexmo/oas/renderer/public/assets/images/brands/php.svg +1 -0
  87. data/lib/nexmo/oas/renderer/public/assets/images/brands/python.svg +11 -0
  88. data/lib/nexmo/oas/renderer/public/assets/images/brands/ruby.svg +1 -0
  89. data/lib/nexmo/oas/renderer/public/assets/images/lost.svg +37 -0
  90. data/lib/nexmo/oas/renderer/public/assets/javascripts/components/format.js +42 -0
  91. data/lib/nexmo/oas/renderer/public/assets/javascripts/volta.accordion.js +249 -0
  92. data/lib/nexmo/oas/renderer/public/assets/javascripts/volta.core.js +230 -0
  93. data/lib/nexmo/oas/renderer/public/assets/javascripts/volta.modal.js +300 -0
  94. data/lib/nexmo/oas/renderer/public/assets/javascripts/volta.tabs.js +139 -0
  95. data/lib/nexmo/oas/renderer/public/assets/stylesheets/api.css +95 -0
  96. data/lib/nexmo/oas/renderer/public/assets/stylesheets/buttons.css +80 -0
  97. data/lib/nexmo/oas/renderer/public/assets/stylesheets/core.css +79 -0
  98. data/lib/nexmo/oas/renderer/public/assets/stylesheets/mediaqueries.css +2 -0
  99. data/lib/nexmo/oas/renderer/public/assets/stylesheets/mediaqueries.css.map +7 -0
  100. data/lib/nexmo/oas/renderer/public/assets/stylesheets/navigation.css +79 -0
  101. data/lib/nexmo/oas/renderer/public/assets/stylesheets/nexmo.css +68 -0
  102. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/api.scss +147 -0
  103. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/core.scss +133 -0
  104. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/mediaqueries.scss +48 -0
  105. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/navigation.scss +106 -0
  106. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/nexmo.scss +61 -0
  107. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/style.scss +10 -0
  108. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/syntax.scss +63 -0
  109. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/typography.scss +248 -0
  110. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/variables.scss +91 -0
  111. data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/volta-templates.scss +119 -0
  112. data/lib/nexmo/oas/renderer/public/assets/stylesheets/style.css +2 -0
  113. data/lib/nexmo/oas/renderer/public/assets/stylesheets/style.css.map +7 -0
  114. data/lib/nexmo/oas/renderer/public/assets/stylesheets/syntax.css +79 -0
  115. data/lib/nexmo/oas/renderer/public/assets/stylesheets/typography.css +86 -0
  116. data/lib/nexmo/oas/renderer/public/assets/stylesheets/variables.css +2 -0
  117. data/lib/nexmo/oas/renderer/public/assets/stylesheets/variables.css.map +7 -0
  118. data/lib/nexmo/oas/renderer/public/assets/stylesheets/volta-templates.css +2 -0
  119. data/lib/nexmo/oas/renderer/public/assets/stylesheets/volta-templates.css.map +7 -0
  120. data/lib/nexmo/oas/renderer/public/assets/stylesheets/volta.min.css +1 -0
  121. data/lib/nexmo/oas/renderer/public/assets/symbol/volta-icons.svg +1 -0
  122. data/lib/nexmo/oas/renderer/public/favicon.ico +0 -0
  123. data/lib/nexmo/oas/renderer/services/code_language_api.rb +98 -0
  124. data/lib/nexmo/oas/renderer/services/oas_parser.rb +21 -0
  125. data/lib/nexmo/oas/renderer/services/open_api_definition_resolver.rb +33 -0
  126. data/lib/nexmo/oas/renderer/version.rb +7 -0
  127. data/lib/nexmo/oas/renderer/views/api/show.erb +1 -0
  128. data/lib/nexmo/oas/renderer/views/code_snippets/_application_messages_dispatch.html.erb +9 -0
  129. data/lib/nexmo/oas/renderer/views/code_snippets/_application_rtc.html.erb +41 -0
  130. data/lib/nexmo/oas/renderer/views/code_snippets/_application_voice.html.erb +24 -0
  131. data/lib/nexmo/oas/renderer/views/code_snippets/_code_only.html.erb +6 -0
  132. data/lib/nexmo/oas/renderer/views/code_snippets/_configure_client.html.erb +20 -0
  133. data/lib/nexmo/oas/renderer/views/code_snippets/_dependencies.html.erb +11 -0
  134. data/lib/nexmo/oas/renderer/views/code_snippets/_write_code.html.erb +13 -0
  135. data/lib/nexmo/oas/renderer/views/code_snippets/list/plain.html.erb +10 -0
  136. data/lib/nexmo/oas/renderer/views/concepts/list/plain.html.erb +5 -0
  137. data/lib/nexmo/oas/renderer/views/layouts/_head.erb +4 -0
  138. data/lib/nexmo/oas/renderer/views/layouts/_javascripts.erb +9 -0
  139. data/lib/nexmo/oas/renderer/views/layouts/api.erb +23 -0
  140. data/lib/nexmo/oas/renderer/views/layouts/open_api.erb +10 -0
  141. data/lib/nexmo/oas/renderer/views/open_api/_callback.erb +5 -0
  142. data/lib/nexmo/oas/renderer/views/open_api/_callback_endpoint.erb +48 -0
  143. data/lib/nexmo/oas/renderer/views/open_api/_code_examples.erb +16 -0
  144. data/lib/nexmo/oas/renderer/views/open_api/_endpoint.erb +156 -0
  145. data/lib/nexmo/oas/renderer/views/open_api/_model.erb +38 -0
  146. data/lib/nexmo/oas/renderer/views/open_api/_navigation.erb +80 -0
  147. data/lib/nexmo/oas/renderer/views/open_api/_parameter_groups.erb +50 -0
  148. data/lib/nexmo/oas/renderer/views/open_api/_parameters.erb +165 -0
  149. data/lib/nexmo/oas/renderer/views/open_api/_response_description_parameters.erb +61 -0
  150. data/lib/nexmo/oas/renderer/views/open_api/_response_descriptions.erb +41 -0
  151. data/lib/nexmo/oas/renderer/views/open_api/show.erb +104 -0
  152. data/lib/nexmo/oas/renderer/views/static/404.erb +6 -0
  153. data/lib/nexmo/oas/renderer/views/tutorials/_index.html.erb +32 -0
  154. data/lib/nexmo/oas/renderer/views/tutorials/index.html.erb +7 -0
  155. data/lib/nexmo/oas/renderer/views/tutorials/list/plain.html.erb +5 -0
  156. data/lib/nexmo/oas/renderer/views/tutorials/show.html.erb +8 -0
  157. data/nexmo-oas-renderer.gemspec +49 -0
  158. metadata +399 -0
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Copyright (c) 2001-present, Vonage.
3
+ *
4
+ * Core of volta
5
+ */
6
+ 'use strict';
7
+ var Volta;
8
+
9
+ Volta = function (){
10
+ return {
11
+ _closest: closest,
12
+ _hasClass: hasClass,
13
+ init: initialise,
14
+ _isMobile: isMobileDevice,
15
+ _getElementSiblings: getElementSiblings,
16
+ _getFunction: getFunctionFromString,
17
+ _removeFromArr: removeFromArr
18
+ }
19
+
20
+ /**
21
+ * @private
22
+ *
23
+ * @description Finds the first ancestor of the given element, matching a specific selector.
24
+ * @param {HTMLElement} element Starting element
25
+ * @param {string} selector Selector to find (can be .class, #id, div...)
26
+ * @param {string} stopSelector Selector to stop searching on (can be .class, #id, div...)
27
+ * @returns {HTMLElement|null} The matched element or null if no element is found
28
+ */
29
+ function closest(element, selector, stopSelector) {
30
+ var match = null;
31
+ while (element) {
32
+ if (element.matches(selector)) {
33
+ match = element;
34
+ break
35
+ } else if (stopSelector && element.matches(stopSelector)) {
36
+ break
37
+ }
38
+ element = element.parentElement;
39
+ }
40
+ return match;
41
+ }
42
+
43
+ /**
44
+ * @private
45
+ * @description Given the name of a function returns the function itself
46
+ * @param {string} callbackFnName The function name e.g. "testFunction" OR "test.function"
47
+ * @returns {Function}
48
+ */
49
+ function getFunctionFromString(fnName) {
50
+ var fn;
51
+
52
+ if(fnName) {
53
+ var fnNames = fnName.split(".");
54
+ var fn = window;
55
+ for(var i = 0; i < fnNames.length; i++) {
56
+ fn = fn[fnNames[i]];
57
+ }
58
+ }
59
+
60
+ return fn;
61
+ }
62
+
63
+ /**
64
+ * @private
65
+ * @description Get all siblings of an element
66
+ * @param {HTMLElement} el
67
+ */
68
+ function getElementSiblings(element) {
69
+ var siblings = [];
70
+ element = element.parentNode.firstChild;
71
+ do {
72
+ if(element.nodeType === 1) {
73
+ siblings.push(element);
74
+ }
75
+ } while (element = element.nextSibling);
76
+ return siblings;
77
+ }
78
+
79
+ /**
80
+ * @private
81
+ *
82
+ * @description Check if the given element has a particular class
83
+ * @param {HTMLElement} el Element to evaluate
84
+ * @param {string} className Class name to check for
85
+ * @returns {boolean} True if the element has the class or false if not
86
+ */
87
+ function hasClass(element, className) {
88
+ if(!element) {
89
+ return false;
90
+ }
91
+ return (" " + element.className + " ").replace(/[\n\t]/g, " ").indexOf(" " + className+ " ") > -1;
92
+ }
93
+
94
+ /**
95
+ * @private
96
+ *
97
+ * @description Is the current device a mobile
98
+ * @returns {boolean} True if mobile false if not
99
+ */
100
+ function isMobileDevice() {
101
+ var isMobile = /Android|webOS|iPhone|iPad|BlackBerry|Windows Phone|Opera Mini|IEMobile|Mobile/i;
102
+
103
+ return isMobile.test(navigator.userAgent);
104
+ }
105
+
106
+ /**
107
+ * @public
108
+ *
109
+ * @description Initailise volta with required components
110
+ * @param {Array} components Array of strings, names of the components to initialise
111
+ */
112
+ function initialise(components) {
113
+ polyfilsForIE11();
114
+
115
+ if(components.indexOf('accordion') !== -1){
116
+ if(Volta.accordion) {
117
+ Volta.accordion.init();
118
+ } else {
119
+ console.warn('Volta: volta.accordion.js component missing')
120
+ }
121
+ }
122
+ if(components.indexOf('callout') !== -1){
123
+ if(Volta.callout) {
124
+ Volta.callout.init();
125
+ } else {
126
+ console.warn('Volta: volta.callout.js component missing')
127
+ }
128
+ }
129
+ if(components.indexOf('badge') !== -1){
130
+ if(Volta.badge) {
131
+ Volta.badge.init();
132
+ } else {
133
+ console.warn('Volta: volta.badge.js component missing')
134
+ }
135
+ }
136
+ if(components.indexOf('dropdown') !== -1){
137
+ if(Volta.dropdown) {
138
+ Volta.dropdown.init();
139
+ } else {
140
+ console.warn('Volta: volta.dropdown.js component missing')
141
+ }
142
+ }
143
+ if(components.indexOf('flash') !== -1){
144
+ if(Volta.flash) {
145
+ Volta.flash.init();
146
+ } else {
147
+ console.warn('Volta: volta.dropdown.js component missing')
148
+ }
149
+ }
150
+ if(components.indexOf('menu') !== -1){
151
+ if(Volta.menu) {
152
+ Volta.menu.init();
153
+ } else {
154
+ console.warn('Volta: volta.menu.js component missing')
155
+ }
156
+ }
157
+ if(components.indexOf('menuCollapse') !== -1){
158
+ if(Volta.menuCollapse) {
159
+ Volta.menuCollapse.init();
160
+ } else {
161
+ console.warn('Volta: volta.menuCollapse.js component missing')
162
+ }
163
+ }
164
+ if(components.indexOf('modal') !== -1){
165
+ if(Volta.modal) {
166
+ Volta.modal.init();
167
+ } else {
168
+ console.warn('Volta: volta.modal.js component missing')
169
+ }
170
+ }
171
+ if(components.indexOf('tab') !== -1){
172
+ if(Volta.tab) {
173
+ Volta.tab.init();
174
+ } else {
175
+ console.warn('Volta: volta.tab.js component missing')
176
+ }
177
+ }
178
+ if(components.indexOf('tooltip') !== -1){
179
+ if(Volta.tooltip) {
180
+ Volta.tooltip.init();
181
+ } else {
182
+ console.warn('Volta: volta.tooltip.js component missing')
183
+ }
184
+ }
185
+ }
186
+
187
+ /**
188
+ * @private
189
+ *
190
+ * @description Remove an element from an array
191
+ * @param {Array} arr The array containing the element
192
+ * @param {Element} element The element to remove
193
+ * @returns {Array} The array minus the element
194
+ */
195
+ function removeFromArr(arr, element) {
196
+ var index = arr.indexOf(element);
197
+ arr.splice(index, 1);
198
+ return arr;
199
+ }
200
+
201
+ /**
202
+ * @private
203
+ *
204
+ */
205
+ function polyfilsForIE11() {
206
+ if (window.NodeList && !NodeList.prototype.forEach) {
207
+ NodeList.prototype.forEach = function (callback, thisArg) {
208
+ thisArg = thisArg || window;
209
+ for (var i = 0; i < this.length; i++) {
210
+ callback.call(thisArg, this[i], i, this);
211
+ }
212
+ };
213
+ }
214
+
215
+ if (!Element.prototype.matches) {
216
+ Element.prototype.matches =
217
+ Element.prototype.matchesSelector ||
218
+ Element.prototype.mozMatchesSelector ||
219
+ Element.prototype.msMatchesSelector ||
220
+ Element.prototype.oMatchesSelector ||
221
+ Element.prototype.webkitMatchesSelector ||
222
+ function(s) {
223
+ var matches = (this.document || this.ownerDocument).querySelectorAll(s),
224
+ i = matches.length;
225
+ while (--i >= 0 && matches.item(i) !== this) {}
226
+ return i > -1;
227
+ };
228
+ }
229
+ }
230
+ }();
@@ -0,0 +1,300 @@
1
+ /**
2
+ * Copyright (c) 2001-present, Vonage.
3
+ *
4
+ * Modals (requires core)
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ Volta.modal = function () {
10
+ var _class = {
11
+ auto: 'Vlt-modal--auto',
12
+ bodyModalOpen: 'Vlt-body--modal-open',
13
+ cancel: 'Vlt-modal__cancel',
14
+ confirm: 'Vlt-modal__confirm',
15
+ content: 'Vlt-modal__content',
16
+ modal: 'Vlt-modal',
17
+ out: 'Vlt-modal--out',
18
+ panel: 'Vlt-modal__panel',
19
+ trigger: 'Vlt-modal-trigger',
20
+ visible: 'Vlt-modal_visible',
21
+ dismiss: 'Vlt-modal__dismiss',
22
+ }
23
+
24
+ var body,
25
+ dismissModalHandler,
26
+ cancelModalHandler,
27
+ confirmModalHandler,
28
+ escHandler,
29
+ clickHandler,
30
+ escAttached;
31
+
32
+ function Modal() {}
33
+
34
+ Modal.prototype = {
35
+ attachButtons: function() {
36
+ var _this = this;
37
+ _this.dismissBtn = _this.modal.querySelector('.' + _class.dismiss);
38
+
39
+ if(_this.dismissBtn) {
40
+ dismissModalHandler = dismissModal.bind(_this);
41
+ _this.dismissBtn.addEventListener('click', dismissModalHandler);
42
+ }
43
+
44
+ _this.cancelBtn = _this.modal.querySelector('.' + _class.cancel);
45
+
46
+ if(_this.cancelBtn) {
47
+ cancelModalHandler = cancelModal.bind(_this);
48
+ _this.cancelBtn.addEventListener('click', cancelModalHandler);
49
+ }
50
+
51
+ _this.confirmBtn = _this.modal.querySelector('.' + _class.confirm);
52
+
53
+ if(_this.confirmBtn) {
54
+ confirmModalHandler = confirmModal.bind(_this);
55
+ _this.confirmBtn.addEventListener('click', confirmModalHandler);
56
+ }
57
+ },
58
+ html: function(newHtml) {
59
+ this.modal.innerHTML = newHtml;
60
+ return this;
61
+ },
62
+ init: function(elementOrId) {
63
+ if(elementOrId.length) {
64
+ this.modal = document.querySelector('#' + elementOrId);
65
+ } else {
66
+ this.modal = elementOrId;
67
+ }
68
+
69
+ this._callback = Volta._getFunction(this.modal.dataset.callback);
70
+ },
71
+ open: function(e) {
72
+ if(e && e.preventDefault) {
73
+ e.preventDefault();
74
+ e.stopPropagation();
75
+ }
76
+
77
+ this.modal.classList.remove(_class.out);
78
+ this.modal.classList.add(_class.visible);
79
+ this.attachButtons();
80
+
81
+ disableScroll();
82
+
83
+ if(!escAttached && !this.modal.dataset.disableEsc || this.modal.dataset.disableEsc === "false") {
84
+ escHandler = closeModalOnEscape.bind(this);
85
+ body.addEventListener('keyup', escHandler, { once: true });
86
+ escAttached = true;
87
+ }
88
+
89
+ if(!this.modal.dataset.disableClick || this.modal.dataset.disableClick === "false") {
90
+ clickHandler = closeModalOnClick.bind(this);
91
+ this.modal.addEventListener('click', clickHandler, { once: true });
92
+ }
93
+ },
94
+ dismiss: function(e, confirmed) {
95
+ var _this = this;
96
+
97
+ if(e && e.preventDefault) {
98
+ e.preventDefault();
99
+ e.stopPropagation();
100
+ }
101
+
102
+ enableScroll();
103
+
104
+ if(_this.modal){
105
+ _this.modal.classList.remove(_class.visible);
106
+ _this.modal.classList.add(_class.out);
107
+ }
108
+
109
+ if(_this._callback) {
110
+ _this._callback(confirmed);
111
+ }
112
+
113
+ removeModal(_this);
114
+ }
115
+ }
116
+
117
+ return {
118
+ create: create,
119
+ init: attachModalHandlers
120
+ }
121
+
122
+ /**
123
+ * @public
124
+ *
125
+ * @description Attach a click listener to each modals trigger on the screen, which will open the modal
126
+ */
127
+ function attachModalHandlers() {
128
+ if(!body) {
129
+ body = document.querySelector('body');
130
+ }
131
+
132
+ var triggers = document.querySelectorAll('.' + _class.trigger);
133
+
134
+ if(triggers.length > 0) {
135
+ triggers.forEach(attachTriggerHandler);
136
+ }
137
+
138
+ //Not the recommended way to use modals
139
+ var modals = document.querySelectorAll('.' + _class.modal);
140
+
141
+ if(modals.length > 0) {
142
+ modals.forEach(attachModalHandler);
143
+ }
144
+
145
+ function attachModalHandler(modal) {
146
+ if(Volta._hasClass(modal, _class.auto)) {
147
+ var trigger = document.querySelector('#' + modal.dataset.trigger);
148
+ trigger.addEventListener('click', function() {
149
+ create(modal).open();
150
+ });
151
+ }
152
+ }
153
+
154
+ function attachTriggerHandler(trigger) {
155
+ if(trigger.dataset.modal) {
156
+ var modal = document.querySelector('#' + trigger.dataset.modal);
157
+
158
+ if(!modal) {
159
+ console.warn('Volta: modal ' + trigger.dataset.modal + ' cannot be found');
160
+ }
161
+
162
+ trigger.addEventListener('click', function() {
163
+ create(modal).open();
164
+ });
165
+ }
166
+ }
167
+ }
168
+
169
+ /**
170
+ * @private
171
+ *
172
+ * @description Close the modal, triggered by cancel button, passes false to callback function
173
+ * @param {event} e
174
+ */
175
+ function cancelModal(e) {
176
+ return this.dismiss(e, false);
177
+ }
178
+
179
+ /**
180
+ * @private
181
+ *
182
+ * @description Close the modal, triggered by confirm button, passes true to callback function
183
+ * @param {event} e
184
+ */
185
+ function confirmModal(e) {
186
+ return this.dismiss(e, true);
187
+ }
188
+
189
+ /**
190
+ * @private
191
+ *
192
+ * @description Close the modal, triggered by 'x' button, passes false to callback function
193
+ * @param {event} e
194
+ */
195
+ function dismissModal(e) {
196
+ return this.dismiss(e, false);
197
+ }
198
+
199
+ /** @private
200
+ *
201
+ * @description Close the modal, triggered by 'esc' key, passes false to callback function
202
+ * @param {event} e
203
+ */
204
+ function closeModalOnEscape(e){
205
+ if(e && e.keyCode === 27) {
206
+ this.dismiss(e, false);
207
+ } else {
208
+ body.addEventListener('click', escHandler, { once: true });
209
+ }
210
+ }
211
+
212
+
213
+ /** @private
214
+ *
215
+ * @description Close the modal, triggered by 'body click, passes false to callback function
216
+ * @param {event} e
217
+ */
218
+ function closeModalOnClick(e){
219
+ if(!Volta._hasClass(e.target, _class.trigger)
220
+ && !Volta._closest(e.target, '.' + _class.trigger, '.' + _class.trigger)
221
+ && !Volta._closest(e.target, '.' + _class.panel, '.' + _class.panel)) {
222
+ this.dismiss(e, false);
223
+ } else if(this.modal) {
224
+ this.modal.addEventListener('click', clickHandler, { once: true });
225
+ }
226
+ }
227
+
228
+ /**
229
+ * @public
230
+ *
231
+ * @description Create the modal object
232
+ * @param {HTMLElement|string} elementOrId Reference to the modal element or the id
233
+ *. @return {Object} A modal object
234
+ */
235
+ function create(elementOrId) {
236
+ if(!body) {
237
+ body = document.querySelector('body');
238
+ }
239
+ var modal = Object.create(Modal.prototype, {})
240
+ modal.init(elementOrId);
241
+ return modal;
242
+ }
243
+
244
+ /**
245
+ * Private functions to disable body scroll when modal is open
246
+ */
247
+ function disableScroll() {
248
+ body.classList.add(_class.bodyModalOpen);
249
+ body.addEventListener('touchmove', preventScroll);
250
+ body.querySelector('main').addEventListener('touchmove', preventScroll);
251
+ body.querySelector('.' + _class.content).addEventListener('touchmove', allowScroll);
252
+ }
253
+
254
+ function enableScroll() {
255
+ body.classList.remove(_class.bodyModalOpen);
256
+ body.removeEventListener('touchmove', preventScroll);
257
+ body.querySelector('main').removeEventListener('touchmove', preventScroll);
258
+ var modalContent = body.querySelector('.' + _class.content);
259
+ if(modalContent) modalContent.removeEventListener('touchmove', allowScroll);
260
+ }
261
+
262
+ function allowScroll(e) {
263
+ e.stopPropagation();
264
+ }
265
+
266
+ function preventScroll(e) {
267
+ e.preventDefault();
268
+ }
269
+
270
+ /**
271
+ * @private
272
+ *
273
+ * @description Remove the modal after dismiss, makes sure to delete the modal properties so it can be garbage collected, and removes event listeners
274
+ * @param {HTMLElement|string} elementOrId Reference to the modal element or the id
275
+ */
276
+ function removeModal(modal) {
277
+ delete modal.modal;
278
+
279
+ if(modal.dismissBtn) {
280
+ modal.dismissBtn.removeEventListener('click', dismissModalHandler);
281
+ }
282
+
283
+ if(modal.cancelBtn) {
284
+ modal.cancelBtn.removeEventListener('click', cancelModalHandler);
285
+ }
286
+
287
+ if(modal.confirmBtn) {
288
+ modal.confirmBtn.removeEventListener('click', confirmModalHandler);
289
+ }
290
+
291
+ if(clickHandler) {
292
+ body.removeEventListener('click', clickHandler);
293
+ }
294
+
295
+ if(escHandler) {
296
+ body.removeEventListener('keyup', escHandler);
297
+ escAttached = false;
298
+ }
299
+ }
300
+ }();