mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-11 00:20:54 +00:00
4.20.21
* Added: Display rich tool-tips for channel panels. * Fixed: Hide Unfollow button in theater mode with the appropriate setting. (Closes #860) * Fixed: Automatically open Theater Mode not working when the channel is window is not visible. (Closes #861) * Fixed: Game titles not appearing in clip embeds. * Fixed: Featured Follow metadata failing when trying to open the menu. * Debug Added: Setting to choose the link resolver. * Debug Added: Test UI for working on link resolvers.
This commit is contained in:
parent
05e8428a4a
commit
eec65551fb
14 changed files with 519 additions and 86 deletions
|
@ -6,13 +6,12 @@ import {ALLOWED_ATTRIBUTES, ALLOWED_TAGS} from 'utilities/constants';
|
|||
const ERROR_IMAGE = 'https://static-cdn.jtvnw.net/emoticons/v1/58765/2.0';
|
||||
|
||||
export default {
|
||||
props: ['data', 'url'],
|
||||
props: ['data', 'url', 'events'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
loaded: false,
|
||||
error: false,
|
||||
html: null,
|
||||
error: null,
|
||||
title: this.t('card.loading', 'Loading...'),
|
||||
title_tokens: null,
|
||||
desc_1: null,
|
||||
|
@ -26,58 +25,96 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
async mounted() {
|
||||
let data;
|
||||
try {
|
||||
data = this.data.getData();
|
||||
if ( data instanceof Promise ) {
|
||||
const to_wait = has(this.data, 'timeout') ? this.data.timeout : 1000;
|
||||
if ( to_wait )
|
||||
data = await timeout(data, to_wait);
|
||||
else
|
||||
data = await data;
|
||||
}
|
||||
watch: {
|
||||
data() {
|
||||
this.reset();
|
||||
this.load();
|
||||
}
|
||||
},
|
||||
|
||||
if ( ! data )
|
||||
data = {
|
||||
error: true,
|
||||
title: this.t('card.error', 'An error occured.'),
|
||||
desc_1: this.t('card.empty', 'No data was returned.')
|
||||
}
|
||||
} catch(err) {
|
||||
data = {
|
||||
error: true,
|
||||
title: this.t('card.error', 'An error occured.'),
|
||||
desc_1: String(err)
|
||||
}
|
||||
created() {
|
||||
if ( this.events ) {
|
||||
this._events = this.events;
|
||||
this._events.on('chat:update-link-resolver', this.checkRefresh, this);
|
||||
}
|
||||
|
||||
this.loaded = true;
|
||||
this.error = data.error;
|
||||
this.html = data.html;
|
||||
this.title = data.title;
|
||||
this.title_tokens = data.title_tokens;
|
||||
this.desc_1 = data.desc_1;
|
||||
this.desc_1_tokens = data.desc_1_tokens;
|
||||
this.desc_2 = data.desc_2;
|
||||
this.desc_2_tokens = data.desc_2_tokens;
|
||||
this.image = data.image;
|
||||
this.image_square = data.image_square;
|
||||
this.image_title = data.image_title;
|
||||
this.load();
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
if ( this._events ) {
|
||||
this._events.off('chat:update-link-resolver', this.checkRefresh, this);
|
||||
this._events = null;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
checkRefresh(url) {
|
||||
if ( ! url || (url && url === this.url) ) {
|
||||
this.reset();
|
||||
this.load();
|
||||
}
|
||||
},
|
||||
|
||||
reset() {
|
||||
this.loaded = false;
|
||||
this.error = null;
|
||||
this.title = this.t('card.loading', 'Loading...');
|
||||
this.title_tokens = null;
|
||||
this.desc_1 = null;
|
||||
this.desc_1_tokens = null;
|
||||
this.desc_2 = null;
|
||||
this.desc_2_tokens = null;
|
||||
this.image = null;
|
||||
this.image_title = null;
|
||||
this.image_square = null;
|
||||
this.accent = null;
|
||||
},
|
||||
|
||||
async load() {
|
||||
let data;
|
||||
try {
|
||||
data = this.data.getData();
|
||||
if ( data instanceof Promise ) {
|
||||
const to_wait = has(this.data, 'timeout') ? this.data.timeout : 1000;
|
||||
if ( to_wait )
|
||||
data = await timeout(data, to_wait);
|
||||
else
|
||||
data = await data;
|
||||
}
|
||||
|
||||
if ( ! data )
|
||||
data = {
|
||||
error: true,
|
||||
title: this.t('card.error', 'An error occured.'),
|
||||
desc_1: this.t('card.empty', 'No data was returned.')
|
||||
}
|
||||
} catch(err) {
|
||||
data = {
|
||||
error: true,
|
||||
title: this.t('card.error', 'An error occured.'),
|
||||
desc_1: String(err)
|
||||
}
|
||||
}
|
||||
|
||||
this.loaded = true;
|
||||
this.error = data.error;
|
||||
this.title = data.title;
|
||||
this.title_tokens = data.title_tokens;
|
||||
this.desc_1 = data.desc_1;
|
||||
this.desc_1_tokens = data.desc_1_tokens;
|
||||
this.desc_2 = data.desc_2;
|
||||
this.desc_2_tokens = data.desc_2_tokens;
|
||||
this.image = data.image;
|
||||
this.image_square = data.image_square;
|
||||
this.image_title = data.image_title;
|
||||
this.accent = data.accent;
|
||||
},
|
||||
|
||||
renderCard(h) {
|
||||
if ( this.data.renderBody )
|
||||
return [this.data.renderBody(h)];
|
||||
|
||||
if ( this.html )
|
||||
return [h('div', {
|
||||
domProps: {
|
||||
innerHTML: this.html
|
||||
}
|
||||
})];
|
||||
|
||||
return [
|
||||
this.renderImage(h),
|
||||
this.renderDescription(h)
|
||||
|
|
|
@ -71,6 +71,32 @@ export default class Chat extends Module {
|
|||
// Settings
|
||||
// ========================================================================
|
||||
|
||||
this.settings.add('debug.link-resolver.source', {
|
||||
default: null,
|
||||
ui: {
|
||||
path: 'Debugging > Data Sources >> Links',
|
||||
title: 'Link Resolver',
|
||||
component: 'setting-select-box',
|
||||
force_seen: true,
|
||||
data: [
|
||||
{value: null, title: 'Automatic'},
|
||||
{value: 'dev', title: 'localhost'},
|
||||
{value: 'test', title: 'API Test'},
|
||||
{value: 'prod', title: 'API Production' },
|
||||
{value: 'socket', title: 'Socket Cluster (Deprecated)'}
|
||||
]
|
||||
},
|
||||
|
||||
changed: () => this.clearLinkCache()
|
||||
});
|
||||
|
||||
this.settings.addUI('debug.link-resolver.test', {
|
||||
path: 'Debugging > Data Sources >> Links',
|
||||
component: 'link-tester',
|
||||
getChat: () => this,
|
||||
force_seen: true
|
||||
});
|
||||
|
||||
this.settings.add('chat.font-size', {
|
||||
default: 12,
|
||||
ui: {
|
||||
|
@ -1506,6 +1532,33 @@ export default class Chat extends Module {
|
|||
// Twitch Crap
|
||||
// ====
|
||||
|
||||
clearLinkCache(url) {
|
||||
if ( url ) {
|
||||
const info = this._link_info[url];
|
||||
if ( ! info[0] ) {
|
||||
for(const pair of info[2])
|
||||
pair[1]();
|
||||
}
|
||||
|
||||
this._link_info[url] = null;
|
||||
this.emit(':update-link-resolver', url);
|
||||
return;
|
||||
}
|
||||
|
||||
const old = this._link_info;
|
||||
this._link_info = {};
|
||||
|
||||
for(const info of Object.values(old)) {
|
||||
if ( ! info[0] ) {
|
||||
for(const pair of info[2])
|
||||
pair[1]();
|
||||
}
|
||||
}
|
||||
|
||||
this.emit(':update-link-resolver');
|
||||
}
|
||||
|
||||
|
||||
get_link_info(url, no_promises) {
|
||||
let info = this._link_info[url];
|
||||
const expires = info && info[1];
|
||||
|
@ -1536,15 +1589,23 @@ export default class Chat extends Module {
|
|||
cbs[success ? 0 : 1](data);
|
||||
}
|
||||
|
||||
if ( this.experiments.getAssignment('api_links') )
|
||||
timeout(fetch(`https://api-test.frankerfacez.com/v2/link?url=${encodeURIComponent(url)}`).then(r => r.json()), 15000)
|
||||
.then(data => handle(true, data))
|
||||
.catch(err => handle(false, err));
|
||||
let provider = this.settings.get('debug.link-resolver.source');
|
||||
if ( provider == null )
|
||||
provider = this.experiments.getAssignment('api_links') ? 'test' : 'socket';
|
||||
|
||||
else
|
||||
if ( provider === 'socket' ) {
|
||||
timeout(this.socket.call('get_link', url), 15000)
|
||||
.then(data => handle(true, data))
|
||||
.catch(err => handle(false, err));
|
||||
} else {
|
||||
const host = provider === 'dev' ? 'https://localhost:8002/' :
|
||||
provider === 'test' ? 'https://api-test.frankerfacez.com/v2/link' :
|
||||
'https://api.frankerfacez.com/v2/link';
|
||||
|
||||
timeout(fetch(`${host}?url=${encodeURIComponent(url)}`).then(r => r.json()), 15000)
|
||||
.then(data => handle(true, data))
|
||||
.catch(err => handle(false, err));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -63,10 +63,14 @@ export const Links = {
|
|||
url: token.url,
|
||||
accent: data.accent,
|
||||
image: this.context.get('tooltip.link-images') ? (data.image_safe || this.context.get('tooltip.link-nsfw-images') ) ? data.preview || data.image : null : null,
|
||||
image_title: data.image_title,
|
||||
image_square: data.image_square,
|
||||
title: data.title,
|
||||
title_tokens: data.title_tokens,
|
||||
desc_1: data.desc_1,
|
||||
desc_2: data.desc_2
|
||||
desc_1_tokens: data.desc_1_tokens,
|
||||
desc_2: data.desc_2,
|
||||
desc_2_tokens: data.desc_2_tokens
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -227,7 +231,7 @@ export const Clips = {
|
|||
} else if ( game ) {
|
||||
desc_1_tokens = this.i18n.tList('clip.desc.1.playing', '{user} playing {game}', {
|
||||
user: {class: 'tw-semibold', content: user},
|
||||
game: {class: 'tw-semibold', game_display}
|
||||
game: {class: 'tw-semibold', content: game_display}
|
||||
});
|
||||
desc_1 = this.i18n.t('clip.desc.1.playing', '{user} playing {game}', {
|
||||
user,
|
||||
|
|
|
@ -47,7 +47,9 @@ export const Links = {
|
|||
if ( target.dataset.isMail === 'true' )
|
||||
return [this.i18n.t('tooltip.email-link', 'E-Mail {address}', {address: target.textContent})];
|
||||
|
||||
return this.get_link_info(target.dataset.url).then(data => {
|
||||
const url = target.dataset.url || target.href;
|
||||
|
||||
return this.get_link_info(url).then(data => {
|
||||
if ( ! data || (data.v || 1) > TOOLTIP_VERSION )
|
||||
return '';
|
||||
|
||||
|
|
230
src/modules/main_menu/components/link-tester.vue
Normal file
230
src/modules/main_menu/components/link-tester.vue
Normal file
|
@ -0,0 +1,230 @@
|
|||
<template>
|
||||
<div class="ffz--link-tester">
|
||||
<div class="ffz--widget ffz--select-box">
|
||||
<div class="tw-flex tw-align-items-start">
|
||||
<label for="selector" class="tw-mg-y-05">
|
||||
{{ t('debug.link-provider.url', 'Test URL') }}
|
||||
</label>
|
||||
|
||||
<div class="tw-flex tw-flex-column tw-mg-05">
|
||||
<select
|
||||
id="selector"
|
||||
ref="selector"
|
||||
class="tw-border-top-left-radius-medium tw-border-top-right-radius-medium tw-font-size-6 tw-select tw-pd-l-1 tw-pd-r-3 tw-pd-y-05"
|
||||
@change="onSelectChange"
|
||||
>
|
||||
<option
|
||||
v-for="i in stock_urls"
|
||||
:key="i"
|
||||
:selected="i === raw_url"
|
||||
>
|
||||
{{ i }}
|
||||
</option>
|
||||
<option :selected="isCustomURL">
|
||||
{{ t('setting.combo-box.custom', 'Custom') }}
|
||||
</option>
|
||||
</select>
|
||||
<input
|
||||
ref="text"
|
||||
v-model="raw_url"
|
||||
:disabled="! isCustomURL"
|
||||
class="ffz-mg-t-1p tw-border-bottom-left-radius-medium tw-border-bottom-right-radius-medium tw-font-size-6 tw-pd-x-1 tw-pd-y-05 tw-input"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tw-flex tw-mg-b-1">
|
||||
<div class="tw-flex-grow-1" />
|
||||
<button
|
||||
class="tw-mg-l-1 tw-button tw-button--text"
|
||||
@click="refresh"
|
||||
>
|
||||
<span class="tw-button__text ffz-i-arrows-cw">
|
||||
{{ t('debug.link-provider.refresh', 'Refresh') }}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="tw-flex tw-mg-b-1 tw-full-width">
|
||||
<label>
|
||||
{{ t('debug.link-provider.embed', 'Rich Embed') }}
|
||||
</label>
|
||||
<div class="tw-full-width tw-overflow-hidden">
|
||||
<chat-rich
|
||||
v-if="rich_data"
|
||||
:data="rich_data"
|
||||
:url="url"
|
||||
:events="events"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tw-flex tw-mg-b-1 tw-full-width">
|
||||
<label>
|
||||
{{ t('debug.link-provider.link', 'Chat Link') }}
|
||||
</label>
|
||||
<div class="tw-full-width tw-overflow-hidden">
|
||||
<a
|
||||
v-if="url"
|
||||
:href="url"
|
||||
:data-url="url"
|
||||
class="ffz-tooltip"
|
||||
data-tooltip-type="link"
|
||||
data-force-tooltip="true"
|
||||
data-is-mail="false"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
{{ url }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tw-flex tw-mg-b-1 tw-full-width">
|
||||
<label>
|
||||
{{ t('debug.link-provider.raw', 'Raw Data') }}
|
||||
</label>
|
||||
<div class="tw-full-width tw-overflow-hidden ffz--example-report">
|
||||
<div v-if="url" class="tw-c-background-alt-2 tw-font-size-5 tw-pd-y-05 tw-pd-x-1 tw-border-radius-large">
|
||||
<div v-if="raw_loading" class="tw-align-center">
|
||||
<h1 class="tw-mg-5 ffz-i-zreknarf loading" />
|
||||
</div>
|
||||
<code v-else>{{ raw_data }}</code>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { deep_copy } from 'utilities/object'
|
||||
import { debounce } from '../../../utilities/object';
|
||||
|
||||
const STOCK_URLS = [
|
||||
'https://www.twitch.tv/sirstendec',
|
||||
'https://discord.gg/UrAkGhT',
|
||||
'https://www.youtube.com/watch?v=CAL4WMpBNs0',
|
||||
'https://xkcd.com/221/',
|
||||
'https://github.com/FrankerFaceZ/FrankerFaceZ',
|
||||
'https://twitter.com/frankerfacez',
|
||||
'https://twitter.com/FrankerFaceZ/status/1240717057630625792'
|
||||
]
|
||||
|
||||
export default {
|
||||
components: {
|
||||
'chat-rich': async () => {
|
||||
const stuff = await import(/* webpackChunkName: "chat" */ 'src/modules/chat/components');
|
||||
return stuff.default('./chat-rich.vue').default;
|
||||
}
|
||||
},
|
||||
|
||||
props: ['item', 'context'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
stock_urls: deep_copy(STOCK_URLS),
|
||||
raw_url: STOCK_URLS[Math.floor(Math.random() * STOCK_URLS.length)],
|
||||
rich_data: null,
|
||||
isCustomURL: false,
|
||||
raw_loading: false,
|
||||
raw_data: null,
|
||||
events: {
|
||||
on: (...args) => this.item.getChat().on(...args),
|
||||
off: (...args) => this.item.getChat().off(...args)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
url() {
|
||||
try {
|
||||
return new URL(this.raw_url).toString();
|
||||
} catch(err) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
url() {
|
||||
this.rebuildData();
|
||||
},
|
||||
|
||||
rich_data() {
|
||||
this.refreshRaw();
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.rebuildData = debounce(this.rebuildData, 250);
|
||||
this.refreshRaw = debounce(this.refreshRaw, 250);
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.chat = this.item.getChat();
|
||||
this.chat.on('chat:update-link-resolver', this.checkRefreshRaw, this);
|
||||
this.rebuildData();
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.chat.off('chat:update-link-resolver', this.checkRefreshRaw, this);
|
||||
this.chat = null;
|
||||
},
|
||||
|
||||
methods: {
|
||||
checkRefreshRaw(url) {
|
||||
if ( ! url || (url && url === this.url) )
|
||||
this.refreshRaw();
|
||||
},
|
||||
|
||||
async refreshRaw() {
|
||||
this.raw_data = null;
|
||||
if ( ! this.rich_data ) {
|
||||
this.raw_loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.raw_loading = true;
|
||||
try {
|
||||
this.raw_data = JSON.stringify(await this.chat.get_link_info(this.url), null, '\t');
|
||||
} catch(err) {
|
||||
this.raw_data = `Error\n\n${err.toString()}`;
|
||||
}
|
||||
this.raw_loading = false;
|
||||
},
|
||||
|
||||
rebuildData() {
|
||||
if ( ! this.url )
|
||||
return this.rich_data = null;
|
||||
|
||||
const token = {
|
||||
type: 'link',
|
||||
force_rich: true,
|
||||
is_mail: false,
|
||||
url: this.url,
|
||||
text: this.url
|
||||
};
|
||||
|
||||
this.rich_data = this.chat.rich_providers.link.process.call(this.chat, token);
|
||||
},
|
||||
|
||||
refresh() {
|
||||
this.chat.clearLinkCache(this.url);
|
||||
},
|
||||
|
||||
onSelectChange() {
|
||||
const idx = this.$refs.selector.selectedIndex,
|
||||
raw_value = this.stock_urls[idx];
|
||||
|
||||
if ( raw_value ) {
|
||||
this.raw_url = raw_value;
|
||||
this.isCustomURL = false;
|
||||
} else
|
||||
this.isCustomURL = true;
|
||||
},
|
||||
|
||||
onTextChange() {
|
||||
this.raw_url = this.$refs.text
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</script>
|
|
@ -78,22 +78,22 @@ export default class TooltipProvider extends Module {
|
|||
}
|
||||
|
||||
|
||||
_createInstance(container) {
|
||||
return new Tooltip(container, 'ffz-tooltip', {
|
||||
_createInstance(container, klass = 'ffz-tooltip', default_type) {
|
||||
return new Tooltip(container, klass, {
|
||||
html: true,
|
||||
i18n: this.i18n,
|
||||
live: true,
|
||||
|
||||
delayHide: this.checkDelayHide.bind(this),
|
||||
delayShow: this.checkDelayShow.bind(this),
|
||||
content: this.process.bind(this),
|
||||
interactive: this.checkInteractive.bind(this),
|
||||
hover_events: this.checkHoverEvents.bind(this),
|
||||
delayHide: this.checkDelayHide.bind(this, default_type),
|
||||
delayShow: this.checkDelayShow.bind(this, default_type),
|
||||
content: this.process.bind(this, default_type),
|
||||
interactive: this.checkInteractive.bind(this, default_type),
|
||||
hover_events: this.checkHoverEvents.bind(this, default_type),
|
||||
|
||||
onShow: this.delegateOnShow.bind(this),
|
||||
onHide: this.delegateOnHide.bind(this),
|
||||
onShow: this.delegateOnShow.bind(this, default_type),
|
||||
onHide: this.delegateOnHide.bind(this, default_type),
|
||||
|
||||
popperConfig: this.delegatePopperConfig.bind(this),
|
||||
popperConfig: this.delegatePopperConfig.bind(this, default_type),
|
||||
popper: {
|
||||
placement: 'top',
|
||||
modifiers: {
|
||||
|
@ -132,8 +132,8 @@ export default class TooltipProvider extends Module {
|
|||
this.tips.cleanup();
|
||||
}
|
||||
|
||||
delegatePopperConfig(target, tip, pop_opts) {
|
||||
const type = target.dataset.tooltipType,
|
||||
delegatePopperConfig(default_type, target, tip, pop_opts) {
|
||||
const type = target.dataset.tooltipType || default_type,
|
||||
handler = this.types[type];
|
||||
|
||||
if ( handler && handler.popperConfig )
|
||||
|
@ -142,24 +142,24 @@ export default class TooltipProvider extends Module {
|
|||
return pop_opts;
|
||||
}
|
||||
|
||||
delegateOnShow(target, tip) {
|
||||
const type = target.dataset.tooltipType,
|
||||
delegateOnShow(default_type, target, tip) {
|
||||
const type = target.dataset.tooltipType || default_type,
|
||||
handler = this.types[type];
|
||||
|
||||
if ( handler && handler.onShow )
|
||||
handler.onShow(target, tip);
|
||||
}
|
||||
|
||||
delegateOnHide(target, tip) {
|
||||
const type = target.dataset.tooltipType,
|
||||
delegateOnHide(default_type, target, tip) {
|
||||
const type = target.dataset.tooltipType || default_type,
|
||||
handler = this.types[type];
|
||||
|
||||
if ( handler && handler.onHide )
|
||||
handler.onHide(target, tip);
|
||||
}
|
||||
|
||||
checkDelayShow(target, tip) {
|
||||
const type = target.dataset.tooltipType,
|
||||
checkDelayShow(default_type, target, tip) {
|
||||
const type = target.dataset.tooltipType || default_type,
|
||||
handler = this.types[type];
|
||||
|
||||
if ( has(handler, 'delayShow') )
|
||||
|
@ -168,8 +168,8 @@ export default class TooltipProvider extends Module {
|
|||
return 0;
|
||||
}
|
||||
|
||||
checkDelayHide(target, tip) {
|
||||
const type = target.dataset.tooltipType,
|
||||
checkDelayHide(default_type, target, tip) {
|
||||
const type = target.dataset.tooltipType || default_type,
|
||||
handler = this.types[type];
|
||||
|
||||
if ( has(handler, 'delayHide') )
|
||||
|
@ -178,8 +178,8 @@ export default class TooltipProvider extends Module {
|
|||
return 0;
|
||||
}
|
||||
|
||||
checkInteractive(target, tip) {
|
||||
const type = target.dataset.tooltipType,
|
||||
checkInteractive(default_type, target, tip) {
|
||||
const type = target.dataset.tooltipType || default_type,
|
||||
handler = this.types[type];
|
||||
|
||||
if ( has(handler, 'interactive') )
|
||||
|
@ -188,8 +188,8 @@ export default class TooltipProvider extends Module {
|
|||
return false;
|
||||
}
|
||||
|
||||
checkHoverEvents(target, tip) {
|
||||
const type = target.dataset.tooltipType,
|
||||
checkHoverEvents(default_type, target, tip) {
|
||||
const type = target.dataset.tooltipType || default_type,
|
||||
handler = this.types[type];
|
||||
|
||||
if ( has(handler, 'hover_events') )
|
||||
|
@ -198,8 +198,8 @@ export default class TooltipProvider extends Module {
|
|||
return false;
|
||||
}
|
||||
|
||||
process(target, tip) {
|
||||
const type = target.dataset.tooltipType || 'text',
|
||||
process(default_type, target, tip) {
|
||||
const type = target.dataset.tooltipType || default_type || 'text',
|
||||
handler = this.types[type];
|
||||
|
||||
if ( ! handler )
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue