Allow displaying buttons on single highlight elements
Browse files- .eslintrc.json +0 -1
- src/common/constants.js +4 -2
- src/core/popover.js +17 -1
- src/driver.scss +16 -3
- src/index.js +17 -17
.eslintrc.json
CHANGED
@@ -4,7 +4,6 @@
|
|
4 |
"browser": true
|
5 |
},
|
6 |
"rules": {
|
7 |
-
"no-console": "off",
|
8 |
"no-underscore-dangle": "off",
|
9 |
"no-plusplus": "off",
|
10 |
"no-cond-assign": "off",
|
|
|
4 |
"browser": true
|
5 |
},
|
6 |
"rules": {
|
|
|
7 |
"no-underscore-dangle": "off",
|
8 |
"no-plusplus": "off",
|
9 |
"no-cond-assign": "off",
|
src/common/constants.js
CHANGED
@@ -27,6 +27,8 @@ export const CLASS_CLOSE_BTN = 'driver-close-btn';
|
|
27 |
export const CLASS_NEXT_STEP_BTN = 'driver-next-btn';
|
28 |
export const CLASS_PREV_STEP_BTN = 'driver-prev-btn';
|
29 |
export const CLASS_BTN_DISABLED = 'driver-disabled';
|
|
|
|
|
30 |
|
31 |
// NOTE: It must match the one set in the animations in CSS file
|
32 |
export const ANIMATION_DURATION_MS = 300;
|
@@ -37,9 +39,9 @@ export const POPOVER_HTML = (className = '') => `
|
|
37 |
<div class="${CLASS_POPOVER_TIP}"></div>
|
38 |
<div class="${CLASS_POPOVER_TITLE}">Popover Title</div>
|
39 |
<div class="${CLASS_POPOVER_DESCRIPTION}">Popover Description</div>
|
40 |
-
<div class="${CLASS_POPOVER_FOOTER}">
|
41 |
<button class="${CLASS_CLOSE_BTN}">Close</button>
|
42 |
-
<span class="driver-btn-group">
|
43 |
<button class="${CLASS_PREV_STEP_BTN}">← Previous</button>
|
44 |
<button class="${CLASS_NEXT_STEP_BTN}">Next →</button>
|
45 |
</span>
|
|
|
27 |
export const CLASS_NEXT_STEP_BTN = 'driver-next-btn';
|
28 |
export const CLASS_PREV_STEP_BTN = 'driver-prev-btn';
|
29 |
export const CLASS_BTN_DISABLED = 'driver-disabled';
|
30 |
+
export const CLASS_CLOSE_ONLY_BTN = 'driver-close-only-btn';
|
31 |
+
export const CLASS_NAVIGATION_BTNS = 'driver-navigation-btns';
|
32 |
|
33 |
// NOTE: It must match the one set in the animations in CSS file
|
34 |
export const ANIMATION_DURATION_MS = 300;
|
|
|
39 |
<div class="${CLASS_POPOVER_TIP}"></div>
|
40 |
<div class="${CLASS_POPOVER_TITLE}">Popover Title</div>
|
41 |
<div class="${CLASS_POPOVER_DESCRIPTION}">Popover Description</div>
|
42 |
+
<div class="driver-clearfix ${CLASS_POPOVER_FOOTER}">
|
43 |
<button class="${CLASS_CLOSE_BTN}">Close</button>
|
44 |
+
<span class="driver-btn-group ${CLASS_NAVIGATION_BTNS}">
|
45 |
<button class="${CLASS_PREV_STEP_BTN}">← Previous</button>
|
46 |
<button class="${CLASS_NEXT_STEP_BTN}">Next →</button>
|
47 |
</span>
|
src/core/popover.js
CHANGED
@@ -2,6 +2,7 @@ import Element from './element';
|
|
2 |
import {
|
3 |
CLASS_BTN_DISABLED,
|
4 |
CLASS_CLOSE_BTN,
|
|
|
5 |
CLASS_NEXT_STEP_BTN,
|
6 |
CLASS_POPOVER_DESCRIPTION,
|
7 |
CLASS_POPOVER_FOOTER,
|
@@ -190,12 +191,27 @@ export default class Popover extends Element {
|
|
190 |
this.prevBtnNode.innerHTML = this.options.prevBtnText;
|
191 |
this.closeBtnNode.innerHTML = this.options.closeBtnText;
|
192 |
|
|
|
|
|
193 |
// If there was only one item, hide the buttons
|
194 |
-
if (!this.options.showButtons
|
195 |
this.footerNode.style.display = 'none';
|
196 |
return;
|
197 |
}
|
198 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
199 |
this.footerNode.style.display = 'block';
|
200 |
if (this.options.isFirst) {
|
201 |
this.prevBtnNode.classList.add(CLASS_BTN_DISABLED);
|
|
|
2 |
import {
|
3 |
CLASS_BTN_DISABLED,
|
4 |
CLASS_CLOSE_BTN,
|
5 |
+
CLASS_CLOSE_ONLY_BTN,
|
6 |
CLASS_NEXT_STEP_BTN,
|
7 |
CLASS_POPOVER_DESCRIPTION,
|
8 |
CLASS_POPOVER_FOOTER,
|
|
|
191 |
this.prevBtnNode.innerHTML = this.options.prevBtnText;
|
192 |
this.closeBtnNode.innerHTML = this.options.closeBtnText;
|
193 |
|
194 |
+
const hasSteps = this.options.totalCount && this.options.totalCount !== 1;
|
195 |
+
|
196 |
// If there was only one item, hide the buttons
|
197 |
+
if (!this.options.showButtons) {
|
198 |
this.footerNode.style.display = 'none';
|
199 |
return;
|
200 |
}
|
201 |
|
202 |
+
// If this is just a single highlighted element i.e. there
|
203 |
+
// are no other steps to go to – just hide the navigation buttons
|
204 |
+
if (!hasSteps) {
|
205 |
+
this.nextBtnNode.style.display = 'none';
|
206 |
+
this.prevBtnNode.style.display = 'none';
|
207 |
+
this.closeBtnNode.classList.add(CLASS_CLOSE_ONLY_BTN);
|
208 |
+
} else {
|
209 |
+
// @todo modify CSS to use block
|
210 |
+
this.nextBtnNode.style.display = 'inline-block';
|
211 |
+
this.prevBtnNode.style.display = 'inline-block';
|
212 |
+
this.closeBtnNode.classList.remove(CLASS_CLOSE_ONLY_BTN);
|
213 |
+
}
|
214 |
+
|
215 |
this.footerNode.style.display = 'block';
|
216 |
if (this.options.isFirst) {
|
217 |
this.prevBtnNode.classList.add(CLASS_BTN_DISABLED);
|
src/driver.scss
CHANGED
@@ -107,8 +107,7 @@ div#driver-popover-item {
|
|
107 |
|
108 |
.driver-popover-footer {
|
109 |
display: block;
|
110 |
-
|
111 |
-
margin-top: 5px;
|
112 |
|
113 |
button {
|
114 |
display: inline-block;
|
@@ -123,7 +122,6 @@ div#driver-popover-item {
|
|
123 |
background-color: $button-bg;
|
124 |
border-radius: 2px;
|
125 |
zoom: 1;
|
126 |
-
margin: 10px 0 0;
|
127 |
line-height: 1.3;
|
128 |
}
|
129 |
|
@@ -137,6 +135,10 @@ div#driver-popover-item {
|
|
137 |
float: left;
|
138 |
}
|
139 |
|
|
|
|
|
|
|
|
|
140 |
.driver-btn-group {
|
141 |
float: right;
|
142 |
}
|
@@ -162,6 +164,17 @@ div#driver-popover-item {
|
|
162 |
}
|
163 |
}
|
164 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
165 |
.driver-stage-no-animation {
|
166 |
-webkit-transition: none !important;
|
167 |
-moz-transition: none !important;
|
|
|
107 |
|
108 |
.driver-popover-footer {
|
109 |
display: block;
|
110 |
+
margin-top: 10px;
|
|
|
111 |
|
112 |
button {
|
113 |
display: inline-block;
|
|
|
122 |
background-color: $button-bg;
|
123 |
border-radius: 2px;
|
124 |
zoom: 1;
|
|
|
125 |
line-height: 1.3;
|
126 |
}
|
127 |
|
|
|
135 |
float: left;
|
136 |
}
|
137 |
|
138 |
+
.driver-close-only-btn {
|
139 |
+
float: right;
|
140 |
+
}
|
141 |
+
|
142 |
.driver-btn-group {
|
143 |
float: right;
|
144 |
}
|
|
|
164 |
}
|
165 |
}
|
166 |
|
167 |
+
.driver-clearfix:before {
|
168 |
+
content: "";
|
169 |
+
display: table;
|
170 |
+
}
|
171 |
+
|
172 |
+
.driver-clearfix:after {
|
173 |
+
clear: both;
|
174 |
+
content: "";
|
175 |
+
display: table;
|
176 |
+
}
|
177 |
+
|
178 |
.driver-stage-no-animation {
|
179 |
-webkit-transition: none !important;
|
180 |
-moz-transition: none !important;
|
src/index.js
CHANGED
@@ -182,13 +182,17 @@ export default class Driver {
|
|
182 |
return;
|
183 |
}
|
184 |
|
185 |
-
//
|
186 |
-
if
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
|
|
|
|
|
|
|
|
192 |
}
|
193 |
}
|
194 |
|
@@ -226,7 +230,7 @@ export default class Driver {
|
|
226 |
|
227 |
// Call the bound `onNext` handler if available
|
228 |
const currentStep = this.steps[this.currentStep];
|
229 |
-
if (currentStep.options.onNext) {
|
230 |
currentStep.options.onNext(this.overlay.highlightedElement);
|
231 |
}
|
232 |
|
@@ -246,7 +250,7 @@ export default class Driver {
|
|
246 |
|
247 |
// Call the bound `onPrevious` handler if available
|
248 |
const currentStep = this.steps[this.currentStep];
|
249 |
-
if (currentStep.options.onPrevious) {
|
250 |
currentStep.options.onPrevious(this.overlay.highlightedElement);
|
251 |
}
|
252 |
|
@@ -357,7 +361,7 @@ export default class Driver {
|
|
357 |
* @private
|
358 |
*/
|
359 |
prepareElementFromStep(currentStep, allSteps = [], index = 0) {
|
360 |
-
let elementOptions = {};
|
361 |
let querySelector = currentStep;
|
362 |
|
363 |
// If the `currentStep` is step definition
|
@@ -388,23 +392,19 @@ export default class Driver {
|
|
388 |
].filter(c => c).join(' ');
|
389 |
|
390 |
const popoverOptions = {
|
391 |
-
...
|
392 |
...elementOptions.popover,
|
393 |
className: mergedClassNames,
|
394 |
totalCount: allSteps.length,
|
395 |
currentIndex: index,
|
396 |
isFirst: index === 0,
|
397 |
-
isLast: index === allSteps.length - 1,
|
398 |
};
|
399 |
|
400 |
popover = new Popover(popoverOptions, this.window, this.document);
|
401 |
}
|
402 |
|
403 |
-
const stageOptions = {
|
404 |
-
...this.options,
|
405 |
-
...elementOptions,
|
406 |
-
};
|
407 |
-
|
408 |
const stage = new Stage(stageOptions, this.window, this.document);
|
409 |
|
410 |
return new Element({
|
|
|
182 |
return;
|
183 |
}
|
184 |
|
185 |
+
// If there is no highlighted element or there is a highlighted element
|
186 |
+
// without popover or if the popover does not allow buttons - ignore
|
187 |
+
const highlightedElement = this.getHighlightedElement();
|
188 |
+
if (!highlightedElement || !highlightedElement.popover || !highlightedElement.popover.options.showButtons) {
|
189 |
+
return;
|
190 |
+
}
|
191 |
+
|
192 |
+
if (event.keyCode === RIGHT_KEY_CODE) {
|
193 |
+
this.handleNext();
|
194 |
+
} else if (event.keyCode === LEFT_KEY_CODE) {
|
195 |
+
this.handlePrevious();
|
196 |
}
|
197 |
}
|
198 |
|
|
|
230 |
|
231 |
// Call the bound `onNext` handler if available
|
232 |
const currentStep = this.steps[this.currentStep];
|
233 |
+
if (currentStep && currentStep.options && currentStep.options.onNext) {
|
234 |
currentStep.options.onNext(this.overlay.highlightedElement);
|
235 |
}
|
236 |
|
|
|
250 |
|
251 |
// Call the bound `onPrevious` handler if available
|
252 |
const currentStep = this.steps[this.currentStep];
|
253 |
+
if (currentStep && currentStep.options && currentStep.options.onPrevious) {
|
254 |
currentStep.options.onPrevious(this.overlay.highlightedElement);
|
255 |
}
|
256 |
|
|
|
361 |
* @private
|
362 |
*/
|
363 |
prepareElementFromStep(currentStep, allSteps = [], index = 0) {
|
364 |
+
let elementOptions = { ...this.options };
|
365 |
let querySelector = currentStep;
|
366 |
|
367 |
// If the `currentStep` is step definition
|
|
|
392 |
].filter(c => c).join(' ');
|
393 |
|
394 |
const popoverOptions = {
|
395 |
+
...elementOptions,
|
396 |
...elementOptions.popover,
|
397 |
className: mergedClassNames,
|
398 |
totalCount: allSteps.length,
|
399 |
currentIndex: index,
|
400 |
isFirst: index === 0,
|
401 |
+
isLast: allSteps.length === 0 || index === allSteps.length - 1, // Only one item or last item
|
402 |
};
|
403 |
|
404 |
popover = new Popover(popoverOptions, this.window, this.document);
|
405 |
}
|
406 |
|
407 |
+
const stageOptions = { ...elementOptions };
|
|
|
|
|
|
|
|
|
408 |
const stage = new Stage(stageOptions, this.window, this.document);
|
409 |
|
410 |
return new Element({
|