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.
- checksums.yaml +7 -0
- data/.env.example +1 -0
- data/.gitignore +5 -0
- data/CHANGELOG.md +2 -0
- data/CONTRIBUTING.md +46 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +183 -0
- data/LICENSE.txt +21 -0
- data/README.md +73 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/nexmo-oas-renderer +5 -0
- data/lib/nexmo/oas/engine.rb +9 -0
- data/lib/nexmo/oas/renderer.rb +13 -0
- data/lib/nexmo/oas/renderer/app.rb +116 -0
- data/lib/nexmo/oas/renderer/config.ru +7 -0
- data/lib/nexmo/oas/renderer/config/code_languages.yml +138 -0
- data/lib/nexmo/oas/renderer/config/dynamic_content.yml +1 -0
- data/lib/nexmo/oas/renderer/config/redirects.yml +8 -0
- data/lib/nexmo/oas/renderer/constraints/open_api.rb +76 -0
- data/lib/nexmo/oas/renderer/constraints/redirector.rb +17 -0
- data/lib/nexmo/oas/renderer/decorators/response_parser_decorator.rb +55 -0
- data/lib/nexmo/oas/renderer/filters/anchor.rb +17 -0
- data/lib/nexmo/oas/renderer/filters/audio.rb +21 -0
- data/lib/nexmo/oas/renderer/filters/block_escape.rb +24 -0
- data/lib/nexmo/oas/renderer/filters/break.rb +13 -0
- data/lib/nexmo/oas/renderer/filters/code.rb +64 -0
- data/lib/nexmo/oas/renderer/filters/code_snippet.rb +194 -0
- data/lib/nexmo/oas/renderer/filters/code_snippet_list.rb +33 -0
- data/lib/nexmo/oas/renderer/filters/code_snippets.rb +158 -0
- data/lib/nexmo/oas/renderer/filters/collapsible.rb +27 -0
- data/lib/nexmo/oas/renderer/filters/columns.rb +50 -0
- data/lib/nexmo/oas/renderer/filters/concept_list.rb +33 -0
- data/lib/nexmo/oas/renderer/filters/dynamic_content.rb +30 -0
- data/lib/nexmo/oas/renderer/filters/external_link.rb +32 -0
- data/lib/nexmo/oas/renderer/filters/frontmatter.rb +14 -0
- data/lib/nexmo/oas/renderer/filters/heading.rb +61 -0
- data/lib/nexmo/oas/renderer/filters/icon.rb +22 -0
- data/lib/nexmo/oas/renderer/filters/indent.rb +20 -0
- data/lib/nexmo/oas/renderer/filters/inline_escape.rb +17 -0
- data/lib/nexmo/oas/renderer/filters/js_sequence_diagram.rb +21 -0
- data/lib/nexmo/oas/renderer/filters/label.rb +32 -0
- data/lib/nexmo/oas/renderer/filters/language.rb +15 -0
- data/lib/nexmo/oas/renderer/filters/markdown.rb +85 -0
- data/lib/nexmo/oas/renderer/filters/modal.rb +41 -0
- data/lib/nexmo/oas/renderer/filters/partial.rb +28 -0
- data/lib/nexmo/oas/renderer/filters/php_inliner.rb +15 -0
- data/lib/nexmo/oas/renderer/filters/screenshot.rb +26 -0
- data/lib/nexmo/oas/renderer/filters/tab.rb +250 -0
- data/lib/nexmo/oas/renderer/filters/techio.rb +24 -0
- data/lib/nexmo/oas/renderer/filters/tooltip.rb +22 -0
- data/lib/nexmo/oas/renderer/filters/tutorial_link.rb +27 -0
- data/lib/nexmo/oas/renderer/filters/tutorials.rb +28 -0
- data/lib/nexmo/oas/renderer/filters/unfreeze.rb +20 -0
- data/lib/nexmo/oas/renderer/filters/user_personalization.rb +43 -0
- data/lib/nexmo/oas/renderer/helpers/navigation.rb +66 -0
- data/lib/nexmo/oas/renderer/helpers/render.rb +24 -0
- data/lib/nexmo/oas/renderer/helpers/summary.rb +30 -0
- data/lib/nexmo/oas/renderer/helpers/url.rb +17 -0
- data/lib/nexmo/oas/renderer/lib/core_ext/string.rb +14 -0
- data/lib/nexmo/oas/renderer/lib/redcarpet.rb +14 -0
- data/lib/nexmo/oas/renderer/models/code_snippet.rb +75 -0
- data/lib/nexmo/oas/renderer/models/tutorial.rb +83 -0
- data/lib/nexmo/oas/renderer/pipelines/markdown_pipeline.rb +52 -0
- data/lib/nexmo/oas/renderer/presenters/api_specification.rb +42 -0
- data/lib/nexmo/oas/renderer/presenters/groups.rb +35 -0
- data/lib/nexmo/oas/renderer/presenters/navigation.rb +24 -0
- data/lib/nexmo/oas/renderer/presenters/open_api_specification.rb +68 -0
- data/lib/nexmo/oas/renderer/presenters/versions.rb +40 -0
- data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Black.woff +0 -0
- data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Black.woff2 +0 -0
- data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Heavy.woff +0 -0
- data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Heavy.woff2 +0 -0
- data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Regular.woff +0 -0
- data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Regular.woff2 +0 -0
- data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Semibold.woff +0 -0
- data/lib/nexmo/oas/renderer/public/assets/fonts/Lato-Semibold.woff2 +0 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/android.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/curl.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/dotnet.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/ios.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/java.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/javascript.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/node.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/php.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/python.svg +11 -0
- data/lib/nexmo/oas/renderer/public/assets/images/brands/ruby.svg +1 -0
- data/lib/nexmo/oas/renderer/public/assets/images/lost.svg +37 -0
- data/lib/nexmo/oas/renderer/public/assets/javascripts/components/format.js +42 -0
- data/lib/nexmo/oas/renderer/public/assets/javascripts/volta.accordion.js +249 -0
- data/lib/nexmo/oas/renderer/public/assets/javascripts/volta.core.js +230 -0
- data/lib/nexmo/oas/renderer/public/assets/javascripts/volta.modal.js +300 -0
- data/lib/nexmo/oas/renderer/public/assets/javascripts/volta.tabs.js +139 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/api.css +95 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/buttons.css +80 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/core.css +79 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/mediaqueries.css +2 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/mediaqueries.css.map +7 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/navigation.css +79 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/nexmo.css +68 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/api.scss +147 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/core.scss +133 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/mediaqueries.scss +48 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/navigation.scss +106 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/nexmo.scss +61 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/style.scss +10 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/syntax.scss +63 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/typography.scss +248 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/variables.scss +91 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/sass/volta-templates.scss +119 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/style.css +2 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/style.css.map +7 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/syntax.css +79 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/typography.css +86 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/variables.css +2 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/variables.css.map +7 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/volta-templates.css +2 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/volta-templates.css.map +7 -0
- data/lib/nexmo/oas/renderer/public/assets/stylesheets/volta.min.css +1 -0
- data/lib/nexmo/oas/renderer/public/assets/symbol/volta-icons.svg +1 -0
- data/lib/nexmo/oas/renderer/public/favicon.ico +0 -0
- data/lib/nexmo/oas/renderer/services/code_language_api.rb +98 -0
- data/lib/nexmo/oas/renderer/services/oas_parser.rb +21 -0
- data/lib/nexmo/oas/renderer/services/open_api_definition_resolver.rb +33 -0
- data/lib/nexmo/oas/renderer/version.rb +7 -0
- data/lib/nexmo/oas/renderer/views/api/show.erb +1 -0
- data/lib/nexmo/oas/renderer/views/code_snippets/_application_messages_dispatch.html.erb +9 -0
- data/lib/nexmo/oas/renderer/views/code_snippets/_application_rtc.html.erb +41 -0
- data/lib/nexmo/oas/renderer/views/code_snippets/_application_voice.html.erb +24 -0
- data/lib/nexmo/oas/renderer/views/code_snippets/_code_only.html.erb +6 -0
- data/lib/nexmo/oas/renderer/views/code_snippets/_configure_client.html.erb +20 -0
- data/lib/nexmo/oas/renderer/views/code_snippets/_dependencies.html.erb +11 -0
- data/lib/nexmo/oas/renderer/views/code_snippets/_write_code.html.erb +13 -0
- data/lib/nexmo/oas/renderer/views/code_snippets/list/plain.html.erb +10 -0
- data/lib/nexmo/oas/renderer/views/concepts/list/plain.html.erb +5 -0
- data/lib/nexmo/oas/renderer/views/layouts/_head.erb +4 -0
- data/lib/nexmo/oas/renderer/views/layouts/_javascripts.erb +9 -0
- data/lib/nexmo/oas/renderer/views/layouts/api.erb +23 -0
- data/lib/nexmo/oas/renderer/views/layouts/open_api.erb +10 -0
- data/lib/nexmo/oas/renderer/views/open_api/_callback.erb +5 -0
- data/lib/nexmo/oas/renderer/views/open_api/_callback_endpoint.erb +48 -0
- data/lib/nexmo/oas/renderer/views/open_api/_code_examples.erb +16 -0
- data/lib/nexmo/oas/renderer/views/open_api/_endpoint.erb +156 -0
- data/lib/nexmo/oas/renderer/views/open_api/_model.erb +38 -0
- data/lib/nexmo/oas/renderer/views/open_api/_navigation.erb +80 -0
- data/lib/nexmo/oas/renderer/views/open_api/_parameter_groups.erb +50 -0
- data/lib/nexmo/oas/renderer/views/open_api/_parameters.erb +165 -0
- data/lib/nexmo/oas/renderer/views/open_api/_response_description_parameters.erb +61 -0
- data/lib/nexmo/oas/renderer/views/open_api/_response_descriptions.erb +41 -0
- data/lib/nexmo/oas/renderer/views/open_api/show.erb +104 -0
- data/lib/nexmo/oas/renderer/views/static/404.erb +6 -0
- data/lib/nexmo/oas/renderer/views/tutorials/_index.html.erb +32 -0
- data/lib/nexmo/oas/renderer/views/tutorials/index.html.erb +7 -0
- data/lib/nexmo/oas/renderer/views/tutorials/list/plain.html.erb +5 -0
- data/lib/nexmo/oas/renderer/views/tutorials/show.html.erb +8 -0
- data/nexmo-oas-renderer.gemspec +49 -0
- 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
|
+
}();
|