kamrify commited on
Commit
bdfd65a
·
1 Parent(s): 24dfcae

WIP - Remove canvas and use HTML/CSS

Browse files
index.html CHANGED
@@ -320,9 +320,6 @@ activeElement.getNode(); // Gets the DOM Element behind this element
320
  </div>
321
  </div>
322
 
323
- <div id="driver-page-overlay"></div>
324
- <div id="driver-highlighted-element-stage"></div>
325
-
326
  <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
327
  <script async defer src="//buttons.github.io/buttons.js"></script>
328
  <script src="//twemoji.maxcdn.com/2/twemoji.min.js?2.5"></script>
 
320
  </div>
321
  </div>
322
 
 
 
 
323
  <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
324
  <script async defer src="//buttons.github.io/buttons.js"></script>
325
  <script src="//twemoji.maxcdn.com/2/twemoji.min.js?2.5"></script>
src/common/constants.js CHANGED
@@ -7,9 +7,10 @@ export const ESC_KEY_CODE = 27;
7
  export const LEFT_KEY_CODE = 37;
8
  export const RIGHT_KEY_CODE = 39;
9
 
10
- export const ID_OVERLAY = 'driver-canvas-overlay';
11
-
12
  export const ID_POPOVER = 'driver-popover-item';
 
13
  export const CLASS_POPOVER_TIP = 'driver-popover-tip';
14
  export const CLASS_POPOVER_TITLE = 'driver-popover-title';
15
  export const CLASS_POPOVER_DESCRIPTION = 'driver-popover-description';
@@ -33,3 +34,6 @@ export const POPOVER_HTML = `
33
  </span>
34
  </div>
35
  </div>`;
 
 
 
 
7
  export const LEFT_KEY_CODE = 37;
8
  export const RIGHT_KEY_CODE = 39;
9
 
10
+ export const ID_OVERLAY = 'driver-page-overlay';
11
+ export const ID_STAGE = 'driver-highlighted-element-stage';
12
  export const ID_POPOVER = 'driver-popover-item';
13
+
14
  export const CLASS_POPOVER_TIP = 'driver-popover-tip';
15
  export const CLASS_POPOVER_TITLE = 'driver-popover-title';
16
  export const CLASS_POPOVER_DESCRIPTION = 'driver-popover-description';
 
34
  </span>
35
  </div>
36
  </div>`;
37
+
38
+ export const OVERLAY_HTML = `<div id="${ID_OVERLAY}"></div>`;
39
+ export const STAGE_HTML = `<div id="${ID_STAGE}"></div>`;
src/common/utils.js ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Turn a string into a node
3
+ * @param {String} htmlString to convert
4
+ * @return {Node} Converted node element
5
+ */
6
+ // eslint-disable-next-line
7
+ export const createNodeFromString = (htmlString) => {
8
+ const div = document.createElement('div');
9
+ div.innerHTML = htmlString.trim();
10
+
11
+ // Change this to div.childNodes to support multiple top-level nodes
12
+ return div.firstChild;
13
+ };
src/core/element.js CHANGED
@@ -148,14 +148,6 @@ export default class Element {
148
  }
149
  }
150
 
151
- getSize() {
152
- const boundingRect = this.node.getBoundingClientRect();
153
- return {
154
- width: boundingRect.width,
155
- height: boundingRect.height
156
- };
157
- }
158
-
159
  /**
160
  * Is called when the element is about to be highlighted
161
  * i.e. either if overlay has started moving the highlight towards
@@ -249,4 +241,15 @@ export default class Element {
249
  width: Math.max(body.scrollWidth, body.offsetWidth, html.scrollWidth, html.offsetWidth),
250
  };
251
  }
 
 
 
 
 
 
 
 
 
 
 
252
  }
 
148
  }
149
  }
150
 
 
 
 
 
 
 
 
 
151
  /**
152
  * Is called when the element is about to be highlighted
153
  * i.e. either if overlay has started moving the highlight towards
 
241
  width: Math.max(body.scrollWidth, body.offsetWidth, html.scrollWidth, html.offsetWidth),
242
  };
243
  }
244
+
245
+ /**
246
+ * Gets the size for popover
247
+ * @returns {{height: number, width: number}}
248
+ */
249
+ getSize() {
250
+ return {
251
+ height: Math.max(this.node.scrollHeight, this.node.offsetHeight),
252
+ width: Math.max(this.node.scrollWidth, this.node.offsetWidth),
253
+ };
254
+ }
255
  }
src/core/overlay.js CHANGED
@@ -1,4 +1,6 @@
1
  import Position from './position';
 
 
2
 
3
  /**
4
  * Responsible for overlay creation and manipulation i.e.
@@ -8,9 +10,10 @@ export default class Overlay {
8
  /**
9
  * @param {Object} options
10
  * @param {Window} window
 
11
  * @param {Document} document
12
  */
13
- constructor(options, window, document) {
14
  this.options = options;
15
 
16
  this.positionToHighlight = new Position({}); // position at which layover is to be patched at
@@ -22,18 +25,22 @@ export default class Overlay {
22
 
23
  this.window = window;
24
  this.document = document;
 
25
 
26
- this.resetOverlay();
27
  }
28
 
29
  /**
30
  * Prepares the overlay
31
  */
32
- resetOverlay() {
33
- // @todo: append the elements if not there already
 
 
 
 
34
 
35
- this.pageOverlay = this.document.getElementById('driver-page-overlay');
36
- this.highlightStage = this.document.getElementById('driver-highlighted-element-stage');
37
  }
38
 
39
  /**
@@ -102,8 +109,8 @@ export default class Overlay {
102
  this.highlightedElement = null;
103
  this.lastHighlightedElement = null;
104
 
105
- this.pageOverlay.style.opacity = '0';
106
- this.highlightStage.style.display = 'none';
107
  }
108
 
109
  /**
@@ -116,22 +123,11 @@ export default class Overlay {
116
  return;
117
  }
118
 
119
- // Make it two times the padding because, half will be given on left and half on right
120
- const requiredPadding = this.options.padding * 2;
121
-
122
  // Show the overlay
123
- this.pageOverlay.style.opacity = `${this.options.opacity}`;
124
-
125
- const width = (this.positionToHighlight.right - this.positionToHighlight.left) + (requiredPadding);
126
- const height = (this.positionToHighlight.bottom - this.positionToHighlight.top) + (requiredPadding);
127
 
128
  // Show the stage
129
- this.highlightStage.style.display = 'block';
130
- this.highlightStage.style.position = 'absolute';
131
- this.highlightStage.style.width = `${width}px`;
132
- this.highlightStage.style.height = `${height}px`;
133
- this.highlightStage.style.top = `${this.positionToHighlight.top - (requiredPadding / 2)}px`;
134
- this.highlightStage.style.left = `${this.positionToHighlight.left - (requiredPadding / 2)}px`;
135
 
136
  // Element has been highlighted
137
  this.highlightedElement.onHighlighted();
 
1
  import Position from './position';
2
+ import { ID_OVERLAY, OVERLAY_HTML, POPOVER_HTML } from "../common/constants";
3
+ import { createNodeFromString } from "../common/utils";
4
 
5
  /**
6
  * Responsible for overlay creation and manipulation i.e.
 
10
  /**
11
  * @param {Object} options
12
  * @param {Window} window
13
+ * @param {Stage} stage
14
  * @param {Document} document
15
  */
16
+ constructor(options, stage, window, document) {
17
  this.options = options;
18
 
19
  this.positionToHighlight = new Position({}); // position at which layover is to be patched at
 
25
 
26
  this.window = window;
27
  this.document = document;
28
+ this.stage = stage;
29
 
30
+ this.makeNode();
31
  }
32
 
33
  /**
34
  * Prepares the overlay
35
  */
36
+ makeNode() {
37
+ let pageOverlay = this.document.getElementById(ID_OVERLAY);
38
+ if (!pageOverlay) {
39
+ pageOverlay = createNodeFromString(OVERLAY_HTML);
40
+ document.body.appendChild(pageOverlay);
41
+ }
42
 
43
+ this.node = pageOverlay;
 
44
  }
45
 
46
  /**
 
109
  this.highlightedElement = null;
110
  this.lastHighlightedElement = null;
111
 
112
+ this.node.style.opacity = '0';
113
+ this.stage.hide();
114
  }
115
 
116
  /**
 
123
  return;
124
  }
125
 
 
 
 
126
  // Show the overlay
127
+ this.node.style.opacity = `${this.options.opacity}`;
 
 
 
128
 
129
  // Show the stage
130
+ this.stage.show(this.positionToHighlight);
 
 
 
 
 
131
 
132
  // Element has been highlighted
133
  this.highlightedElement.onHighlighted();
src/core/popover.js CHANGED
@@ -9,6 +9,7 @@ import {
9
  ID_POPOVER,
10
  POPOVER_HTML,
11
  } from '../common/constants';
 
12
 
13
  /**
14
  * Popover that is displayed on top of the highlighted element
@@ -48,10 +49,11 @@ export default class Popover extends Element {
48
  makeNode() {
49
  let popover = this.document.getElementById(ID_POPOVER);
50
  if (!popover) {
51
- popover = Popover.createFromString(POPOVER_HTML);
52
  document.body.appendChild(popover);
53
  }
54
 
 
55
  this.node = popover;
56
  this.tipNode = popover.querySelector(`.${CLASS_POPOVER_TIP}`);
57
  this.titleNode = popover.querySelector(`.${CLASS_POPOVER_TITLE}`);
@@ -62,30 +64,6 @@ export default class Popover extends Element {
62
  this.closeBtnNode = popover.querySelector(`.${CLASS_CLOSE_BTN}`);
63
  }
64
 
65
- /**
66
- * Turn a string into a node
67
- * @param {String} htmlString to convert
68
- * @return {Node} Converted node element
69
- */
70
- static createFromString(htmlString) {
71
- const div = document.createElement('div');
72
- div.innerHTML = htmlString.trim();
73
-
74
- // Change this to div.childNodes to support multiple top-level nodes
75
- return div.firstChild;
76
- }
77
-
78
- /**
79
- * Gets the size for popover
80
- * @returns {{height: number, width: number}}
81
- */
82
- getSize() {
83
- return {
84
- height: Math.max(this.node.scrollHeight, this.node.offsetHeight),
85
- width: Math.max(this.node.scrollWidth, this.node.offsetWidth),
86
- };
87
- }
88
-
89
  hide() {
90
  this.node.style.display = 'none';
91
  }
 
9
  ID_POPOVER,
10
  POPOVER_HTML,
11
  } from '../common/constants';
12
+ import { createNodeFromString } from '../common/utils';
13
 
14
  /**
15
  * Popover that is displayed on top of the highlighted element
 
49
  makeNode() {
50
  let popover = this.document.getElementById(ID_POPOVER);
51
  if (!popover) {
52
+ popover = createNodeFromString(POPOVER_HTML);
53
  document.body.appendChild(popover);
54
  }
55
 
56
+
57
  this.node = popover;
58
  this.tipNode = popover.querySelector(`.${CLASS_POPOVER_TIP}`);
59
  this.titleNode = popover.querySelector(`.${CLASS_POPOVER_TITLE}`);
 
64
  this.closeBtnNode = popover.querySelector(`.${CLASS_CLOSE_BTN}`);
65
  }
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  hide() {
68
  this.node.style.display = 'none';
69
  }
src/core/stage.js ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ID_STAGE, POPOVER_HTML, STAGE_HTML } from '../common/constants';
2
+ import { createNodeFromString } from '../common/utils';
3
+ import Element from './element';
4
+
5
+ /**
6
+ * Stage behind the highlighted element to give it a little
7
+ * highlight from rest of the page
8
+ */
9
+ export default class Stage extends Element {
10
+ /**
11
+ * @param {Object} options
12
+ * @param {Window} window
13
+ * @param {Document} document
14
+ */
15
+ constructor(options, window, document) {
16
+ super();
17
+
18
+ this.options = options;
19
+ this.window = window;
20
+ this.document = document;
21
+
22
+ this.makeNode();
23
+ this.hide();
24
+ }
25
+
26
+ /**
27
+ * Prepares the DOM element if not already there
28
+ */
29
+ makeNode() {
30
+ let stage = this.document.getElementById(ID_STAGE);
31
+ if (!stage) {
32
+ stage = createNodeFromString(STAGE_HTML);
33
+ document.body.appendChild(stage);
34
+ }
35
+
36
+ this.node = stage;
37
+ }
38
+
39
+ /**
40
+ * Simply hides the stage
41
+ */
42
+ hide() {
43
+ this.node.style.display = 'none';
44
+ }
45
+
46
+ /**
47
+ * Makes it visible and sets the default properties
48
+ */
49
+ reset() {
50
+ this.node.style.display = 'block';
51
+ this.node.style.left = '0';
52
+ this.node.style.top = '0';
53
+ this.node.style.bottom = '';
54
+ this.node.style.right = '';
55
+ }
56
+
57
+ show(position) {
58
+ this.reset();
59
+
60
+ // Make it two times the padding because, half will be given on left and half on right
61
+ const requiredPadding = this.options.padding * 2;
62
+
63
+ const width = (position.right - position.left) + (requiredPadding);
64
+ const height = (position.bottom - position.top) + (requiredPadding);
65
+
66
+ // Show the stage
67
+ this.node.style.display = 'block';
68
+ this.node.style.position = 'absolute';
69
+ this.node.style.width = `${width}px`;
70
+ this.node.style.height = `${height}px`;
71
+ this.node.style.top = `${position.top - (requiredPadding / 2)}px`;
72
+ this.node.style.left = `${position.left - (requiredPadding / 2)}px`;
73
+ }
74
+ }
75
+
src/index.js CHANGED
@@ -14,6 +14,7 @@ import {
14
  OVERLAY_PADDING,
15
  RIGHT_KEY_CODE,
16
  } from './common/constants';
 
17
 
18
  /**
19
  * Plugin class that drives the plugin
@@ -38,13 +39,13 @@ export default class Driver {
38
 
39
  this.document = document;
40
  this.window = window;
41
-
42
  this.isActivated = false;
43
- this.overlay = new Overlay(this.options, this.window, this.document);
44
-
45
  this.steps = []; // steps to be presented if any
46
  this.currentStep = 0; // index for the currently highlighted step
47
 
 
 
 
48
  this.onResize = this.onResize.bind(this);
49
  this.onKeyUp = this.onKeyUp.bind(this);
50
  this.onClick = this.onClick.bind(this);
@@ -242,11 +243,16 @@ export default class Driver {
242
  let querySelector = '';
243
  let elementOptions = {};
244
 
 
245
  if (typeof currentStep === 'string') {
246
  querySelector = currentStep;
247
  } else {
248
  querySelector = currentStep.element;
249
- elementOptions = Object.assign({}, this.options, currentStep);
 
 
 
 
250
  }
251
 
252
  const domElement = this.document.querySelector(querySelector);
@@ -260,7 +266,8 @@ export default class Driver {
260
  const popoverOptions = Object.assign(
261
  {},
262
  this.options,
263
- elementOptions.popover, {
 
264
  totalCount: allSteps.length,
265
  currentIndex: index,
266
  isFirst: index === 0,
 
14
  OVERLAY_PADDING,
15
  RIGHT_KEY_CODE,
16
  } from './common/constants';
17
+ import Stage from './core/stage';
18
 
19
  /**
20
  * Plugin class that drives the plugin
 
39
 
40
  this.document = document;
41
  this.window = window;
 
42
  this.isActivated = false;
 
 
43
  this.steps = []; // steps to be presented if any
44
  this.currentStep = 0; // index for the currently highlighted step
45
 
46
+ const stage = new Stage(this.options, window, document);
47
+ this.overlay = new Overlay(this.options, stage, window, document);
48
+
49
  this.onResize = this.onResize.bind(this);
50
  this.onKeyUp = this.onKeyUp.bind(this);
51
  this.onClick = this.onClick.bind(this);
 
243
  let querySelector = '';
244
  let elementOptions = {};
245
 
246
+ // If it is just a query selector string
247
  if (typeof currentStep === 'string') {
248
  querySelector = currentStep;
249
  } else {
250
  querySelector = currentStep.element;
251
+ elementOptions = Object.assign(
252
+ {},
253
+ this.options,
254
+ currentStep,
255
+ );
256
  }
257
 
258
  const domElement = this.document.querySelector(querySelector);
 
266
  const popoverOptions = Object.assign(
267
  {},
268
  this.options,
269
+ elementOptions.popover,
270
+ {
271
  totalCount: allSteps.length,
272
  currentIndex: index,
273
  isFirst: index === 0,