camaleon_cms 2.8.2 → 2.9.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.
Potentially problematic release.
This version of camaleon_cms might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/app/assets/javascripts/camaleon_cms/admin/_actions.js +3 -2
- data/app/assets/javascripts/camaleon_cms/admin/_libraries.js +0 -1
- data/app/assets/javascripts/camaleon_cms/admin/admin-manifest.js +1 -2
- data/app/assets/javascripts/camaleon_cms/admin/introjs/intro.min.js +11 -0
- data/app/assets/javascripts/camaleon_cms/admin/introjs/intro.min.js.map +1 -0
- data/app/assets/javascripts/camaleon_cms/admin/jquery.validate.js +5 -5
- data/app/assets/javascripts/camaleon_cms/admin/jquery_validate/messages_ar.js +52 -0
- data/app/assets/javascripts/camaleon_cms/admin/jquery_validate/messages_de.js +70 -0
- data/app/assets/javascripts/camaleon_cms/admin/jquery_validate/{es.js → messages_es.js} +9 -10
- data/app/assets/javascripts/camaleon_cms/admin/jquery_validate/{fr.js → messages_fr.js} +7 -3
- data/app/assets/javascripts/camaleon_cms/admin/jquery_validate/messages_it.js +27 -0
- data/app/assets/javascripts/camaleon_cms/admin/jquery_validate/{nl.js → messages_nl.js} +1 -0
- data/app/assets/javascripts/camaleon_cms/admin/jquery_validate/{pt-BR.js → messages_pt-BR.js} +24 -19
- data/app/assets/javascripts/camaleon_cms/admin/jquery_validate/{ru.js → messages_ru.js} +6 -2
- data/app/assets/javascripts/camaleon_cms/admin/jquery_validate/{zh-CN.js → messages_zh-CN.js} +9 -8
- data/app/assets/javascripts/camaleon_cms/admin/jquery_validate/methods_de.js +12 -0
- data/app/assets/javascripts/camaleon_cms/admin/jquery_validate/methods_nl.js +12 -0
- data/app/assets/javascripts/camaleon_cms/admin/jquery_validate/methods_pt.js +9 -0
- data/app/assets/stylesheets/camaleon_cms/admin/_custom_admin.css.scss +19 -7
- data/app/assets/stylesheets/camaleon_cms/admin/admin-manifest.css +1 -1
- data/app/assets/stylesheets/camaleon_cms/admin/introjs/introjs.min.css +2 -0
- data/app/assets/stylesheets/camaleon_cms/admin/introjs/introjs.min.css.map +1 -0
- data/app/controllers/camaleon_cms/admin/media_controller.rb +2 -1
- data/app/controllers/camaleon_cms/admin/sessions_controller.rb +1 -1
- data/app/helpers/camaleon_cms/uploader_helper.rb +11 -4
- data/app/uploaders/camaleon_cms_aws_uploader.rb +10 -1
- data/app/uploaders/camaleon_cms_local_uploader.rb +3 -1
- data/app/uploaders/camaleon_cms_uploader.rb +2 -4
- data/app/views/camaleon_cms/admin/settings/_file_system_settings.html.erb +5 -5
- data/app/views/layouts/camaleon_cms/admin.html.erb +7 -1
- data/lib/camaleon_cms/version.rb +1 -1
- data/lib/plugin_routes.rb +2 -0
- metadata +20 -15
- data/app/assets/javascripts/camaleon_cms/admin/_underscore.js +0 -1536
- data/app/assets/javascripts/camaleon_cms/admin/introjs/_intro.min.js +0 -1317
- data/app/assets/javascripts/camaleon_cms/admin/jquery_validate/de.js +0 -20
- data/app/assets/javascripts/camaleon_cms/admin/jquery_validate/it.js +0 -23
- data/app/assets/stylesheets/camaleon_cms/admin/introjs/_introjs.min.css +0 -1
- /data/app/assets/javascripts/camaleon_cms/admin/jquery_validate/{uk.js → messages_uk.js} +0 -0
@@ -1,1317 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Intro.js v1.1.1
|
3
|
-
* https://github.com/usablica/intro.js
|
4
|
-
* MIT licensed
|
5
|
-
*
|
6
|
-
* Copyright (C) 2013 usabli.ca - A weekend project by Afshin Mehrabani (@afshinmeh)
|
7
|
-
*/
|
8
|
-
|
9
|
-
(function (root, factory) {
|
10
|
-
if (typeof exports === 'object') {
|
11
|
-
// CommonJS
|
12
|
-
factory(exports);
|
13
|
-
} else if (typeof define === 'function' && define.amd) {
|
14
|
-
// AMD. Register as an anonymous module.
|
15
|
-
define(['exports'], factory);
|
16
|
-
} else {
|
17
|
-
// Browser globals
|
18
|
-
factory(root);
|
19
|
-
}
|
20
|
-
} (this, function (exports) {
|
21
|
-
//Default config/variables
|
22
|
-
var VERSION = '1.1.1';
|
23
|
-
|
24
|
-
/**
|
25
|
-
* IntroJs main class
|
26
|
-
*
|
27
|
-
* @class IntroJs
|
28
|
-
*/
|
29
|
-
function IntroJs(obj) {
|
30
|
-
this._targetElement = obj;
|
31
|
-
|
32
|
-
this._options = {
|
33
|
-
/* Next button label in tooltip box */
|
34
|
-
nextLabel: 'Next →',
|
35
|
-
/* Previous button label in tooltip box */
|
36
|
-
prevLabel: '← Back',
|
37
|
-
/* Skip button label in tooltip box */
|
38
|
-
skipLabel: 'Skip',
|
39
|
-
/* Done button label in tooltip box */
|
40
|
-
doneLabel: 'Done',
|
41
|
-
/* Default tooltip box position */
|
42
|
-
tooltipPosition: 'bottom',
|
43
|
-
/* Next CSS class for tooltip boxes */
|
44
|
-
tooltipClass: '',
|
45
|
-
/* CSS class that is added to the helperLayer */
|
46
|
-
highlightClass: '',
|
47
|
-
/* Close introduction when pressing Escape button? */
|
48
|
-
exitOnEsc: true,
|
49
|
-
/* Close introduction when clicking on overlay layer? */
|
50
|
-
exitOnOverlayClick: true,
|
51
|
-
/* Show step numbers in introduction? */
|
52
|
-
showStepNumbers: true,
|
53
|
-
/* Let user use keyboard to navigate the tour? */
|
54
|
-
keyboardNavigation: true,
|
55
|
-
/* Show tour control buttons? */
|
56
|
-
showButtons: true,
|
57
|
-
/* Show tour bullets? */
|
58
|
-
showBullets: true,
|
59
|
-
/* Show tour progress? */
|
60
|
-
showProgress: false,
|
61
|
-
/* Scroll to highlighted element? */
|
62
|
-
scrollToElement: true,
|
63
|
-
/* Set the overlay opacity */
|
64
|
-
overlayOpacity: 0.8,
|
65
|
-
/* Precedence of positions, when auto is enabled */
|
66
|
-
positionPrecedence: ["bottom", "top", "right", "left"],
|
67
|
-
/* Disable an interaction with element? */
|
68
|
-
disableInteraction: false
|
69
|
-
};
|
70
|
-
}
|
71
|
-
|
72
|
-
/**
|
73
|
-
* Initiate a new introduction/guide from an element in the page
|
74
|
-
*
|
75
|
-
* @api private
|
76
|
-
* @method _introForElement
|
77
|
-
* @param {Object} targetElm
|
78
|
-
* @returns {Boolean} Success or not?
|
79
|
-
*/
|
80
|
-
function _introForElement(targetElm) {
|
81
|
-
var introItems = [],
|
82
|
-
self = this;
|
83
|
-
|
84
|
-
if (this._options.steps) {
|
85
|
-
//use steps passed programmatically
|
86
|
-
for (var i = 0, stepsLength = this._options.steps.length; i < stepsLength; i++) {
|
87
|
-
var currentItem = _cloneObject(this._options.steps[i]);
|
88
|
-
//set the step
|
89
|
-
currentItem.step = introItems.length + 1;
|
90
|
-
//use querySelector function only when developer used CSS selector
|
91
|
-
if (typeof(currentItem.element) === 'string') {
|
92
|
-
//grab the element with given selector from the page
|
93
|
-
currentItem.element = document.querySelector(currentItem.element);
|
94
|
-
}
|
95
|
-
|
96
|
-
//intro without element
|
97
|
-
if (typeof(currentItem.element) === 'undefined' || currentItem.element == null) {
|
98
|
-
var floatingElementQuery = document.querySelector(".introjsFloatingElement");
|
99
|
-
|
100
|
-
if (floatingElementQuery == null) {
|
101
|
-
floatingElementQuery = document.createElement('div');
|
102
|
-
floatingElementQuery.className = 'introjsFloatingElement';
|
103
|
-
|
104
|
-
document.body.appendChild(floatingElementQuery);
|
105
|
-
}
|
106
|
-
|
107
|
-
currentItem.element = floatingElementQuery;
|
108
|
-
currentItem.position = 'floating';
|
109
|
-
}
|
110
|
-
|
111
|
-
if (currentItem.element != null) {
|
112
|
-
introItems.push(currentItem);
|
113
|
-
}
|
114
|
-
}
|
115
|
-
|
116
|
-
} else {
|
117
|
-
//use steps from data-* annotations
|
118
|
-
var allIntroSteps = targetElm.querySelectorAll('*[data-intro]');
|
119
|
-
//if there's no element to intro
|
120
|
-
if (allIntroSteps.length < 1) {
|
121
|
-
return false;
|
122
|
-
}
|
123
|
-
|
124
|
-
//first add intro items with data-step
|
125
|
-
for (var i = 0, elmsLength = allIntroSteps.length; i < elmsLength; i++) {
|
126
|
-
var currentElement = allIntroSteps[i];
|
127
|
-
var step = parseInt(currentElement.getAttribute('data-step'), 10);
|
128
|
-
|
129
|
-
if (step > 0) {
|
130
|
-
introItems[step - 1] = {
|
131
|
-
element: currentElement,
|
132
|
-
intro: currentElement.getAttribute('data-intro'),
|
133
|
-
step: parseInt(currentElement.getAttribute('data-step'), 10),
|
134
|
-
tooltipClass: currentElement.getAttribute('data-tooltipClass'),
|
135
|
-
highlightClass: currentElement.getAttribute('data-highlightClass'),
|
136
|
-
position: currentElement.getAttribute('data-position') || this._options.tooltipPosition
|
137
|
-
};
|
138
|
-
}
|
139
|
-
}
|
140
|
-
|
141
|
-
//next add intro items without data-step
|
142
|
-
//todo: we need a cleanup here, two loops are redundant
|
143
|
-
var nextStep = 0;
|
144
|
-
for (var i = 0, elmsLength = allIntroSteps.length; i < elmsLength; i++) {
|
145
|
-
var currentElement = allIntroSteps[i];
|
146
|
-
|
147
|
-
if (currentElement.getAttribute('data-step') == null) {
|
148
|
-
|
149
|
-
while (true) {
|
150
|
-
if (typeof introItems[nextStep] == 'undefined') {
|
151
|
-
break;
|
152
|
-
} else {
|
153
|
-
nextStep++;
|
154
|
-
}
|
155
|
-
}
|
156
|
-
|
157
|
-
introItems[nextStep] = {
|
158
|
-
element: currentElement,
|
159
|
-
intro: currentElement.getAttribute('data-intro'),
|
160
|
-
step: nextStep + 1,
|
161
|
-
tooltipClass: currentElement.getAttribute('data-tooltipClass'),
|
162
|
-
highlightClass: currentElement.getAttribute('data-highlightClass'),
|
163
|
-
position: currentElement.getAttribute('data-position') || this._options.tooltipPosition
|
164
|
-
};
|
165
|
-
}
|
166
|
-
}
|
167
|
-
}
|
168
|
-
|
169
|
-
//removing undefined/null elements
|
170
|
-
var tempIntroItems = [];
|
171
|
-
for (var z = 0; z < introItems.length; z++) {
|
172
|
-
introItems[z] && tempIntroItems.push(introItems[z]); // copy non-empty values to the end of the array
|
173
|
-
}
|
174
|
-
|
175
|
-
introItems = tempIntroItems;
|
176
|
-
|
177
|
-
//Ok, sort all items with given steps
|
178
|
-
introItems.sort(function (a, b) {
|
179
|
-
return a.step - b.step;
|
180
|
-
});
|
181
|
-
|
182
|
-
//set it to the introJs object
|
183
|
-
self._introItems = introItems;
|
184
|
-
|
185
|
-
//add overlay layer to the page
|
186
|
-
if(_addOverlayLayer.call(self, targetElm)) {
|
187
|
-
//then, start the show
|
188
|
-
_nextStep.call(self);
|
189
|
-
|
190
|
-
var skipButton = targetElm.querySelector('.introjs-skipbutton'),
|
191
|
-
nextStepButton = targetElm.querySelector('.introjs-nextbutton');
|
192
|
-
|
193
|
-
self._onKeyDown = function(e) {
|
194
|
-
if (e.keyCode === 27 && self._options.exitOnEsc == true) {
|
195
|
-
//escape key pressed, exit the intro
|
196
|
-
//check if exit callback is defined
|
197
|
-
if (self._introExitCallback != undefined) {
|
198
|
-
self._introExitCallback.call(self);
|
199
|
-
}
|
200
|
-
_exitIntro.call(self, targetElm);
|
201
|
-
} else if(e.keyCode === 37) {
|
202
|
-
//left arrow
|
203
|
-
_previousStep.call(self);
|
204
|
-
} else if (e.keyCode === 39) {
|
205
|
-
//right arrow
|
206
|
-
_nextStep.call(self);
|
207
|
-
} else if (e.keyCode === 13) {
|
208
|
-
//srcElement === ie
|
209
|
-
var target = e.target || e.srcElement;
|
210
|
-
if (target && target.className.indexOf('introjs-prevbutton') > 0) {
|
211
|
-
//user hit enter while focusing on previous button
|
212
|
-
_previousStep.call(self);
|
213
|
-
} else if (target && target.className.indexOf('introjs-skipbutton') > 0) {
|
214
|
-
//user hit enter while focusing on skip button
|
215
|
-
if (self._introItems.length - 1 == self._currentStep && typeof (self._introCompleteCallback) === 'function') {
|
216
|
-
self._introCompleteCallback.call(self);
|
217
|
-
}
|
218
|
-
//check if any callback is defined
|
219
|
-
if (self._introExitCallback != undefined) {
|
220
|
-
self._introExitCallback.call(self);
|
221
|
-
}
|
222
|
-
_exitIntro.call(self, targetElm);
|
223
|
-
} else {
|
224
|
-
//default behavior for responding to enter
|
225
|
-
_nextStep.call(self);
|
226
|
-
}
|
227
|
-
|
228
|
-
//prevent default behaviour on hitting Enter, to prevent steps being skipped in some browsers
|
229
|
-
if(e.preventDefault) {
|
230
|
-
e.preventDefault();
|
231
|
-
} else {
|
232
|
-
e.returnValue = false;
|
233
|
-
}
|
234
|
-
}
|
235
|
-
};
|
236
|
-
|
237
|
-
self._onResize = function(e) {
|
238
|
-
_setHelperLayerPosition.call(self, document.querySelector('.introjs-helperLayer'));
|
239
|
-
_setHelperLayerPosition.call(self, document.querySelector('.introjs-tooltipReferenceLayer'));
|
240
|
-
};
|
241
|
-
|
242
|
-
if (window.addEventListener) {
|
243
|
-
if (this._options.keyboardNavigation) {
|
244
|
-
window.addEventListener('keydown', self._onKeyDown, true);
|
245
|
-
}
|
246
|
-
//for window resize
|
247
|
-
window.addEventListener('resize', self._onResize, true);
|
248
|
-
} else if (document.attachEvent) { //IE
|
249
|
-
if (this._options.keyboardNavigation) {
|
250
|
-
document.attachEvent('onkeydown', self._onKeyDown);
|
251
|
-
}
|
252
|
-
//for window resize
|
253
|
-
document.attachEvent('onresize', self._onResize);
|
254
|
-
}
|
255
|
-
}
|
256
|
-
return false;
|
257
|
-
}
|
258
|
-
|
259
|
-
/*
|
260
|
-
* makes a copy of the object
|
261
|
-
* @api private
|
262
|
-
* @method _cloneObject
|
263
|
-
*/
|
264
|
-
function _cloneObject(object) {
|
265
|
-
if (object == null || typeof (object) != 'object' || typeof (object.nodeType) != 'undefined') {
|
266
|
-
return object;
|
267
|
-
}
|
268
|
-
var temp = {};
|
269
|
-
for (var key in object) {
|
270
|
-
if (typeof (jQuery) != 'undefined' && object[key] instanceof jQuery) {
|
271
|
-
temp[key] = object[key];
|
272
|
-
} else {
|
273
|
-
temp[key] = _cloneObject(object[key]);
|
274
|
-
}
|
275
|
-
}
|
276
|
-
return temp;
|
277
|
-
}
|
278
|
-
/**
|
279
|
-
* Go to specific step of introduction
|
280
|
-
*
|
281
|
-
* @api private
|
282
|
-
* @method _goToStep
|
283
|
-
*/
|
284
|
-
function _goToStep(step) {
|
285
|
-
//because steps starts with zero
|
286
|
-
this._currentStep = step - 2;
|
287
|
-
if (typeof (this._introItems) !== 'undefined') {
|
288
|
-
_nextStep.call(this);
|
289
|
-
}
|
290
|
-
}
|
291
|
-
|
292
|
-
/**
|
293
|
-
* Go to next step on intro
|
294
|
-
*
|
295
|
-
* @api private
|
296
|
-
* @method _nextStep
|
297
|
-
*/
|
298
|
-
function _nextStep() {
|
299
|
-
this._direction = 'forward';
|
300
|
-
|
301
|
-
if (typeof (this._currentStep) === 'undefined') {
|
302
|
-
this._currentStep = 0;
|
303
|
-
} else {
|
304
|
-
++this._currentStep;
|
305
|
-
}
|
306
|
-
|
307
|
-
if ((this._introItems.length) <= this._currentStep) {
|
308
|
-
//end of the intro
|
309
|
-
//check if any callback is defined
|
310
|
-
if (typeof (this._introCompleteCallback) === 'function') {
|
311
|
-
this._introCompleteCallback.call(this);
|
312
|
-
}
|
313
|
-
_exitIntro.call(this, this._targetElement);
|
314
|
-
return;
|
315
|
-
}
|
316
|
-
|
317
|
-
var nextStep = this._introItems[this._currentStep];
|
318
|
-
if (typeof (this._introBeforeChangeCallback) !== 'undefined') {
|
319
|
-
this._introBeforeChangeCallback.call(this, nextStep.element);
|
320
|
-
}
|
321
|
-
|
322
|
-
//_showElement.call(this, nextStep);
|
323
|
-
var w = $(nextStep.element).attr("data-wait");
|
324
|
-
var thiss = this;
|
325
|
-
var _f = function(){ _showElement.call(thiss, nextStep); };
|
326
|
-
if(w) setTimeout(_f, w); else _f();
|
327
|
-
}
|
328
|
-
|
329
|
-
/**
|
330
|
-
* Go to previous step on intro
|
331
|
-
*
|
332
|
-
* @api private
|
333
|
-
* @method _nextStep
|
334
|
-
*/
|
335
|
-
function _previousStep() {
|
336
|
-
this._direction = 'backward';
|
337
|
-
|
338
|
-
if (this._currentStep === 0) {
|
339
|
-
return false;
|
340
|
-
}
|
341
|
-
|
342
|
-
var nextStep = this._introItems[--this._currentStep];
|
343
|
-
if (typeof (this._introBeforeChangeCallback) !== 'undefined') {
|
344
|
-
this._introBeforeChangeCallback.call(this, nextStep.element);
|
345
|
-
}
|
346
|
-
|
347
|
-
//_showElement.call(this, nextStep);
|
348
|
-
var w = $(nextStep.element).attr("data-wait");
|
349
|
-
var thiss = this;
|
350
|
-
var _f = function(){ _showElement.call(thiss, nextStep); };
|
351
|
-
if(w) setTimeout(_f, w); else _f();
|
352
|
-
}
|
353
|
-
|
354
|
-
/**
|
355
|
-
* Exit from intro
|
356
|
-
*
|
357
|
-
* @api private
|
358
|
-
* @method _exitIntro
|
359
|
-
* @param {Object} targetElement
|
360
|
-
*/
|
361
|
-
function _exitIntro(targetElement) {
|
362
|
-
//remove overlay layer from the page
|
363
|
-
var overlayLayer = targetElement.querySelector('.introjs-overlay');
|
364
|
-
|
365
|
-
//return if intro already completed or skipped
|
366
|
-
if (overlayLayer == null) {
|
367
|
-
return;
|
368
|
-
}
|
369
|
-
|
370
|
-
//for fade-out animation
|
371
|
-
overlayLayer.style.opacity = 0;
|
372
|
-
setTimeout(function () {
|
373
|
-
if (overlayLayer.parentNode) {
|
374
|
-
overlayLayer.parentNode.removeChild(overlayLayer);
|
375
|
-
}
|
376
|
-
}, 500);
|
377
|
-
|
378
|
-
//remove all helper layers
|
379
|
-
var helperLayer = targetElement.querySelector('.introjs-helperLayer');
|
380
|
-
if (helperLayer) {
|
381
|
-
helperLayer.parentNode.removeChild(helperLayer);
|
382
|
-
}
|
383
|
-
|
384
|
-
var referenceLayer = targetElement.querySelector('.introjs-tooltipReferenceLayer');
|
385
|
-
if (referenceLayer) {
|
386
|
-
referenceLayer.parentNode.removeChild(referenceLayer);
|
387
|
-
}
|
388
|
-
//remove disableInteractionLayer
|
389
|
-
var disableInteractionLayer = targetElement.querySelector('.introjs-disableInteraction');
|
390
|
-
if (disableInteractionLayer) {
|
391
|
-
disableInteractionLayer.parentNode.removeChild(disableInteractionLayer);
|
392
|
-
}
|
393
|
-
|
394
|
-
//remove intro floating element
|
395
|
-
var floatingElement = document.querySelector('.introjsFloatingElement');
|
396
|
-
if (floatingElement) {
|
397
|
-
floatingElement.parentNode.removeChild(floatingElement);
|
398
|
-
}
|
399
|
-
|
400
|
-
//remove `introjs-showElement` class from the element
|
401
|
-
var showElement = document.querySelector('.introjs-showElement');
|
402
|
-
if (showElement) {
|
403
|
-
showElement.className = showElement.className.replace(/introjs-[a-zA-Z]+/g, '').replace(/^\s+|\s+$/g, ''); // This is a manual trim.
|
404
|
-
}
|
405
|
-
|
406
|
-
//remove `introjs-fixParent` class from the elements
|
407
|
-
var fixParents = document.querySelectorAll('.introjs-fixParent');
|
408
|
-
if (fixParents && fixParents.length > 0) {
|
409
|
-
for (var i = fixParents.length - 1; i >= 0; i--) {
|
410
|
-
fixParents[i].className = fixParents[i].className.replace(/introjs-fixParent/g, '').replace(/^\s+|\s+$/g, '');
|
411
|
-
}
|
412
|
-
}
|
413
|
-
|
414
|
-
//clean listeners
|
415
|
-
if (window.removeEventListener) {
|
416
|
-
window.removeEventListener('keydown', this._onKeyDown, true);
|
417
|
-
} else if (document.detachEvent) { //IE
|
418
|
-
document.detachEvent('onkeydown', this._onKeyDown);
|
419
|
-
}
|
420
|
-
|
421
|
-
//set the step to zero
|
422
|
-
this._currentStep = undefined;
|
423
|
-
}
|
424
|
-
|
425
|
-
/**
|
426
|
-
* Render tooltip box in the page
|
427
|
-
*
|
428
|
-
* @api private
|
429
|
-
* @method _placeTooltip
|
430
|
-
* @param {HTMLElement} targetElement
|
431
|
-
* @param {HTMLElement} tooltipLayer
|
432
|
-
* @param {HTMLElement} arrowLayer
|
433
|
-
* @param {HTMLElement} helperNumberLayer
|
434
|
-
*/
|
435
|
-
function _placeTooltip(targetElement, tooltipLayer, arrowLayer, helperNumberLayer) {
|
436
|
-
var tooltipCssClass = '',
|
437
|
-
currentStepObj,
|
438
|
-
tooltipOffset,
|
439
|
-
targetOffset,
|
440
|
-
windowSize,
|
441
|
-
currentTooltipPosition;
|
442
|
-
|
443
|
-
//reset the old style
|
444
|
-
tooltipLayer.style.top = null;
|
445
|
-
tooltipLayer.style.right = null;
|
446
|
-
tooltipLayer.style.bottom = null;
|
447
|
-
tooltipLayer.style.left = null;
|
448
|
-
tooltipLayer.style.marginLeft = null;
|
449
|
-
tooltipLayer.style.marginTop = null;
|
450
|
-
|
451
|
-
arrowLayer.style.display = 'inherit';
|
452
|
-
|
453
|
-
if (typeof(helperNumberLayer) != 'undefined' && helperNumberLayer != null) {
|
454
|
-
helperNumberLayer.style.top = null;
|
455
|
-
helperNumberLayer.style.left = null;
|
456
|
-
}
|
457
|
-
|
458
|
-
//prevent error when `this._currentStep` is undefined
|
459
|
-
if (!this._introItems[this._currentStep]) return;
|
460
|
-
|
461
|
-
//if we have a custom css class for each step
|
462
|
-
currentStepObj = this._introItems[this._currentStep];
|
463
|
-
if (typeof (currentStepObj.tooltipClass) === 'string') {
|
464
|
-
tooltipCssClass = currentStepObj.tooltipClass;
|
465
|
-
} else {
|
466
|
-
tooltipCssClass = this._options.tooltipClass;
|
467
|
-
}
|
468
|
-
|
469
|
-
tooltipLayer.className = ('introjs-tooltip ' + tooltipCssClass).replace(/^\s+|\s+$/g, '');
|
470
|
-
|
471
|
-
currentTooltipPosition = this._introItems[this._currentStep].position;
|
472
|
-
if ((currentTooltipPosition == "auto" || this._options.tooltipPosition == "auto")) {
|
473
|
-
if (currentTooltipPosition != "floating") { // Floating is always valid, no point in calculating
|
474
|
-
currentTooltipPosition = _determineAutoPosition.call(this, targetElement, tooltipLayer, currentTooltipPosition);
|
475
|
-
}
|
476
|
-
}
|
477
|
-
targetOffset = _getOffset(targetElement);
|
478
|
-
tooltipOffset = _getOffset(tooltipLayer);
|
479
|
-
windowSize = _getWinSize();
|
480
|
-
switch (currentTooltipPosition) {
|
481
|
-
case 'top':
|
482
|
-
arrowLayer.className = 'introjs-arrow bottom';
|
483
|
-
|
484
|
-
var tooltipLayerStyleLeft = 15;
|
485
|
-
_checkRight(targetOffset, tooltipLayerStyleLeft, tooltipOffset, windowSize, tooltipLayer);
|
486
|
-
tooltipLayer.style.bottom = (targetOffset.height + 20) + 'px';
|
487
|
-
break;
|
488
|
-
case 'right':
|
489
|
-
tooltipLayer.style.left = (targetOffset.width + 20) + 'px';
|
490
|
-
if (targetOffset.top + tooltipOffset.height > windowSize.height) {
|
491
|
-
// In this case, right would have fallen below the bottom of the screen.
|
492
|
-
// Modify so that the bottom of the tooltip connects with the target
|
493
|
-
arrowLayer.className = "introjs-arrow left-bottom";
|
494
|
-
tooltipLayer.style.top = "-" + (tooltipOffset.height - targetOffset.height - 20) + "px";
|
495
|
-
} else {
|
496
|
-
arrowLayer.className = 'introjs-arrow left';
|
497
|
-
}
|
498
|
-
break;
|
499
|
-
case 'left':
|
500
|
-
if (this._options.showStepNumbers == true) {
|
501
|
-
tooltipLayer.style.top = '15px';
|
502
|
-
}
|
503
|
-
|
504
|
-
if (targetOffset.top + tooltipOffset.height > windowSize.height) {
|
505
|
-
// In this case, left would have fallen below the bottom of the screen.
|
506
|
-
// Modify so that the bottom of the tooltip connects with the target
|
507
|
-
tooltipLayer.style.top = "-" + (tooltipOffset.height - targetOffset.height - 20) + "px";
|
508
|
-
arrowLayer.className = 'introjs-arrow right-bottom';
|
509
|
-
} else {
|
510
|
-
arrowLayer.className = 'introjs-arrow right';
|
511
|
-
}
|
512
|
-
tooltipLayer.style.right = (targetOffset.width + 20) + 'px';
|
513
|
-
|
514
|
-
break;
|
515
|
-
case 'floating':
|
516
|
-
arrowLayer.style.display = 'none';
|
517
|
-
|
518
|
-
//we have to adjust the top and left of layer manually for intro items without element
|
519
|
-
tooltipLayer.style.left = '50%';
|
520
|
-
tooltipLayer.style.top = '50%';
|
521
|
-
tooltipLayer.style.marginLeft = '-' + (tooltipOffset.width / 2) + 'px';
|
522
|
-
tooltipLayer.style.marginTop = '-' + (tooltipOffset.height / 2) + 'px';
|
523
|
-
|
524
|
-
if (typeof(helperNumberLayer) != 'undefined' && helperNumberLayer != null) {
|
525
|
-
helperNumberLayer.style.left = '-' + ((tooltipOffset.width / 2) + 18) + 'px';
|
526
|
-
helperNumberLayer.style.top = '-' + ((tooltipOffset.height / 2) + 18) + 'px';
|
527
|
-
}
|
528
|
-
|
529
|
-
break;
|
530
|
-
case 'bottom-right-aligned':
|
531
|
-
arrowLayer.className = 'introjs-arrow top-right';
|
532
|
-
|
533
|
-
var tooltipLayerStyleRight = 0;
|
534
|
-
_checkLeft(targetOffset, tooltipLayerStyleRight, tooltipOffset, tooltipLayer);
|
535
|
-
tooltipLayer.style.top = (targetOffset.height + 20) + 'px';
|
536
|
-
break;
|
537
|
-
|
538
|
-
case 'bottom-middle-aligned':
|
539
|
-
arrowLayer.className = 'introjs-arrow top-middle';
|
540
|
-
|
541
|
-
var tooltipLayerStyleLeftRight = targetOffset.width / 2 - tooltipOffset.width / 2;
|
542
|
-
if (_checkLeft(targetOffset, tooltipLayerStyleLeftRight, tooltipOffset, tooltipLayer)) {
|
543
|
-
tooltipLayer.style.right = null;
|
544
|
-
_checkRight(targetOffset, tooltipLayerStyleLeftRight, tooltipOffset, windowSize, tooltipLayer);
|
545
|
-
}
|
546
|
-
tooltipLayer.style.top = (targetOffset.height + 20) + 'px';
|
547
|
-
break;
|
548
|
-
|
549
|
-
case 'bottom-left-aligned':
|
550
|
-
// Bottom-left-aligned is the same as the default bottom
|
551
|
-
case 'bottom':
|
552
|
-
// Bottom going to follow the default behavior
|
553
|
-
default:
|
554
|
-
arrowLayer.className = 'introjs-arrow top';
|
555
|
-
|
556
|
-
var tooltipLayerStyleLeft = 0;
|
557
|
-
_checkRight(targetOffset, tooltipLayerStyleLeft, tooltipOffset, windowSize, tooltipLayer);
|
558
|
-
tooltipLayer.style.top = (targetOffset.height + 20) + 'px';
|
559
|
-
break;
|
560
|
-
}
|
561
|
-
}
|
562
|
-
|
563
|
-
/**
|
564
|
-
* Set tooltip left so it doesn't go off the right side of the window
|
565
|
-
*
|
566
|
-
* @return boolean true, if tooltipLayerStyleLeft is ok. false, otherwise.
|
567
|
-
*/
|
568
|
-
function _checkRight(targetOffset, tooltipLayerStyleLeft, tooltipOffset, windowSize, tooltipLayer) {
|
569
|
-
if (targetOffset.left + tooltipLayerStyleLeft + tooltipOffset.width > windowSize.width) {
|
570
|
-
// off the right side of the window
|
571
|
-
tooltipLayer.style.left = (windowSize.width - tooltipOffset.width - targetOffset.left) + 'px';
|
572
|
-
return false;
|
573
|
-
}
|
574
|
-
tooltipLayer.style.left = tooltipLayerStyleLeft + 'px';
|
575
|
-
return true;
|
576
|
-
}
|
577
|
-
|
578
|
-
/**
|
579
|
-
* Set tooltip right so it doesn't go off the left side of the window
|
580
|
-
*
|
581
|
-
* @return boolean true, if tooltipLayerStyleRight is ok. false, otherwise.
|
582
|
-
*/
|
583
|
-
function _checkLeft(targetOffset, tooltipLayerStyleRight, tooltipOffset, tooltipLayer) {
|
584
|
-
if (targetOffset.left + targetOffset.width - tooltipLayerStyleRight - tooltipOffset.width < 0) {
|
585
|
-
// off the left side of the window
|
586
|
-
tooltipLayer.style.left = (-targetOffset.left) + 'px';
|
587
|
-
return false;
|
588
|
-
}
|
589
|
-
tooltipLayer.style.right = tooltipLayerStyleRight + 'px';
|
590
|
-
return true;
|
591
|
-
}
|
592
|
-
|
593
|
-
/**
|
594
|
-
* Determines the position of the tooltip based on the position precedence and availability
|
595
|
-
* of screen space.
|
596
|
-
*
|
597
|
-
* @param {Object} targetElement
|
598
|
-
* @param {Object} tooltipLayer
|
599
|
-
* @param {Object} desiredTooltipPosition
|
600
|
-
*
|
601
|
-
*/
|
602
|
-
function _determineAutoPosition(targetElement, tooltipLayer, desiredTooltipPosition) {
|
603
|
-
|
604
|
-
// Take a clone of position precedence. These will be the available
|
605
|
-
var possiblePositions = this._options.positionPrecedence.slice();
|
606
|
-
|
607
|
-
var windowSize = _getWinSize();
|
608
|
-
var tooltipHeight = _getOffset(tooltipLayer).height + 10;
|
609
|
-
var tooltipWidth = _getOffset(tooltipLayer).width + 20;
|
610
|
-
var targetOffset = _getOffset(targetElement);
|
611
|
-
|
612
|
-
// If we check all the possible areas, and there are no valid places for the tooltip, the element
|
613
|
-
// must take up most of the screen real estate. Show the tooltip floating in the middle of the screen.
|
614
|
-
var calculatedPosition = "floating";
|
615
|
-
|
616
|
-
// Check if the width of the tooltip + the starting point would spill off the right side of the screen
|
617
|
-
// If no, neither bottom or top are valid
|
618
|
-
if (targetOffset.left + tooltipWidth > windowSize.width || ((targetOffset.left + (targetOffset.width / 2)) - tooltipWidth) < 0) {
|
619
|
-
_removeEntry(possiblePositions, "bottom");
|
620
|
-
_removeEntry(possiblePositions, "top");
|
621
|
-
} else {
|
622
|
-
// Check for space below
|
623
|
-
if ((targetOffset.height + targetOffset.top + tooltipHeight) > windowSize.height) {
|
624
|
-
_removeEntry(possiblePositions, "bottom");
|
625
|
-
}
|
626
|
-
|
627
|
-
// Check for space above
|
628
|
-
if (targetOffset.top - tooltipHeight < 0) {
|
629
|
-
_removeEntry(possiblePositions, "top");
|
630
|
-
}
|
631
|
-
}
|
632
|
-
|
633
|
-
// Check for space to the right
|
634
|
-
if (targetOffset.width + targetOffset.left + tooltipWidth > windowSize.width) {
|
635
|
-
_removeEntry(possiblePositions, "right");
|
636
|
-
}
|
637
|
-
|
638
|
-
// Check for space to the left
|
639
|
-
if (targetOffset.left - tooltipWidth < 0) {
|
640
|
-
_removeEntry(possiblePositions, "left");
|
641
|
-
}
|
642
|
-
|
643
|
-
// At this point, our array only has positions that are valid. Pick the first one, as it remains in order
|
644
|
-
if (possiblePositions.length > 0) {
|
645
|
-
calculatedPosition = possiblePositions[0];
|
646
|
-
}
|
647
|
-
|
648
|
-
// If the requested position is in the list, replace our calculated choice with that
|
649
|
-
if (desiredTooltipPosition && desiredTooltipPosition != "auto") {
|
650
|
-
if (possiblePositions.indexOf(desiredTooltipPosition) > -1) {
|
651
|
-
calculatedPosition = desiredTooltipPosition;
|
652
|
-
}
|
653
|
-
}
|
654
|
-
|
655
|
-
return calculatedPosition;
|
656
|
-
}
|
657
|
-
|
658
|
-
/**
|
659
|
-
* Remove an entry from a string array if it's there, does nothing if it isn't there.
|
660
|
-
*
|
661
|
-
* @param {Array} stringArray
|
662
|
-
* @param {String} stringToRemove
|
663
|
-
*/
|
664
|
-
function _removeEntry(stringArray, stringToRemove) {
|
665
|
-
if (stringArray.indexOf(stringToRemove) > -1) {
|
666
|
-
stringArray.splice(stringArray.indexOf(stringToRemove), 1);
|
667
|
-
}
|
668
|
-
}
|
669
|
-
|
670
|
-
/**
|
671
|
-
* Update the position of the helper layer on the screen
|
672
|
-
*
|
673
|
-
* @api private
|
674
|
-
* @method _setHelperLayerPosition
|
675
|
-
* @param {Object} helperLayer
|
676
|
-
*/
|
677
|
-
function _setHelperLayerPosition(helperLayer) {
|
678
|
-
if (helperLayer) {
|
679
|
-
//prevent error when `this._currentStep` in undefined
|
680
|
-
if (!this._introItems[this._currentStep]) return;
|
681
|
-
|
682
|
-
var currentElement = this._introItems[this._currentStep],
|
683
|
-
elementPosition = _getOffset(currentElement.element),
|
684
|
-
widthHeightPadding = 10;
|
685
|
-
|
686
|
-
if (currentElement.position == 'floating') {
|
687
|
-
widthHeightPadding = 0;
|
688
|
-
}
|
689
|
-
|
690
|
-
//set new position to helper layer
|
691
|
-
helperLayer.setAttribute('style', 'width: ' + (elementPosition.width + widthHeightPadding) + 'px; ' +
|
692
|
-
'height:' + (elementPosition.height + widthHeightPadding) + 'px; ' +
|
693
|
-
'top:' + (elementPosition.top - 5) + 'px;' +
|
694
|
-
'left: ' + (elementPosition.left - 5) + 'px;');
|
695
|
-
|
696
|
-
}
|
697
|
-
}
|
698
|
-
|
699
|
-
/**
|
700
|
-
* Add disableinteraction layer and adjust the size and position of the layer
|
701
|
-
*
|
702
|
-
* @api private
|
703
|
-
* @method _disableInteraction
|
704
|
-
*/
|
705
|
-
function _disableInteraction () {
|
706
|
-
var disableInteractionLayer = document.querySelector('.introjs-disableInteraction');
|
707
|
-
if (disableInteractionLayer === null) {
|
708
|
-
disableInteractionLayer = document.createElement('div');
|
709
|
-
disableInteractionLayer.className = 'introjs-disableInteraction';
|
710
|
-
this._targetElement.appendChild(disableInteractionLayer);
|
711
|
-
}
|
712
|
-
|
713
|
-
_setHelperLayerPosition.call(this, disableInteractionLayer);
|
714
|
-
}
|
715
|
-
|
716
|
-
/**
|
717
|
-
* Show an element on the page
|
718
|
-
*
|
719
|
-
* @api private
|
720
|
-
* @method _showElement
|
721
|
-
* @param {Object} targetElement
|
722
|
-
*/
|
723
|
-
function _showElement(targetElement) {
|
724
|
-
|
725
|
-
if (typeof (this._introChangeCallback) !== 'undefined') {
|
726
|
-
this._introChangeCallback.call(this, targetElement.element);
|
727
|
-
}
|
728
|
-
|
729
|
-
var self = this,
|
730
|
-
oldHelperLayer = document.querySelector('.introjs-helperLayer'),
|
731
|
-
oldReferenceLayer = document.querySelector('.introjs-tooltipReferenceLayer'),
|
732
|
-
highlightClass = 'introjs-helperLayer',
|
733
|
-
elementPosition = _getOffset(targetElement.element);
|
734
|
-
|
735
|
-
//check for a current step highlight class
|
736
|
-
if (typeof (targetElement.highlightClass) === 'string') {
|
737
|
-
highlightClass += (' ' + targetElement.highlightClass);
|
738
|
-
}
|
739
|
-
//check for options highlight class
|
740
|
-
if (typeof (this._options.highlightClass) === 'string') {
|
741
|
-
highlightClass += (' ' + this._options.highlightClass);
|
742
|
-
}
|
743
|
-
|
744
|
-
if (oldHelperLayer != null) {
|
745
|
-
var oldHelperNumberLayer = oldReferenceLayer.querySelector('.introjs-helperNumberLayer'),
|
746
|
-
oldtooltipLayer = oldReferenceLayer.querySelector('.introjs-tooltiptext'),
|
747
|
-
oldArrowLayer = oldReferenceLayer.querySelector('.introjs-arrow'),
|
748
|
-
oldtooltipContainer = oldReferenceLayer.querySelector('.introjs-tooltip'),
|
749
|
-
skipTooltipButton = oldReferenceLayer.querySelector('.introjs-skipbutton'),
|
750
|
-
prevTooltipButton = oldReferenceLayer.querySelector('.introjs-prevbutton'),
|
751
|
-
nextTooltipButton = oldReferenceLayer.querySelector('.introjs-nextbutton');
|
752
|
-
|
753
|
-
//update or reset the helper highlight class
|
754
|
-
oldHelperLayer.className = highlightClass;
|
755
|
-
//hide the tooltip
|
756
|
-
oldtooltipContainer.style.opacity = 0;
|
757
|
-
oldtooltipContainer.style.display = "none";
|
758
|
-
|
759
|
-
if (oldHelperNumberLayer != null) {
|
760
|
-
var lastIntroItem = this._introItems[(targetElement.step - 2 >= 0 ? targetElement.step - 2 : 0)];
|
761
|
-
|
762
|
-
if (lastIntroItem != null && (this._direction == 'forward' && lastIntroItem.position == 'floating') || (this._direction == 'backward' && targetElement.position == 'floating')) {
|
763
|
-
oldHelperNumberLayer.style.opacity = 0;
|
764
|
-
}
|
765
|
-
}
|
766
|
-
|
767
|
-
//set new position to helper layer
|
768
|
-
_setHelperLayerPosition.call(self, oldHelperLayer);
|
769
|
-
_setHelperLayerPosition.call(self, oldReferenceLayer);
|
770
|
-
|
771
|
-
//remove `introjs-fixParent` class from the elements
|
772
|
-
var fixParents = document.querySelectorAll('.introjs-fixParent');
|
773
|
-
if (fixParents && fixParents.length > 0) {
|
774
|
-
for (var i = fixParents.length - 1; i >= 0; i--) {
|
775
|
-
fixParents[i].className = fixParents[i].className.replace(/introjs-fixParent/g, '').replace(/^\s+|\s+$/g, '');
|
776
|
-
};
|
777
|
-
}
|
778
|
-
|
779
|
-
//remove old classes
|
780
|
-
var oldShowElement = document.querySelector('.introjs-showElement');
|
781
|
-
oldShowElement.className = oldShowElement.className.replace(/introjs-[a-zA-Z]+/g, '').replace(/^\s+|\s+$/g, '');
|
782
|
-
|
783
|
-
//we should wait until the CSS3 transition is competed (it's 0.3 sec) to prevent incorrect `height` and `width` calculation
|
784
|
-
if (self._lastShowElementTimer) {
|
785
|
-
clearTimeout(self._lastShowElementTimer);
|
786
|
-
}
|
787
|
-
self._lastShowElementTimer = setTimeout(function() {
|
788
|
-
//set current step to the label
|
789
|
-
if (oldHelperNumberLayer != null) {
|
790
|
-
oldHelperNumberLayer.innerHTML = targetElement.step;
|
791
|
-
}
|
792
|
-
//set current tooltip text
|
793
|
-
oldtooltipLayer.innerHTML = targetElement.intro;
|
794
|
-
//set the tooltip position
|
795
|
-
oldtooltipContainer.style.display = "block";
|
796
|
-
_placeTooltip.call(self, targetElement.element, oldtooltipContainer, oldArrowLayer, oldHelperNumberLayer);
|
797
|
-
|
798
|
-
//change active bullet
|
799
|
-
oldReferenceLayer.querySelector('.introjs-bullets li > a.active').className = '';
|
800
|
-
oldReferenceLayer.querySelector('.introjs-bullets li > a[data-stepnumber="' + targetElement.step + '"]').className = 'active';
|
801
|
-
|
802
|
-
oldReferenceLayer.querySelector('.introjs-progress .introjs-progressbar').setAttribute('style', 'width:' + _getProgress.call(self) + '%;');
|
803
|
-
|
804
|
-
//show the tooltip
|
805
|
-
oldtooltipContainer.style.opacity = 1;
|
806
|
-
if (oldHelperNumberLayer) oldHelperNumberLayer.style.opacity = 1;
|
807
|
-
|
808
|
-
//reset button focus
|
809
|
-
if (nextTooltipButton.tabIndex === -1) {
|
810
|
-
//tabindex of -1 means we are at the end of the tour - focus on skip / done
|
811
|
-
skipTooltipButton.focus();
|
812
|
-
} else {
|
813
|
-
//still in the tour, focus on next
|
814
|
-
nextTooltipButton.focus();
|
815
|
-
}
|
816
|
-
}, 350);
|
817
|
-
|
818
|
-
} else {
|
819
|
-
var helperLayer = document.createElement('div'),
|
820
|
-
referenceLayer = document.createElement('div'),
|
821
|
-
arrowLayer = document.createElement('div'),
|
822
|
-
tooltipLayer = document.createElement('div'),
|
823
|
-
tooltipTextLayer = document.createElement('div'),
|
824
|
-
bulletsLayer = document.createElement('div'),
|
825
|
-
progressLayer = document.createElement('div'),
|
826
|
-
buttonsLayer = document.createElement('div');
|
827
|
-
|
828
|
-
helperLayer.className = highlightClass;
|
829
|
-
referenceLayer.className = 'introjs-tooltipReferenceLayer';
|
830
|
-
|
831
|
-
//set new position to helper layer
|
832
|
-
_setHelperLayerPosition.call(self, helperLayer);
|
833
|
-
_setHelperLayerPosition.call(self, referenceLayer);
|
834
|
-
|
835
|
-
//add helper layer to target element
|
836
|
-
this._targetElement.appendChild(helperLayer);
|
837
|
-
this._targetElement.appendChild(referenceLayer);
|
838
|
-
|
839
|
-
arrowLayer.className = 'introjs-arrow';
|
840
|
-
|
841
|
-
tooltipTextLayer.className = 'introjs-tooltiptext';
|
842
|
-
tooltipTextLayer.innerHTML = targetElement.intro;
|
843
|
-
|
844
|
-
bulletsLayer.className = 'introjs-bullets';
|
845
|
-
|
846
|
-
if (this._options.showBullets === false) {
|
847
|
-
bulletsLayer.style.display = 'none';
|
848
|
-
}
|
849
|
-
|
850
|
-
var ulContainer = document.createElement('ul');
|
851
|
-
|
852
|
-
for (var i = 0, stepsLength = this._introItems.length; i < stepsLength; i++) {
|
853
|
-
var innerLi = document.createElement('li');
|
854
|
-
var anchorLink = document.createElement('a');
|
855
|
-
|
856
|
-
anchorLink.onclick = function() {
|
857
|
-
self.goToStep(this.getAttribute('data-stepnumber'));
|
858
|
-
};
|
859
|
-
|
860
|
-
if (i === (targetElement.step-1)) anchorLink.className = 'active';
|
861
|
-
|
862
|
-
anchorLink.href = 'javascript:void(0);';
|
863
|
-
anchorLink.innerHTML = " ";
|
864
|
-
anchorLink.setAttribute('data-stepnumber', this._introItems[i].step);
|
865
|
-
|
866
|
-
innerLi.appendChild(anchorLink);
|
867
|
-
ulContainer.appendChild(innerLi);
|
868
|
-
}
|
869
|
-
|
870
|
-
bulletsLayer.appendChild(ulContainer);
|
871
|
-
|
872
|
-
progressLayer.className = 'introjs-progress';
|
873
|
-
|
874
|
-
if (this._options.showProgress === false) {
|
875
|
-
progressLayer.style.display = 'none';
|
876
|
-
}
|
877
|
-
var progressBar = document.createElement('div');
|
878
|
-
progressBar.className = 'introjs-progressbar';
|
879
|
-
progressBar.setAttribute('style', 'width:' + _getProgress.call(this) + '%;');
|
880
|
-
|
881
|
-
progressLayer.appendChild(progressBar);
|
882
|
-
|
883
|
-
buttonsLayer.className = 'introjs-tooltipbuttons';
|
884
|
-
if (this._options.showButtons === false) {
|
885
|
-
buttonsLayer.style.display = 'none';
|
886
|
-
}
|
887
|
-
|
888
|
-
tooltipLayer.className = 'introjs-tooltip';
|
889
|
-
tooltipLayer.appendChild(tooltipTextLayer);
|
890
|
-
tooltipLayer.appendChild(bulletsLayer);
|
891
|
-
tooltipLayer.appendChild(progressLayer);
|
892
|
-
|
893
|
-
//add helper layer number
|
894
|
-
if (this._options.showStepNumbers == true) {
|
895
|
-
var helperNumberLayer = document.createElement('span');
|
896
|
-
helperNumberLayer.className = 'introjs-helperNumberLayer';
|
897
|
-
helperNumberLayer.innerHTML = targetElement.step;
|
898
|
-
referenceLayer.appendChild(helperNumberLayer);
|
899
|
-
}
|
900
|
-
|
901
|
-
tooltipLayer.appendChild(arrowLayer);
|
902
|
-
referenceLayer.appendChild(tooltipLayer);
|
903
|
-
|
904
|
-
//next button
|
905
|
-
var nextTooltipButton = document.createElement('a');
|
906
|
-
|
907
|
-
nextTooltipButton.onclick = function() {
|
908
|
-
if (self._introItems.length - 1 != self._currentStep) {
|
909
|
-
_nextStep.call(self);
|
910
|
-
}
|
911
|
-
};
|
912
|
-
|
913
|
-
nextTooltipButton.href = 'javascript:void(0);';
|
914
|
-
nextTooltipButton.innerHTML = this._options.nextLabel;
|
915
|
-
|
916
|
-
//previous button
|
917
|
-
var prevTooltipButton = document.createElement('a');
|
918
|
-
|
919
|
-
prevTooltipButton.onclick = function() {
|
920
|
-
if (self._currentStep != 0) {
|
921
|
-
_previousStep.call(self);
|
922
|
-
}
|
923
|
-
};
|
924
|
-
|
925
|
-
prevTooltipButton.href = 'javascript:void(0);';
|
926
|
-
prevTooltipButton.innerHTML = this._options.prevLabel;
|
927
|
-
|
928
|
-
//skip button
|
929
|
-
var skipTooltipButton = document.createElement('a');
|
930
|
-
skipTooltipButton.className = 'introjs-button introjs-skipbutton btn';
|
931
|
-
skipTooltipButton.id = 'introjs_skipbutton';
|
932
|
-
skipTooltipButton.href = 'javascript:void(0);';
|
933
|
-
skipTooltipButton.innerHTML = this._options.skipLabel;
|
934
|
-
|
935
|
-
skipTooltipButton.onclick = function() {
|
936
|
-
if (self._introItems.length - 1 == self._currentStep && typeof (self._introCompleteCallback) === 'function') {
|
937
|
-
self._introCompleteCallback.call(self);
|
938
|
-
}
|
939
|
-
|
940
|
-
if (self._introItems.length - 1 != self._currentStep && typeof (self._introExitCallback) === 'function') {
|
941
|
-
self._introExitCallback.call(self);
|
942
|
-
}
|
943
|
-
|
944
|
-
_exitIntro.call(self, self._targetElement);
|
945
|
-
};
|
946
|
-
|
947
|
-
buttonsLayer.appendChild(skipTooltipButton);
|
948
|
-
|
949
|
-
//in order to prevent displaying next/previous button always
|
950
|
-
if (this._introItems.length > 1) {
|
951
|
-
buttonsLayer.appendChild(prevTooltipButton);
|
952
|
-
buttonsLayer.appendChild(nextTooltipButton);
|
953
|
-
}
|
954
|
-
|
955
|
-
tooltipLayer.appendChild(buttonsLayer);
|
956
|
-
|
957
|
-
//set proper position
|
958
|
-
_placeTooltip.call(self, targetElement.element, tooltipLayer, arrowLayer, helperNumberLayer);
|
959
|
-
}
|
960
|
-
|
961
|
-
//disable interaction
|
962
|
-
if (this._options.disableInteraction === true) {
|
963
|
-
_disableInteraction.call(self);
|
964
|
-
}
|
965
|
-
|
966
|
-
prevTooltipButton.removeAttribute('tabIndex');
|
967
|
-
nextTooltipButton.removeAttribute('tabIndex');
|
968
|
-
|
969
|
-
if (this._currentStep == 0 && this._introItems.length > 1) {
|
970
|
-
prevTooltipButton.className = 'introjs-button introjs-prevbutton introjs-disabled disabled btn btn-success';
|
971
|
-
prevTooltipButton.tabIndex = '-1';
|
972
|
-
nextTooltipButton.className = 'introjs-button introjs-nextbutton btn btn-primary';
|
973
|
-
skipTooltipButton.innerHTML = this._options.skipLabel;
|
974
|
-
} else if (this._introItems.length - 1 == this._currentStep || this._introItems.length == 1) {
|
975
|
-
skipTooltipButton.innerHTML = this._options.doneLabel;
|
976
|
-
prevTooltipButton.className = 'introjs-button introjs-prevbutton btn btn-success';
|
977
|
-
nextTooltipButton.className = 'introjs-button introjs-nextbutton introjs-disabled disabled btn btn-primary';
|
978
|
-
nextTooltipButton.tabIndex = '-1';
|
979
|
-
} else {
|
980
|
-
prevTooltipButton.className = 'introjs-button introjs-prevbutton btn btn-success';
|
981
|
-
nextTooltipButton.className = 'introjs-button introjs-nextbutton btn btn-primary';
|
982
|
-
skipTooltipButton.innerHTML = this._options.skipLabel;
|
983
|
-
}
|
984
|
-
|
985
|
-
//Set focus on "next" button, so that hitting Enter always moves you onto the next step
|
986
|
-
nextTooltipButton.focus();
|
987
|
-
|
988
|
-
//add target element position style
|
989
|
-
targetElement.element.className += ' introjs-showElement';
|
990
|
-
|
991
|
-
var currentElementPosition = _getPropValue(targetElement.element, 'position');
|
992
|
-
if (currentElementPosition !== 'absolute' &&
|
993
|
-
currentElementPosition !== 'relative') {
|
994
|
-
//change to new intro item
|
995
|
-
targetElement.element.className += ' introjs-relativePosition';
|
996
|
-
}
|
997
|
-
|
998
|
-
var parentElm = targetElement.element.parentNode;
|
999
|
-
while (parentElm != null) {
|
1000
|
-
if (parentElm.tagName.toLowerCase() === 'body') break;
|
1001
|
-
|
1002
|
-
//fix The Stacking Contenxt problem.
|
1003
|
-
//More detail: https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context
|
1004
|
-
var zIndex = _getPropValue(parentElm, 'z-index');
|
1005
|
-
var opacity = parseFloat(_getPropValue(parentElm, 'opacity'));
|
1006
|
-
var transform = _getPropValue(parentElm, 'transform') || _getPropValue(parentElm, '-webkit-transform') || _getPropValue(parentElm, '-moz-transform') || _getPropValue(parentElm, '-ms-transform') || _getPropValue(parentElm, '-o-transform');
|
1007
|
-
if (/[0-9]+/.test(zIndex) || opacity < 1 || (transform !== 'none' && transform !== undefined)) {
|
1008
|
-
parentElm.className += ' introjs-fixParent';
|
1009
|
-
}
|
1010
|
-
|
1011
|
-
parentElm = parentElm.parentNode;
|
1012
|
-
}
|
1013
|
-
|
1014
|
-
if (!_elementInViewport(targetElement.element) && this._options.scrollToElement === true) {
|
1015
|
-
var rect = targetElement.element.getBoundingClientRect(),
|
1016
|
-
winHeight = _getWinSize().height,
|
1017
|
-
top = rect.bottom - (rect.bottom - rect.top),
|
1018
|
-
bottom = rect.bottom - winHeight;
|
1019
|
-
|
1020
|
-
//Scroll up
|
1021
|
-
if (top < 0 || targetElement.element.clientHeight > winHeight) {
|
1022
|
-
window.scrollBy(0, top - 30); // 30px padding from edge to look nice
|
1023
|
-
|
1024
|
-
//Scroll down
|
1025
|
-
} else {
|
1026
|
-
window.scrollBy(0, bottom + 100); // 70px + 30px padding from edge to look nice
|
1027
|
-
}
|
1028
|
-
}
|
1029
|
-
|
1030
|
-
if (typeof (this._introAfterChangeCallback) !== 'undefined') {
|
1031
|
-
this._introAfterChangeCallback.call(this, targetElement.element);
|
1032
|
-
}
|
1033
|
-
}
|
1034
|
-
|
1035
|
-
/**
|
1036
|
-
* Get an element CSS property on the page
|
1037
|
-
* Thanks to JavaScript Kit: http://www.javascriptkit.com/dhtmltutors/dhtmlcascade4.shtml
|
1038
|
-
*
|
1039
|
-
* @api private
|
1040
|
-
* @method _getPropValue
|
1041
|
-
* @param {Object} element
|
1042
|
-
* @param {String} propName
|
1043
|
-
* @returns Element's property value
|
1044
|
-
*/
|
1045
|
-
function _getPropValue (element, propName) {
|
1046
|
-
var propValue = '';
|
1047
|
-
if (element.currentStyle) { //IE
|
1048
|
-
propValue = element.currentStyle[propName];
|
1049
|
-
} else if (document.defaultView && document.defaultView.getComputedStyle) { //Others
|
1050
|
-
propValue = document.defaultView.getComputedStyle(element, null).getPropertyValue(propName);
|
1051
|
-
}
|
1052
|
-
|
1053
|
-
//Prevent exception in IE
|
1054
|
-
if (propValue && propValue.toLowerCase) {
|
1055
|
-
return propValue.toLowerCase();
|
1056
|
-
} else {
|
1057
|
-
return propValue;
|
1058
|
-
}
|
1059
|
-
}
|
1060
|
-
|
1061
|
-
/**
|
1062
|
-
* Provides a cross-browser way to get the screen dimensions
|
1063
|
-
* via: http://stackoverflow.com/questions/5864467/internet-explorer-innerheight
|
1064
|
-
*
|
1065
|
-
* @api private
|
1066
|
-
* @method _getWinSize
|
1067
|
-
* @returns {Object} width and height attributes
|
1068
|
-
*/
|
1069
|
-
function _getWinSize() {
|
1070
|
-
if (window.innerWidth != undefined) {
|
1071
|
-
return { width: window.innerWidth, height: window.innerHeight };
|
1072
|
-
} else {
|
1073
|
-
var D = document.documentElement;
|
1074
|
-
return { width: D.clientWidth, height: D.clientHeight };
|
1075
|
-
}
|
1076
|
-
}
|
1077
|
-
|
1078
|
-
/**
|
1079
|
-
* Add overlay layer to the page
|
1080
|
-
* http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
|
1081
|
-
*
|
1082
|
-
* @api private
|
1083
|
-
* @method _elementInViewport
|
1084
|
-
* @param {Object} el
|
1085
|
-
*/
|
1086
|
-
function _elementInViewport(el) {
|
1087
|
-
var rect = el.getBoundingClientRect();
|
1088
|
-
|
1089
|
-
return (
|
1090
|
-
rect.top >= 0 &&
|
1091
|
-
rect.left >= 0 &&
|
1092
|
-
(rect.bottom+80) <= window.innerHeight && // add 80 to get the text right
|
1093
|
-
rect.right <= window.innerWidth
|
1094
|
-
);
|
1095
|
-
}
|
1096
|
-
|
1097
|
-
/**
|
1098
|
-
* Add overlay layer to the page
|
1099
|
-
*
|
1100
|
-
* @api private
|
1101
|
-
* @method _addOverlayLayer
|
1102
|
-
* @param {Object} targetElm
|
1103
|
-
*/
|
1104
|
-
function _addOverlayLayer(targetElm) {
|
1105
|
-
var overlayLayer = document.createElement('div'),
|
1106
|
-
styleText = '',
|
1107
|
-
self = this;
|
1108
|
-
|
1109
|
-
//set css class name
|
1110
|
-
overlayLayer.className = 'introjs-overlay';
|
1111
|
-
|
1112
|
-
//check if the target element is body, we should calculate the size of overlay layer in a better way
|
1113
|
-
if (targetElm.tagName.toLowerCase() === 'body') {
|
1114
|
-
styleText += 'top: 0;bottom: 0; left: 0;right: 0;position: fixed;';
|
1115
|
-
overlayLayer.setAttribute('style', styleText);
|
1116
|
-
} else {
|
1117
|
-
//set overlay layer position
|
1118
|
-
var elementPosition = _getOffset(targetElm);
|
1119
|
-
if (elementPosition) {
|
1120
|
-
styleText += 'width: ' + elementPosition.width + 'px; height:' + elementPosition.height + 'px; top:' + elementPosition.top + 'px;left: ' + elementPosition.left + 'px;';
|
1121
|
-
overlayLayer.setAttribute('style', styleText);
|
1122
|
-
}
|
1123
|
-
}
|
1124
|
-
|
1125
|
-
targetElm.appendChild(overlayLayer);
|
1126
|
-
|
1127
|
-
overlayLayer.onclick = function() {
|
1128
|
-
if (self._options.exitOnOverlayClick == true) {
|
1129
|
-
|
1130
|
-
//check if any callback is defined
|
1131
|
-
if (self._introExitCallback != undefined) {
|
1132
|
-
self._introExitCallback.call(self);
|
1133
|
-
}
|
1134
|
-
_exitIntro.call(self, targetElm);
|
1135
|
-
}
|
1136
|
-
};
|
1137
|
-
|
1138
|
-
setTimeout(function() {
|
1139
|
-
styleText += 'opacity: ' + self._options.overlayOpacity.toString() + ';';
|
1140
|
-
overlayLayer.setAttribute('style', styleText);
|
1141
|
-
}, 10);
|
1142
|
-
|
1143
|
-
return true;
|
1144
|
-
}
|
1145
|
-
|
1146
|
-
/**
|
1147
|
-
* Get an element position on the page
|
1148
|
-
* Thanks to `meouw`: http://stackoverflow.com/a/442474/375966
|
1149
|
-
*
|
1150
|
-
* @api private
|
1151
|
-
* @method _getOffset
|
1152
|
-
* @param {Object} element
|
1153
|
-
* @returns Element's position info
|
1154
|
-
*/
|
1155
|
-
function _getOffset(element) {
|
1156
|
-
var elementPosition = {};
|
1157
|
-
|
1158
|
-
//set width
|
1159
|
-
elementPosition.width = element.offsetWidth;
|
1160
|
-
|
1161
|
-
//set height
|
1162
|
-
elementPosition.height = element.offsetHeight;
|
1163
|
-
|
1164
|
-
//calculate element top and left
|
1165
|
-
var _x = 0;
|
1166
|
-
var _y = 0;
|
1167
|
-
while (element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) {
|
1168
|
-
_x += element.offsetLeft;
|
1169
|
-
_y += element.offsetTop;
|
1170
|
-
element = element.offsetParent;
|
1171
|
-
}
|
1172
|
-
//set top
|
1173
|
-
elementPosition.top = _y;
|
1174
|
-
//set left
|
1175
|
-
elementPosition.left = _x;
|
1176
|
-
|
1177
|
-
return elementPosition;
|
1178
|
-
}
|
1179
|
-
|
1180
|
-
/**
|
1181
|
-
* Gets the current progress percentage
|
1182
|
-
*
|
1183
|
-
* @api private
|
1184
|
-
* @method _getProgress
|
1185
|
-
* @returns current progress percentage
|
1186
|
-
*/
|
1187
|
-
function _getProgress() {
|
1188
|
-
// Steps are 0 indexed
|
1189
|
-
var currentStep = parseInt((this._currentStep + 1), 10);
|
1190
|
-
return ((currentStep / this._introItems.length) * 100);
|
1191
|
-
}
|
1192
|
-
|
1193
|
-
/**
|
1194
|
-
* Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
|
1195
|
-
* via: http://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically
|
1196
|
-
*
|
1197
|
-
* @param obj1
|
1198
|
-
* @param obj2
|
1199
|
-
* @returns obj3 a new object based on obj1 and obj2
|
1200
|
-
*/
|
1201
|
-
function _mergeOptions(obj1,obj2) {
|
1202
|
-
var obj3 = {};
|
1203
|
-
for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
|
1204
|
-
for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
|
1205
|
-
return obj3;
|
1206
|
-
}
|
1207
|
-
|
1208
|
-
var introJs = function (targetElm) {
|
1209
|
-
if (typeof (targetElm) === 'object') {
|
1210
|
-
//Ok, create a new instance
|
1211
|
-
return new IntroJs(targetElm);
|
1212
|
-
|
1213
|
-
} else if (typeof (targetElm) === 'string') {
|
1214
|
-
//select the target element with query selector
|
1215
|
-
var targetElement = document.querySelector(targetElm);
|
1216
|
-
|
1217
|
-
if (targetElement) {
|
1218
|
-
return new IntroJs(targetElement);
|
1219
|
-
} else {
|
1220
|
-
throw new Error('There is no element with given selector.');
|
1221
|
-
}
|
1222
|
-
} else {
|
1223
|
-
return new IntroJs(document.body);
|
1224
|
-
}
|
1225
|
-
};
|
1226
|
-
|
1227
|
-
/**
|
1228
|
-
* Current IntroJs version
|
1229
|
-
*
|
1230
|
-
* @property version
|
1231
|
-
* @type String
|
1232
|
-
*/
|
1233
|
-
introJs.version = VERSION;
|
1234
|
-
|
1235
|
-
//Prototype
|
1236
|
-
introJs.fn = IntroJs.prototype = {
|
1237
|
-
clone: function () {
|
1238
|
-
return new IntroJs(this);
|
1239
|
-
},
|
1240
|
-
setOption: function(option, value) {
|
1241
|
-
this._options[option] = value;
|
1242
|
-
return this;
|
1243
|
-
},
|
1244
|
-
setOptions: function(options) {
|
1245
|
-
this._options = _mergeOptions(this._options, options);
|
1246
|
-
return this;
|
1247
|
-
},
|
1248
|
-
start: function () {
|
1249
|
-
_introForElement.call(this, this._targetElement);
|
1250
|
-
return this;
|
1251
|
-
},
|
1252
|
-
goToStep: function(step) {
|
1253
|
-
_goToStep.call(this, step);
|
1254
|
-
return this;
|
1255
|
-
},
|
1256
|
-
nextStep: function() {
|
1257
|
-
_nextStep.call(this);
|
1258
|
-
return this;
|
1259
|
-
},
|
1260
|
-
previousStep: function() {
|
1261
|
-
_previousStep.call(this);
|
1262
|
-
return this;
|
1263
|
-
},
|
1264
|
-
exit: function() {
|
1265
|
-
_exitIntro.call(this, this._targetElement);
|
1266
|
-
return this;
|
1267
|
-
},
|
1268
|
-
refresh: function() {
|
1269
|
-
_setHelperLayerPosition.call(this, document.querySelector('.introjs-helperLayer'));
|
1270
|
-
_setHelperLayerPosition.call(this, document.querySelector('.introjs-tooltipReferenceLayer'));
|
1271
|
-
return this;
|
1272
|
-
},
|
1273
|
-
onbeforechange: function(providedCallback) {
|
1274
|
-
if (typeof (providedCallback) === 'function') {
|
1275
|
-
this._introBeforeChangeCallback = providedCallback;
|
1276
|
-
} else {
|
1277
|
-
throw new Error('Provided callback for onbeforechange was not a function');
|
1278
|
-
}
|
1279
|
-
return this;
|
1280
|
-
},
|
1281
|
-
onchange: function(providedCallback) {
|
1282
|
-
if (typeof (providedCallback) === 'function') {
|
1283
|
-
this._introChangeCallback = providedCallback;
|
1284
|
-
} else {
|
1285
|
-
throw new Error('Provided callback for onchange was not a function.');
|
1286
|
-
}
|
1287
|
-
return this;
|
1288
|
-
},
|
1289
|
-
onafterchange: function(providedCallback) {
|
1290
|
-
if (typeof (providedCallback) === 'function') {
|
1291
|
-
this._introAfterChangeCallback = providedCallback;
|
1292
|
-
} else {
|
1293
|
-
throw new Error('Provided callback for onafterchange was not a function');
|
1294
|
-
}
|
1295
|
-
return this;
|
1296
|
-
},
|
1297
|
-
oncomplete: function(providedCallback) {
|
1298
|
-
if (typeof (providedCallback) === 'function') {
|
1299
|
-
this._introCompleteCallback = providedCallback;
|
1300
|
-
} else {
|
1301
|
-
throw new Error('Provided callback for oncomplete was not a function.');
|
1302
|
-
}
|
1303
|
-
return this;
|
1304
|
-
},
|
1305
|
-
onexit: function(providedCallback) {
|
1306
|
-
if (typeof (providedCallback) === 'function') {
|
1307
|
-
this._introExitCallback = providedCallback;
|
1308
|
-
} else {
|
1309
|
-
throw new Error('Provided callback for onexit was not a function.');
|
1310
|
-
}
|
1311
|
-
return this;
|
1312
|
-
}
|
1313
|
-
};
|
1314
|
-
|
1315
|
-
exports.introJs = introJs;
|
1316
|
-
return introJs;
|
1317
|
-
}));
|