From fa4fbb8369d722fde412de1a125981e12531fb95 Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Sat, 10 Mar 2018 16:20:54 +0100 Subject: [PATCH] Positioning the popover by giving position --- assets/scripts/src/popover.js | 136 ++++++++++++++++++++++++++++------ index.html | 14 +++- 2 files changed, 124 insertions(+), 26 deletions(-) diff --git a/assets/scripts/src/popover.js b/assets/scripts/src/popover.js index 05fbd87..795f312 100644 --- a/assets/scripts/src/popover.js +++ b/assets/scripts/src/popover.js @@ -21,20 +21,21 @@ export default class Popover extends Element { this.window = window; this.document = document; - this.node = this.makeNode(); + this.makeNode(); this.hide(); } makeNode() { let popover = this.document.getElementById(ID_POPOVER); - if (popover) { - return popover; + if (!popover) { + popover = Popover.createFromString(POPOVER_HTML); + document.body.appendChild(popover); } - popover = Popover.createFromString(POPOVER_HTML); - document.body.appendChild(popover); - - return popover; + this.node = popover; + this.tipNode = popover.querySelector(`.${CLASS_POPOVER_TIP}`); + this.titleNode = popover.querySelector(`.${CLASS_POPOVER_TITLE}`); + this.descriptionNode = popover.querySelector(`.${CLASS_POPOVER_DESCRIPTION}`); } /** @@ -50,8 +51,11 @@ export default class Popover extends Element { return div.firstChild; } - getHeight() { - return Math.max(this.node.scrollHeight, this.node.offsetHeight); + getSize() { + return { + height: Math.max(this.node.scrollHeight, this.node.offsetHeight), + width: Math.max(this.node.scrollWidth, this.node.offsetWidth), + }; } hide() { @@ -74,29 +78,113 @@ export default class Popover extends Element { show(position) { this.reset(); - const popoverTip = this.node.querySelector(`.${CLASS_POPOVER_TIP}`); - const popoverTitle = this.node.querySelector(`.${CLASS_POPOVER_TITLE}`); - const popoverDescription = this.node.querySelector(`.${CLASS_POPOVER_DESCRIPTION}`); + // Set the title and descriptions + this.titleNode.innerText = this.options.title; + this.descriptionNode.innerText = this.options.description; + + // Position the popover around the given position + switch (this.options.position) { + case 'left': + this.positionOnLeft(position); + break; + case 'right': + this.positionOnRight(position); + break; + case 'top': + this.positionOnTop(position); + break; + case 'bottom': + this.positionOnBottom(position); + break; + case 'auto': + default: + this.autoPosition(position); + break; + } + } + + /** + * Shows the popover on the left of the given position + * @param elementPosition + */ + positionOnLeft(elementPosition) { + const popoverWidth = this.getSize().width; + const popoverMargin = this.options.padding + 10; // adding 10 to give it a little distance from the element + + this.node.style.left = `${elementPosition.left - popoverWidth - popoverMargin}px`; + this.node.style.top = `${elementPosition.top - this.options.padding}px`; + this.node.style.right = ''; + this.node.style.bottom = ''; + + this.tipNode.classList.add('right'); + } + + /** + * Shows the popover on the right of the given position + * @param elementPosition + */ + positionOnRight(elementPosition) { + const popoverMargin = this.options.padding + 10; // adding 10 to give it a little distance from the element + + this.node.style.left = `${elementPosition.right + popoverMargin}px`; + this.node.style.top = `${elementPosition.top - this.options.padding}px`; + this.node.style.right = ''; + this.node.style.bottom = ''; + + this.tipNode.classList.add('left'); + } + + /** + * Shows the popover on the top of the given position + * @param elementPosition + */ + positionOnTop(elementPosition) { + const popoverHeight = this.getSize().height; + const popoverMargin = this.options.padding + 10; // adding 10 to give it a little distance from the element + + this.node.style.top = `${elementPosition.top - popoverHeight - popoverMargin}px`; + this.node.style.left = `${elementPosition.left - this.options.padding}px`; + this.node.style.right = ''; + this.node.style.bottom = ''; + + this.tipNode.classList.add('bottom'); + } - popoverTitle.innerText = this.options.title; - popoverDescription.innerText = this.options.description; + /** + * Shows the popover on the bottom of the given position + * @param elementPosition + */ + positionOnBottom(elementPosition) { + const popoverMargin = this.options.padding + 10; // adding 10 to give it a little distance from the element + + this.node.style.top = `${elementPosition.bottom + popoverMargin}px`; + this.node.style.left = `${elementPosition.left - this.options.padding}px`; + this.node.style.right = ''; + this.node.style.bottom = ''; - const pageHeight = this.getFullPageSize().height; - const popoverMargin = this.options.padding + 10; - const popoverHeight = this.getHeight(); + this.tipNode.classList.add('top'); + } + + /** + * Automatically positions the popover around the given position + * such that the element and popover remain in view + * @param elementPosition + */ + autoPosition(elementPosition) { + const pageSize = this.getFullPageSize(); + const popoverSize = this.getSize(); - this.node.style.left = `${position.left - this.options.padding}px`; + const pageHeight = pageSize.height; + const popoverHeight = popoverSize.height; + const popoverMargin = this.options.padding + 10; // adding 10 to give it a little distance from the element - // Calculate different dimensions after attaching popover - const pageHeightAfterPopOver = position.bottom + popoverHeight + popoverMargin; + const pageHeightAfterPopOver = elementPosition.bottom + popoverHeight + popoverMargin; // If adding popover would go out of the window height, then show it to the top if (pageHeightAfterPopOver >= pageHeight) { - this.node.style.top = `${position.top - popoverHeight - popoverMargin}px`; - popoverTip.classList.add('bottom'); + this.positionOnTop(elementPosition); } else { - this.node.style.top = `${position.bottom + popoverMargin}px`; - popoverTip.classList.add('top'); + this.positionOnBottom(elementPosition); } } } diff --git a/index.html b/index.html index ba179cc..fff3be8 100644 --- a/index.html +++ b/index.html @@ -68,24 +68,34 @@ element: '.section__header', popover: { title: 'Adding Introductions', - description: 'You can use it to add popovers on top of the website' + description: 'You can use it to add popovers on top of the website', + position: 'left' }, }, { element: '.section__how', popover: { title: 'Just Specify the Item', - description: 'All you have to do is provide the query selector of element to highlight' + description: 'All you have to do is provide the query selector of element to highlight', + position: 'right' }, }, { element: '.section__purpose', + popover: { + title: 'Automatically Position', + description: 'It can automatically position too if you dont provide' + } }, { element: '.section__examples', }, { element: '.section__contributing', + popover: { + title: 'Automatically Position', + description: 'It can automatically position too if you dont provide' + } }, ]); -- GitLab