У меня есть этот веб-компонент, в котором есть карточки с всплывающими подсказками.
Я пытаюсь выполнить 3 вещи. Я пытаюсь использовать Vanilla Javascript против jQuery или других библиотек.
Показать, когда кнопка нажата, и скрыть, если кнопка нажата снова. В настоящее время это работает.
Скрыть при нажатии за пределами кнопки. Я попытался выбрать документ, а затем сравнить щелкнутый элемент с элементом, на который я хочу настроить таргетинг, но у меня возникли проблемы с таргетингом.
Показывать только 1 всплывающую подсказку за раз, поэтому, если 1 открыта, вы нажимаете другую, отображается только вторая. Не уверен, как подойти к этому.
Вот что у меня есть до сих пор.
class BuildABox extends HTMLElement {
constructor() {
super();
this.querySelectorAll('[data-tooltip]').forEach((button) =>
button.addEventListener('click', this.toggleTooltip.bind(this))
);
}
toggleTooltip(e) {
e.preventDefault();
const toolTip = e.currentTarget.lastChild.previousSibling;
toolTip.classList.toggle('tw-invisible');
}
}
customElements.define('build-a-box', BuildABox);
<button id = "info-btn" aria-label = "Information" type = "button" data-info = "{{ block.settings.product_description }}">
<div data-tooltip = "tooltip" class = "tw-w-12">
<svg xmlns = "http://www.w3.org/2000/svg"
viewBox = "0 0 24 24"
fill = "currentColor"
class = "w-12 h-12"
>
<path fill-rule = "evenodd" d = "M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm8.706-1.442c1.146-.573 2.437.463 2.126 1.706l-.709 2.836.042-.02a.75.75 0 01.67 1.34l-.04.022c-1.147.573-2.438-.463-2.127-1.706l.71-2.836-.042.02a.75.75 0 11-.671-1.34l.041-.022zM12 9a.75.75 0 100-1.5.75.75 0 000 1.5z" clip-rule = "evenodd" />
</svg>
{% comment %} This is tooltip to hide/show {% endcomment %}
<div
id = "tooltip"
class = "tw-invisible z-50 tw-absolute tw-top-24 tw-max-w-[300px] tw-bg-blue-400 tw-text-white tw-border-graphite tw-border-2 tw-overflow-auto tw-rounded-2xl tw-p-4 tw-mt-1"
>
<p>{{ block.settings.product_description }}</p>
</div>
</div>
</button>
Спасибо, Дэнни, я скоро узнаю, как настроить фрагмент.
Вот пример с внешней таблицей стилей: github.com/mdn/web-components-examples/blob/main/… и у этой есть внутренние стили, но она больше похожа на «CSS» (ну, потому что она ЕСТЬ) для кто-то привык к этому: github.com/mdn/web-components-examples/blob/main/…
Спасибо Марк за ресурсы
Разъяснить мои предыдущие комментарии, которые я удалил; Я немного обновил ваш код и добавил немного CSS, чтобы показать его здесь. У меня есть элемент данных, чтобы выбрать цель, а затем использовать ее в обработчике кликов.
class BuildABox extends HTMLElement {
constructor() {
super();
this.querySelectorAll('[data-tooltip-target]').forEach((button) => {
button.addEventListener('click', this.toggleTooltip.bind(this))
});
}
toggleTooltip(e) {
e.preventDefault();
const mytarget = e.currentTarget.dataset.tooltipTarget;
const toolTip = e.currentTarget.querySelector(`[data-tooltip = "${mytarget}"]`);
toolTip.classList.toggle('tw-invisible');
}
}
customElements.define('build-a-box', BuildABox);
.tw-invisible {
display: none;
}
.tooltip-text {
color: blue;
font-size: 1.5rem;
}
<build-a-box>
<button id = "info-btn" aria-label = "Information" type = "button" data-info = "{{ block.settings.product_description }}" data-tooltip-target = "mine">
<div class = "tw-w-12">
<svg xmlns = "http://www.w3.org/2000/svg"
viewBox = "0 0 24 24"
fill = "currentColor"
class = "w-12 h-12"
>
<path fill-rule = "evenodd" d = "M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm8.706-1.442c1.146-.573 2.437.463 2.126 1.706l-.709 2.836.042-.02a.75.75 0 01.67 1.34l-.04.022c-1.147.573-2.438-.463-2.127-1.706l.71-2.836-.042.02a.75.75 0 11-.671-1.34l.041-.022zM12 9a.75.75 0 100-1.5.75.75 0 000 1.5z" clip-rule = "evenodd" />
</svg>
<tool-tip data-tooltip = "mine" class = "tw-invisible">
<span class = "tooltip-text">This is tooltip to hide/show</span>
</tool-tip>
<div class = "z-50 tw-absolute tw-top-24 tw-max-w-[300px] tw-bg-blue-400 tw-text-white tw-border-graphite tw-border-2 tw-overflow-auto tw-rounded-2xl tw-p-4 tw-mt-1">
<p>{{ block.settings.product_description }}</p>
</div>
</div>
</button>
</build-a-box>
Вы не хотите создавать зависимости, поэтому сохраните как можно больше логики внутри веб-компонента.
Здесь используется shadowDOM, потому что он сохраняет размер веб-компонента
и вы можете стилизовать с помощью глобального CSS, используя ::part
Ключевое понятие: <my-button tooltip>
Атрибут tooltip
определяет, виден он или нет.
Я добавил дополнительные стили, чтобы показать больше вариантов стилей.
Для более подробной информации о <slot>
и ::slotted
читайте: ::slotted CSS-селектор для вложенных дочерних элементов в слоте shadowDOM
тот же код в: https://jsfiddle.net/WebComponents/xg3ns6od/
customElements.define('my-button', class extends HTMLElement {
constructor() {
super().attachShadow({mode:"open"}).innerHTML =
`<style>`+
`button{ width:120px; cursor:pointer } ::slotted(div){ pointer-events:none }` +
`[name = "tooltip"]::slotted(div) { color:blue; font-size: 1.2rem }`+
`[name = "label"]::slotted(div) { font-size:1em;font-weight:bold }`+
`:host([tooltip]) svg { fill:green!important } `+
`:host(:hover:not([tooltip])) path{ scale:1.2; transform-origin: center }` +
`:host(:not([tooltip])) [name = "tooltip"]::slotted(div) { visibility:hidden } `+
`</style>`+
`<button part = "button"><svg part = "icon" viewBox = "0 0 2400 2400">`+
`<path fill-rule = "evenodd" d = "m225 1200c0-539 437-975 975-975s975 437 975 975-437 975-975 975-975-436-975-975zm871-144c115-57 244 46 213 171l-71 284 4-2a75 75 90 0167 134l-4 2c-115 57-244-46-213-171l71-284-4 2a75 75 90 11-67-134l4-2zm104-156a75 75 90 100-150 75 75 90 000 150z"/>`+
`</svg><slot name = "tooltip"></slot>`+
`<slot name = "label"></slot></button>`;
}
connectedCallback(){
this.onclick = () => this.tooltip = !this.tooltip;
this.globalListener = document.addEventListener("click",
(evt) => this.tooltip = evt.target == this )
}
get tooltip() { return this.hasAttribute("tooltip") }
set tooltip(val){ this.toggleAttribute("tooltip",val) }
disconnectedCallback(){
document.removeEventListener("click", this.globalListener);
}
});
/* style parts IN shadowDOM */
my-button::part(icon){ fill:red }
/* style lightDOM! */
my-button[tooltip] [slot = "tooltip"] { background:lightgreen }
<my-button>
<div slot = "tooltip">Tooltip 1</div>
<div slot = "label">Product Description</div>
</my-button>
<my-button tooltip>
<div slot = "tooltip">Tooltip 2</div>
<div slot = "label">Product Description</div>
</my-button>
<my-button>
<div slot = "tooltip">Tooltip 3</div>
<div slot = "label">Product Description</div>
</my-button>
Дэнни, большое спасибо, это действительно много значит для меня. Очень элегантное решение. Спасибо за отзыв о веб-компонентах. Я только начинаю с ними, так что это очень полезно.
Пожалуйста, добавьте Минимальный минимально воспроизводимый пример сниппета StackOverflow к своему сообщению. Это поможет читателям выполнить ваш код одним щелчком мыши. И помогите создать ответы одним щелчком мыши. См. Как добавить фрагмент StackOverflow