Skip to content

Commit 49cc77a

Browse files
authored
Merge pull request usablica#1118 from usablica/fix-next-button-single-step
fix(showElement): next/done button needs to be displayed when tour has one step
2 parents 54864e4 + 82e06a8 commit 49cc77a

17 files changed

+370
-130
lines changed

.jshintrc

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,32 @@
55
"eqeqeq": true,
66
"globals": {
77
"window": true,
8-
"jest": true,
9-
"describe": true,
10-
"expect": true,
11-
"test": true,
128
"document": true,
139
"exports": true,
1410
"define": true,
1511
"SVGElement": true,
12+
"Element": true,
1613
"module": true,
1714
"console": true,
1815
"global": true,
19-
"self": true
16+
"self": true,
17+
18+
"afterAll": false,
19+
"afterEach": false,
20+
"beforeAll": false,
21+
"beforeEach": false,
22+
"check": false,
23+
"describe": false,
24+
"expect": false,
25+
"gen": false,
26+
"it": false,
27+
"fit": false,
28+
"jest": false,
29+
"pit": false,
30+
"require": false,
31+
"test": false,
32+
"xdescribe": false,
33+
"xit": false,
34+
"xtest": false
2035
}
2136
}

src/core/addOverlayLayer.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import setStyle from "../util/setStyle";
1212
*/
1313
export default function addOverlayLayer(targetElm) {
1414
const overlayLayer = createElement("div", {
15-
className: "introjs-overlay"
15+
className: "introjs-overlay",
1616
});
1717

1818
const self = this;
@@ -24,7 +24,7 @@ export default function addOverlayLayer(targetElm) {
2424
bottom: 0,
2525
left: 0,
2626
right: 0,
27-
position: 'fixed'
27+
position: "fixed",
2828
});
2929
} else {
3030
// set overlay layer position
@@ -34,7 +34,7 @@ export default function addOverlayLayer(targetElm) {
3434
width: `${elementPosition.width}px`,
3535
height: `${elementPosition.height}px`,
3636
top: `${elementPosition.top}px`,
37-
left: `${elementPosition.left}px`
37+
left: `${elementPosition.left}px`,
3838
});
3939
}
4040
}
@@ -43,7 +43,7 @@ export default function addOverlayLayer(targetElm) {
4343

4444
if (self._options.exitOnOverlayClick === true) {
4545
setStyle(overlayLayer, {
46-
cursor: 'pointer'
46+
cursor: "pointer",
4747
});
4848

4949
overlayLayer.onclick = () => {

src/core/hint.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ export function addHints() {
132132

133133
if (hintsWrapper === null) {
134134
hintsWrapper = createElement("div", {
135-
className: "introjs-hints"
135+
className: "introjs-hints",
136136
});
137137
}
138138

@@ -163,7 +163,7 @@ export function addHints() {
163163
}
164164

165165
const hint = createElement("a", {
166-
className: "introjs-hint"
166+
className: "introjs-hint",
167167
});
168168
setAnchorAsButton(hint);
169169

@@ -179,11 +179,11 @@ export function addHints() {
179179
}
180180

181181
const hintDot = createElement("div", {
182-
className: "introjs-hint-dot"
182+
className: "introjs-hint-dot",
183183
});
184184

185185
const hintPulse = createElement("div", {
186-
className: "introjs-hint-pulse"
186+
className: "introjs-hint-pulse",
187187
});
188188

189189
hint.appendChild(hintDot);
@@ -294,7 +294,7 @@ export function showHintDialog(stepId) {
294294
}
295295

296296
const tooltipLayer = createElement("div", {
297-
className: "introjs-tooltip"
297+
className: "introjs-tooltip",
298298
});
299299
const tooltipTextLayer = createElement("div");
300300
const arrowLayer = createElement("div");

src/core/introForElement.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export default function introForElement(targetElm, group) {
2828
//set the step
2929
currentItem.step = introItems.length + 1;
3030

31-
currentItem.title = currentItem.title || '';
31+
currentItem.title = currentItem.title || "";
3232

3333
//use querySelector function only when developer used CSS selector
3434
if (typeof currentItem.element === "string") {
@@ -47,7 +47,7 @@ export default function introForElement(targetElm, group) {
4747

4848
if (floatingElementQuery === null) {
4949
floatingElementQuery = createElement("div", {
50-
className: "introjsFloatingElement"
50+
className: "introjsFloatingElement",
5151
});
5252

5353
document.body.appendChild(floatingElementQuery);
@@ -102,7 +102,7 @@ export default function introForElement(targetElm, group) {
102102
if (step > 0) {
103103
introItems[step - 1] = {
104104
element: currentElement,
105-
title: currentElement.getAttribute("data-title") || '',
105+
title: currentElement.getAttribute("data-title") || "",
106106
intro: currentElement.getAttribute("data-intro"),
107107
step: parseInt(currentElement.getAttribute("data-step"), 10),
108108
tooltipClass: currentElement.getAttribute("data-tooltipclass"),
@@ -148,7 +148,7 @@ export default function introForElement(targetElm, group) {
148148

149149
introItems[nextStep] = {
150150
element: currentElement,
151-
title: currentElement.getAttribute("data-title") || '',
151+
title: currentElement.getAttribute("data-title") || "",
152152
intro: currentElement.getAttribute("data-intro"),
153153
step: nextStep + 1,
154154
tooltipClass: currentElement.getAttribute("data-tooltipclass"),

src/core/setHelperLayerPosition.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export default function setHelperLayerPosition(helperLayer) {
3838
width: `${elementPosition.width + widthHeightPadding}px`,
3939
height: `${elementPosition.height + widthHeightPadding}px`,
4040
top: `${elementPosition.top - widthHeightPadding / 2}px`,
41-
left: `${elementPosition.left - widthHeightPadding / 2}px`
41+
left: `${elementPosition.left - widthHeightPadding / 2}px`,
4242
});
4343
}
4444
}

src/core/showElement.js

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function _disableInteraction() {
4040

4141
if (disableInteractionLayer === null) {
4242
disableInteractionLayer = createElement("div", {
43-
className: "introjs-disableInteraction"
43+
className: "introjs-disableInteraction",
4444
});
4545

4646
this._targetElement.appendChild(disableInteractionLayer);
@@ -194,34 +194,34 @@ export default function _showElement(targetElement) {
194194
// end of old element if-else condition
195195
} else {
196196
const helperLayer = createElement("div", {
197-
className: highlightClass
197+
className: highlightClass,
198198
});
199199
const referenceLayer = createElement("div", {
200-
className: "introjs-tooltipReferenceLayer"
200+
className: "introjs-tooltipReferenceLayer",
201201
});
202202
const arrowLayer = createElement("div", {
203-
className: "introjs-arrow"
203+
className: "introjs-arrow",
204204
});
205205
const tooltipLayer = createElement("div", {
206-
className: "introjs-tooltip"
206+
className: "introjs-tooltip",
207207
});
208208
const tooltipTextLayer = createElement("div", {
209-
className: "introjs-tooltiptext"
209+
className: "introjs-tooltiptext",
210210
});
211211
const tooltipHeaderLayer = createElement("div", {
212-
className: "introjs-tooltip-header"
212+
className: "introjs-tooltip-header",
213213
});
214214
const tooltipTitleLayer = createElement("h1", {
215-
className: "introjs-tooltip-title"
215+
className: "introjs-tooltip-title",
216216
});
217217
const bulletsLayer = createElement("div", {
218-
className: "introjs-bullets"
218+
className: "introjs-bullets",
219219
});
220220
const progressLayer = createElement("div");
221221
const buttonsLayer = createElement("div");
222222

223223
setStyle(helperLayer, {
224-
'box-shadow': `0 0 1px 2px rgba(33, 33, 33, 0.8), rgba(33, 33, 33, ${self._options.overlayOpacity.toString()}) 0 0 0 5000px`
224+
"box-shadow": `0 0 1px 2px rgba(33, 33, 33, 0.8), rgba(33, 33, 33, ${self._options.overlayOpacity.toString()}) 0 0 0 5000px`,
225225
});
226226

227227
// scroll to element
@@ -284,11 +284,11 @@ export default function _showElement(targetElement) {
284284
}
285285

286286
const progressBar = createElement("div", {
287-
className: "introjs-progressbar"
287+
className: "introjs-progressbar",
288288
});
289289

290290
if (this._options.progressBarAdditionalClass) {
291-
progressBar.className += ' ' + this._options.progressBarAdditionalClass;
291+
progressBar.className += " " + this._options.progressBarAdditionalClass;
292292
}
293293
progressBar.setAttribute("role", "progress");
294294
progressBar.setAttribute("aria-valuemin", 0);
@@ -353,7 +353,7 @@ export default function _showElement(targetElement) {
353353

354354
//skip button
355355
skipTooltipButton = createElement("a", {
356-
className: 'introjs-skipbutton'
356+
className: "introjs-skipbutton",
357357
});
358358

359359
setAnchorAsButton(skipTooltipButton);
@@ -376,21 +376,18 @@ export default function _showElement(targetElement) {
376376

377377
tooltipHeaderLayer.appendChild(skipTooltipButton);
378378

379-
//in order to prevent displaying next/previous button always
379+
//in order to prevent displaying previous button always
380380
if (this._introItems.length > 1) {
381381
buttonsLayer.appendChild(prevTooltipButton);
382-
buttonsLayer.appendChild(nextTooltipButton);
383382
}
384383

384+
// we always need the next button because this
385+
// button changes to "Done" in the last step of the tour
386+
buttonsLayer.appendChild(nextTooltipButton);
385387
tooltipLayer.appendChild(buttonsLayer);
386388

387389
//set proper position
388-
placeTooltip.call(
389-
self,
390-
targetElement.element,
391-
tooltipLayer,
392-
arrowLayer
393-
);
390+
placeTooltip.call(self, targetElement.element, tooltipLayer, arrowLayer);
394391

395392
// change the scroll of the window, if needed
396393
scrollTo.call(this, targetElement.scrollTo, targetElement, tooltipLayer);
@@ -474,12 +471,14 @@ export default function _showElement(targetElement) {
474471
) {
475472
if (this._options.nextToDone === true) {
476473
nextTooltipButton.innerHTML = this._options.doneLabel;
477-
addClass(nextTooltipButton, "introjs-donebutton");
474+
addClass(
475+
nextTooltipButton,
476+
`${this._options.buttonClass} introjs-nextbutton introjs-donebutton`
477+
);
478478
} else {
479479
nextTooltipButton.className = `${this._options.buttonClass} introjs-nextbutton introjs-disabled`;
480480
}
481481
}
482-
483482
}
484483
} else {
485484
// steps between start and end

src/core/steps.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ export function nextStep() {
5757
let continueStep = true;
5858

5959
if (typeof this._introBeforeChangeCallback !== "undefined") {
60-
continueStep = this._introBeforeChangeCallback.call(this, nextStep && nextStep.element);
60+
continueStep = this._introBeforeChangeCallback.call(
61+
this,
62+
nextStep && nextStep.element
63+
);
6164
}
6265

6366
// if `onbeforechange` returned `false`, stop displaying the element
@@ -98,7 +101,10 @@ export function previousStep() {
98101
let continueStep = true;
99102

100103
if (typeof this._introBeforeChangeCallback !== "undefined") {
101-
continueStep = this._introBeforeChangeCallback.call(this, nextStep && nextStep.element);
104+
continueStep = this._introBeforeChangeCallback.call(
105+
this,
106+
nextStep && nextStep.element
107+
);
102108
}
103109

104110
// if `onbeforechange` returned `false`, stop displaying the element

src/util/addClass.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ export default function addClass(element, className) {
1414
// svg
1515
const pre = element.getAttribute("class") || "";
1616

17-
element.setAttribute("class", `${pre} ${className}`);
17+
if (!pre.match(className)) {
18+
// check if element doesn't already have className
19+
element.setAttribute("class", `${pre} ${className}`);
20+
}
1821
} else {
1922
if (element.classList !== undefined) {
2023
// check for modern classList property

src/util/appendChild.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ import setStyle from "./setStyle";
99
*/
1010
export default function appendChild(parentElement, element, animate) {
1111
if (animate) {
12-
const existingOpacity = element.style.opacity || '1';
12+
const existingOpacity = element.style.opacity || "1";
1313

1414
setStyle(element, {
15-
'opacity': '0'
15+
opacity: "0",
1616
});
1717

1818
window.setTimeout(() => {
1919
setStyle(element, {
20-
'opacity': existingOpacity
20+
opacity: existingOpacity,
2121
});
2222
}, 10);
2323
}

src/util/createElement.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* Create a DOM element with various attributes
3-
*
3+
*
44
* @param {String} tagname
55
* @param {Object} attrs
66
* @return Element
@@ -18,7 +18,7 @@ export default function _createElement(tagname, attrs) {
1818
for (const k in attrs) {
1919
let v = attrs[k];
2020

21-
if (k === 'style') {
21+
if (k === "style") {
2222
setStyle(element, v);
2323
} else if (k.match(setAttRegex)) {
2424
element.setAttribute(k, v);

src/util/removeChild.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export default function removeChild(element, animate) {
1313

1414
if (animate) {
1515
setStyle(element, {
16-
'opacity': '0',
16+
opacity: "0",
1717
});
1818

1919
window.setTimeout(() => {

src/util/setStyle.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
* @return null
77
*/
88
export default function setStyle(element, style) {
9-
let cssText = '';
9+
let cssText = "";
1010

1111
if (element.style.cssText) {
1212
cssText += element.style.cssText;
1313
}
1414

15-
if (typeof style === 'string') {
15+
if (typeof style === "string") {
1616
cssText += style;
1717
} else {
1818
for (const rule in style) {

0 commit comments

Comments
 (0)