diff --git a/app/assets/javascripts/admin/components/admin-report.js.es6 b/app/assets/javascripts/admin/components/admin-report.js.es6 index d1c186effec..c7f03112084 100644 --- a/app/assets/javascripts/admin/components/admin-report.js.es6 +++ b/app/assets/javascripts/admin/components/admin-report.js.es6 @@ -4,10 +4,6 @@ import { exportEntity } from "discourse/lib/export-csv"; import { outputExportResult } from "discourse/lib/export-result"; import { SCHEMA_VERSION, default as Report } from "admin/models/report"; import computed from "ember-addons/ember-computed-decorators"; -import { - registerHoverTooltip, - unregisterHoverTooltip -} from "discourse/lib/tooltip"; const TABLE_OPTIONS = { perPage: 8, @@ -102,18 +98,6 @@ export default Ember.Component.extend({ } }, - didRender() { - this._super(...arguments); - - registerHoverTooltip($(".info[data-tooltip]")); - }, - - willDestroyElement() { - this._super(...arguments); - - unregisterHoverTooltip($(".info[data-tooltip]")); - }, - showError: Ember.computed.or( "showTimeoutError", "showExceptionError", diff --git a/app/assets/javascripts/discourse/initializers/d-popover.js.es6 b/app/assets/javascripts/discourse/initializers/d-popover.js.es6 new file mode 100644 index 00000000000..0fae353b8b2 --- /dev/null +++ b/app/assets/javascripts/discourse/initializers/d-popover.js.es6 @@ -0,0 +1,18 @@ +import { showPopover, hidePopover } from "discourse/lib/d-popover"; + +const SELECTORS = + "[data-html-popover],[data-tooltip],[data-popover],[data-html-tooltip]"; + +export default { + name: "d-popover", + + initialize() { + $("#main").on("click.d-popover mouseenter.d-popover", SELECTORS, event => + showPopover(event) + ); + + $("#main").on("mouseleave.d-popover", SELECTORS, event => + hidePopover(event) + ); + } +}; diff --git a/app/assets/javascripts/discourse/lib/d-popover.js.es6 b/app/assets/javascripts/discourse/lib/d-popover.js.es6 new file mode 100644 index 00000000000..a1a70761f09 --- /dev/null +++ b/app/assets/javascripts/discourse/lib/d-popover.js.es6 @@ -0,0 +1,173 @@ +import { siteDir } from "discourse/lib/text-direction"; + +const D_POPOVER_ID = "d-popover"; + +const D_POPOVER_TEMPLATE = ` +
+
+
+
+
+
+
+`; + +const D_ARROW_HEIGHT = 10; + +const D_HORIZONTAL_MARGIN = 5; + +export function hidePopover() { + getPopover() + .fadeOut() + .remove(); + + return getPopover(); +} + +export function showPopover(event, options = {}) { + const $enteredElement = $(event.currentTarget); + + if (isRetina()) { + getPopover().addClass("retina"); + } + + if (!getPopover().length) { + $("body").append($(D_POPOVER_TEMPLATE)); + } + + setPopoverHtmlContent($enteredElement, options.htmlContent); + setPopoverTextContent($enteredElement, options.textContent); + + getPopover().fadeIn(); + + positionPopover($enteredElement); + + return { + html: content => replaceHtmlContent($enteredElement, content), + text: content => replaceTextContent($enteredElement, content), + hide: hidePopover + }; +} + +function setPopoverHtmlContent($enteredElement, content) { + content = + content || + $enteredElement.attr("data-html-popover") || + $enteredElement.attr("data-html-tooltip"); + + replaceHtmlContent($enteredElement, content); +} + +function setPopoverTextContent($enteredElement, content) { + content = + content || + $enteredElement.attr("data-popover") || + $enteredElement.attr("data-tooltip"); + + replaceTextContent($enteredElement, content); +} + +function replaceTextContent($enteredElement, content) { + if (content) { + getPopover() + .find(".d-popover-content") + .text(content); + window.requestAnimationFrame(() => positionPopover($enteredElement)); + } +} + +function replaceHtmlContent($enteredElement, content) { + if (content) { + getPopover() + .find(".d-popover-content") + .html(content); + window.requestAnimationFrame(() => positionPopover($enteredElement)); + } +} + +function positionPopover($element) { + const $popover = getPopover(); + $popover.removeClass("is-above is-under is-left-aligned is-right-aligned"); + + const $dHeader = $(".d-header"); + const windowRect = { + left: 0, + top: $dHeader.length ? $dHeader[0].getBoundingClientRect().bottom : 0, + width: $(window).width(), + height: $(window).height() + }; + + const popoverRect = { + width: $popover.width(), + height: $popover.height(), + left: null, + right: null + }; + + if (popoverRect.width > windowRect.width - D_HORIZONTAL_MARGIN * 2) { + popoverRect.width = windowRect.width - D_HORIZONTAL_MARGIN * 2; + $popover.width(popoverRect.width); + } + + const targetRect = $element[0].getBoundingClientRect(); + const underSpace = windowRect.height - targetRect.bottom - D_ARROW_HEIGHT; + const topSpace = targetRect.top - windowRect.top - D_ARROW_HEIGHT; + + if ( + underSpace > popoverRect.height + D_HORIZONTAL_MARGIN || + underSpace > topSpace + ) { + $popover + .css("top", targetRect.bottom + window.pageYOffset + D_ARROW_HEIGHT) + .addClass("is-under"); + } else { + $popover + .css( + "top", + targetRect.top + + window.pageYOffset - + popoverRect.height - + D_ARROW_HEIGHT + ) + .addClass("is-above"); + } + + const leftSpace = targetRect.left + targetRect.width / 2; + + if (siteDir() === "ltr") { + if (leftSpace > popoverRect.width / 2 + D_HORIZONTAL_MARGIN) { + popoverRect.left = leftSpace - popoverRect.width / 2; + $popover.css("left", popoverRect.left); + } else { + popoverRect.left = D_HORIZONTAL_MARGIN; + $popover.css("left", popoverRect.left).addClass("is-left-aligned"); + } + } else { + const rightSpace = windowRect.width - targetRect.right; + + if (rightSpace > popoverRect.width / 2 + D_HORIZONTAL_MARGIN) { + popoverRect.left = leftSpace - popoverRect.width / 2; + $popover.css("left", popoverRect.left); + } else { + popoverRect.left = + windowRect.width - popoverRect.width - D_HORIZONTAL_MARGIN * 2; + $popover.css("left", popoverRect.left).addClass("is-right-aligned"); + } + } + + let arrowPosition; + if (siteDir() === "ltr") { + arrowPosition = Math.abs(targetRect.left - popoverRect.left); + } else { + arrowPosition = targetRect.left - popoverRect.left + targetRect.width / 2; + } + $popover.find(".d-popover-arrow").css("left", arrowPosition); +} + +function isRetina() { + return window.devicePixelRatio && window.devicePixelRatio > 1; +} + +function getPopover() { + return $(document.getElementById(D_POPOVER_ID)); +} diff --git a/app/assets/javascripts/discourse/lib/tooltip.js.es6 b/app/assets/javascripts/discourse/lib/tooltip.js.es6 index ecf93d8c0ca..852451bf31d 100644 --- a/app/assets/javascripts/discourse/lib/tooltip.js.es6 +++ b/app/assets/javascripts/discourse/lib/tooltip.js.es6 @@ -1,3 +1,4 @@ +import deprecated from "discourse-common/lib/deprecated"; import { escapeExpression } from "discourse/lib/utilities"; const fadeSpeed = 300; @@ -77,12 +78,16 @@ export function hideTooltip() { } export function registerTooltip(jqueryContext) { + deprecated("tooltip is getting deprecated. Use d-popover instead"); + if (jqueryContext.length) { jqueryContext.off("click").on("click", event => showTooltip(event)); } } export function registerHoverTooltip(jqueryContext) { + deprecated("tooltip is getting deprecated. Use d-popover instead"); + if (jqueryContext.length) { jqueryContext .off("mouseenter mouseleave click") diff --git a/app/assets/stylesheets/common/base/d-popover.scss b/app/assets/stylesheets/common/base/d-popover.scss new file mode 100644 index 00000000000..c6e90d1b3d1 --- /dev/null +++ b/app/assets/stylesheets/common/base/d-popover.scss @@ -0,0 +1,114 @@ +$d-popover-background: $secondary; +$d-popover-border: $primary-medium; + +@-webkit-keyframes popoverFadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes popoverFadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +#d-popover { + background-color: $d-popover-background; + position: absolute; + z-index: z("tooltip"); + border-color: $d-popover-border; + border-style: solid; + border-width: 1px; + max-width: 300px; + -webkit-animation: popoverFadeIn 0.5s; + animation: popoverFadeIn 0.5s; + background-clip: padding-box; + display: block; + box-shadow: shadow("dropdown"); + border-radius: 2px; + + &.is-under { + margin-top: 0px; + + .d-popover-top-arrow { + display: block; + } + + .d-popover-bottom-arrow { + display: none; + } + } + + &.is-above { + margin-top: 0px; + + .d-popover-bottom-arrow { + display: block; + } + + .d-popover-top-arrow { + display: none; + } + } + + &.retina { + border-width: 0.5px; + } + + .d-popover-content { + padding: 1em; + font-size: $font-down-1; + overflow-wrap: break-word; + -webkit-animation: popoverFadeIn 0.5s; + animation: popoverFadeIn 0.5s; + } + + .d-popover-arrow { + border-style: solid; + color: transparent; + content: ""; + position: absolute; + z-index: calc(z("tooltip") - 100); + } + + .d-popover-top-arrow { + border-color: transparent transparent $d-popover-border; + top: 8px; + transform: translate(0, -15px); + border-width: 0 8px 8px; + + &:after { + border-color: transparent transparent $d-popover-background; + border-style: solid; + border-width: 0 7px 7px; + bottom: -8px; + margin-left: -7px; + position: absolute; + content: ""; + } + } + + .d-popover-bottom-arrow { + border-color: $d-popover-border transparent transparent; + top: calc(100% + 16px); + transform: translate(0, -16px); + border-width: 8px 8px 0; + + &:after { + position: absolute; + content: ""; + border-color: $d-popover-background transparent transparent; + border-style: solid; + border-width: 7px 7px 0; + bottom: 2px; + transform: translate(-7px, 0); + } + } +} diff --git a/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js.es6 b/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js.es6 index 87780f6c392..14a9cab3b2e 100644 --- a/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js.es6 +++ b/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js.es6 @@ -1,11 +1,9 @@ import { withPluginApi } from "discourse/lib/plugin-api"; import showModal from "discourse/lib/show-modal"; -import { registerTooltip } from "discourse/lib/tooltip"; function initializeDiscourseLocalDates(api) { api.decorateCooked($elem => { $(".discourse-local-date", $elem).applyLocalDates(); - registerTooltip($(".discourse-local-date", $elem)); }); api.addToolbarPopupMenuOptionsCallback(() => {