提交 c647bb68 编写于 作者: K Kamran Ahmed

WIP - Remove canvas and use HTML/CSS

上级 b3642596
......@@ -320,9 +320,6 @@ activeElement.getNode(); // Gets the DOM Element behind this element
</div>
</div>
<div id="driver-page-overlay"></div>
<div id="driver-highlighted-element-stage"></div>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<script async defer src="//buttons.github.io/buttons.js"></script>
<script src="//twemoji.maxcdn.com/2/twemoji.min.js?2.5"></script>
......
......@@ -7,9 +7,10 @@ export const ESC_KEY_CODE = 27;
export const LEFT_KEY_CODE = 37;
export const RIGHT_KEY_CODE = 39;
export const ID_OVERLAY = 'driver-canvas-overlay';
export const ID_OVERLAY = 'driver-page-overlay';
export const ID_STAGE = 'driver-highlighted-element-stage';
export const ID_POPOVER = 'driver-popover-item';
export const CLASS_POPOVER_TIP = 'driver-popover-tip';
export const CLASS_POPOVER_TITLE = 'driver-popover-title';
export const CLASS_POPOVER_DESCRIPTION = 'driver-popover-description';
......@@ -33,3 +34,6 @@ export const POPOVER_HTML = `
</span>
</div>
</div>`;
export const OVERLAY_HTML = `<div id="${ID_OVERLAY}"></div>`;
export const STAGE_HTML = `<div id="${ID_STAGE}"></div>`;
\ No newline at end of file
/**
* Turn a string into a node
* @param {String} htmlString to convert
* @return {Node} Converted node element
*/
// eslint-disable-next-line
export const createNodeFromString = (htmlString) => {
const div = document.createElement('div');
div.innerHTML = htmlString.trim();
// Change this to div.childNodes to support multiple top-level nodes
return div.firstChild;
};
......@@ -148,14 +148,6 @@ export default class Element {
}
}
getSize() {
const boundingRect = this.node.getBoundingClientRect();
return {
width: boundingRect.width,
height: boundingRect.height
};
}
/**
* Is called when the element is about to be highlighted
* i.e. either if overlay has started moving the highlight towards
......@@ -249,4 +241,15 @@ export default class Element {
width: Math.max(body.scrollWidth, body.offsetWidth, html.scrollWidth, html.offsetWidth),
};
}
/**
* Gets the size for popover
* @returns {{height: number, width: number}}
*/
getSize() {
return {
height: Math.max(this.node.scrollHeight, this.node.offsetHeight),
width: Math.max(this.node.scrollWidth, this.node.offsetWidth),
};
}
}
import Position from './position';
import { ID_OVERLAY, OVERLAY_HTML, POPOVER_HTML } from "../common/constants";
import { createNodeFromString } from "../common/utils";
/**
* Responsible for overlay creation and manipulation i.e.
......@@ -8,9 +10,10 @@ export default class Overlay {
/**
* @param {Object} options
* @param {Window} window
* @param {Stage} stage
* @param {Document} document
*/
constructor(options, window, document) {
constructor(options, stage, window, document) {
this.options = options;
this.positionToHighlight = new Position({}); // position at which layover is to be patched at
......@@ -22,18 +25,22 @@ export default class Overlay {
this.window = window;
this.document = document;
this.stage = stage;
this.resetOverlay();
this.makeNode();
}
/**
* Prepares the overlay
*/
resetOverlay() {
// @todo: append the elements if not there already
makeNode() {
let pageOverlay = this.document.getElementById(ID_OVERLAY);
if (!pageOverlay) {
pageOverlay = createNodeFromString(OVERLAY_HTML);
document.body.appendChild(pageOverlay);
}
this.pageOverlay = this.document.getElementById('driver-page-overlay');
this.highlightStage = this.document.getElementById('driver-highlighted-element-stage');
this.node = pageOverlay;
}
/**
......@@ -102,8 +109,8 @@ export default class Overlay {
this.highlightedElement = null;
this.lastHighlightedElement = null;
this.pageOverlay.style.opacity = '0';
this.highlightStage.style.display = 'none';
this.node.style.opacity = '0';
this.stage.hide();
}
/**
......@@ -116,22 +123,11 @@ export default class Overlay {
return;
}
// Make it two times the padding because, half will be given on left and half on right
const requiredPadding = this.options.padding * 2;
// Show the overlay
this.pageOverlay.style.opacity = `${this.options.opacity}`;
const width = (this.positionToHighlight.right - this.positionToHighlight.left) + (requiredPadding);
const height = (this.positionToHighlight.bottom - this.positionToHighlight.top) + (requiredPadding);
this.node.style.opacity = `${this.options.opacity}`;
// Show the stage
this.highlightStage.style.display = 'block';
this.highlightStage.style.position = 'absolute';
this.highlightStage.style.width = `${width}px`;
this.highlightStage.style.height = `${height}px`;
this.highlightStage.style.top = `${this.positionToHighlight.top - (requiredPadding / 2)}px`;
this.highlightStage.style.left = `${this.positionToHighlight.left - (requiredPadding / 2)}px`;
this.stage.show(this.positionToHighlight);
// Element has been highlighted
this.highlightedElement.onHighlighted();
......
......@@ -9,6 +9,7 @@ import {
ID_POPOVER,
POPOVER_HTML,
} from '../common/constants';
import { createNodeFromString } from '../common/utils';
/**
* Popover that is displayed on top of the highlighted element
......@@ -48,10 +49,11 @@ export default class Popover extends Element {
makeNode() {
let popover = this.document.getElementById(ID_POPOVER);
if (!popover) {
popover = Popover.createFromString(POPOVER_HTML);
popover = createNodeFromString(POPOVER_HTML);
document.body.appendChild(popover);
}
this.node = popover;
this.tipNode = popover.querySelector(`.${CLASS_POPOVER_TIP}`);
this.titleNode = popover.querySelector(`.${CLASS_POPOVER_TITLE}`);
......@@ -62,30 +64,6 @@ export default class Popover extends Element {
this.closeBtnNode = popover.querySelector(`.${CLASS_CLOSE_BTN}`);
}
/**
* Turn a string into a node
* @param {String} htmlString to convert
* @return {Node} Converted node element
*/
static createFromString(htmlString) {
const div = document.createElement('div');
div.innerHTML = htmlString.trim();
// Change this to div.childNodes to support multiple top-level nodes
return div.firstChild;
}
/**
* Gets the size for popover
* @returns {{height: number, width: number}}
*/
getSize() {
return {
height: Math.max(this.node.scrollHeight, this.node.offsetHeight),
width: Math.max(this.node.scrollWidth, this.node.offsetWidth),
};
}
hide() {
this.node.style.display = 'none';
}
......
import { ID_STAGE, POPOVER_HTML, STAGE_HTML } from '../common/constants';
import { createNodeFromString } from '../common/utils';
import Element from './element';
/**
* Stage behind the highlighted element to give it a little
* highlight from rest of the page
*/
export default class Stage extends Element {
/**
* @param {Object} options
* @param {Window} window
* @param {Document} document
*/
constructor(options, window, document) {
super();
this.options = options;
this.window = window;
this.document = document;
this.makeNode();
this.hide();
}
/**
* Prepares the DOM element if not already there
*/
makeNode() {
let stage = this.document.getElementById(ID_STAGE);
if (!stage) {
stage = createNodeFromString(STAGE_HTML);
document.body.appendChild(stage);
}
this.node = stage;
}
/**
* Simply hides the stage
*/
hide() {
this.node.style.display = 'none';
}
/**
* Makes it visible and sets the default properties
*/
reset() {
this.node.style.display = 'block';
this.node.style.left = '0';
this.node.style.top = '0';
this.node.style.bottom = '';
this.node.style.right = '';
}
show(position) {
this.reset();
// Make it two times the padding because, half will be given on left and half on right
const requiredPadding = this.options.padding * 2;
const width = (position.right - position.left) + (requiredPadding);
const height = (position.bottom - position.top) + (requiredPadding);
// Show the stage
this.node.style.display = 'block';
this.node.style.position = 'absolute';
this.node.style.width = `${width}px`;
this.node.style.height = `${height}px`;
this.node.style.top = `${position.top - (requiredPadding / 2)}px`;
this.node.style.left = `${position.left - (requiredPadding / 2)}px`;
}
}
......@@ -14,6 +14,7 @@ import {
OVERLAY_PADDING,
RIGHT_KEY_CODE,
} from './common/constants';
import Stage from './core/stage';
/**
* Plugin class that drives the plugin
......@@ -38,13 +39,13 @@ export default class Driver {
this.document = document;
this.window = window;
this.isActivated = false;
this.overlay = new Overlay(this.options, this.window, this.document);
this.steps = []; // steps to be presented if any
this.currentStep = 0; // index for the currently highlighted step
const stage = new Stage(this.options, window, document);
this.overlay = new Overlay(this.options, stage, window, document);
this.onResize = this.onResize.bind(this);
this.onKeyUp = this.onKeyUp.bind(this);
this.onClick = this.onClick.bind(this);
......@@ -242,11 +243,16 @@ export default class Driver {
let querySelector = '';
let elementOptions = {};
// If it is just a query selector string
if (typeof currentStep === 'string') {
querySelector = currentStep;
} else {
querySelector = currentStep.element;
elementOptions = Object.assign({}, this.options, currentStep);
elementOptions = Object.assign(
{},
this.options,
currentStep,
);
}
const domElement = this.document.querySelector(querySelector);
......@@ -260,7 +266,8 @@ export default class Driver {
const popoverOptions = Object.assign(
{},
this.options,
elementOptions.popover, {
elementOptions.popover,
{
totalCount: allSteps.length,
currentIndex: index,
isFirst: index === 0,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册