/* https://github.com/hekigan/vue-directive-tooltip */
/*
* @author: laurent blanes <laurent.blanes@gmail.com>
* @tutorial: https://hekigan.github.io/vue-directive-tooltip/
*/
import Tooltip from './tooltip.js';
const BASE_CLASS = 'vue-tooltip';
const POSITIONS = ['auto', 'top', 'bottom', 'left', 'right'];
const SUB_POSITIONS = ['start', 'end'];
/**
* usage:
*
* // basic usage:
* <div v-tooltip="'my content'">
* or
* <div v-tooltip="{content: 'my content'}">
*
* // change position of tooltip
* // options: auto (default) | bottom | top | left | right
*
* // change sub-position of tooltip
* // options: start | end
*
* <div v-tooltip.top="{content: 'my content'}">
*
* // add custom class
* <div v-tooltip="{class: 'custom-class', content: 'my content'}">
*
* // toggle visibility
* <div v-tooltip="{visible: false, content: 'my content'}">
*/
export default {
name: 'tooltip',
config: {},
install (Vue, installOptions) {
Vue.directive('tooltip', {
bind (el, binding, vnode) {
if (installOptions) {
Tooltip.defaults(installOptions);
}
},
inserted (el, binding, vnode, oldVnode) {
if (installOptions) {
Tooltip.defaults(installOptions);
}
let options = filterBindings(binding, vnode);
el.tooltip = new Tooltip(el, options);
if (binding.modifiers.notrigger && binding.value.visible === true) {
el.tooltip.show();
}
if (binding.value && binding.value.visible === false) {
el.tooltip.disabled = true;
}
},
componentUpdated (el, binding, vnode, oldVnode) {
if (hasUpdated(binding.value, binding.oldValue)) {
update(el, binding, vnode, oldVnode);
}
},
unbind (el, binding, vnode, oldVnode) {
el.tooltip.destroy();
}
});
}
};
/**
*
* @param {*} vnode component's properties
* @param {*} oldvnode component's previous properties
* @return boolean
*/
function hasUpdated (value, oldValue) {
let updated = false;
if (typeof value === 'string' && value !== oldValue) {
updated = true;
} else if (isObject(value)) {
Object.keys(value).forEach(prop => {
if (value[prop] !== oldValue[prop]) {
updated = true;
}
});
}
return updated;
}
/**
* Sanitize data
* @param {*} binding
* @param {*} vnode
* @return {*} filtered data object
*/
function filterBindings (binding, vnode) {
const delay = !binding.value || isNaN(binding.value.delay) ? Tooltip._defaults.delay : binding.value.delay;
if (binding.value.ref) {
if (vnode.context.$refs[binding.value.ref]) {
binding.value.html = vnode.context.$refs[binding.value.ref];
} else {
console.error(`[Tooltip] no REF element [${binding.value.ref}]`); // eslint-disable-line
}
}
return {
class: getClass(binding),
id: (binding.value) ? binding.value.id : null,
html: (binding.value) ? binding.value.html : null,
placement: getPlacement(binding),
title: getContent(binding),
triggers: getTriggers(binding),
fixIosSafari: binding.modifiers.ios || false,
offset: (binding.value && binding.value.offset) ? binding.value.offset : Tooltip._defaults.offset,
delay
};
}
/**
* Get placement from modifiers
* @param {*} binding
*/
function getPlacement ({modifiers, value}) {
let MODS = Object.keys(modifiers);
if (MODS.length === 0 && isObject(value) && typeof value.placement === 'string') {
MODS = value.placement.split('.');
}
let head = 'bottom';
let tail = null;
for (let i = 0; i < MODS.length; i++) {
const pos = MODS[i];
if (POSITIONS.indexOf(pos) > -1) {
head = pos;
}
if (SUB_POSITIONS.indexOf(pos) > -1) {
tail = pos;
}
}
// console.log((head && tail) ? `${head}-${tail}` : head);
// return 'auto';
return (head && tail) ? `${head}-${tail}` : head;
}
/**
* Get trigger value from modifiers
* @param {*} binding
* @return String
*/
function getTriggers ({modifiers}) {
let trigger = [];
if (modifiers.notrigger) {
return trigger;
} else if (modifiers.manual) {
trigger.push('manual');
} else {
if (modifiers.click) {
trigger.push('click');
}
if (modifiers.hover) {
trigger.push('hover');
}
if (modifiers.focus) {
trigger.push('focus');
}
if (trigger.length === 0) {
trigger.push('hover', 'focus');
}
}
return trigger;
}
/**
* Check if the variable is an object
* @param {*} value
* @return Boolean
*/
function isObject (value) {
return typeof value === 'object';
}
/**
* Check if the variable is an html element
* @param {*} value
* @return Boolean
*/
function isElement (value) {
return value instanceof window.Element;
}
/**
* Get the css class
* @param {*} binding
* @return HTMLElement | String
*/
function getClass ({value}) {
if (value === null) {
return BASE_CLASS;
} else if (isObject(value) && typeof value.class === 'string') {
return `${BASE_CLASS} ${value.class}`;
} else if (Tooltip._defaults.class) {
return `${BASE_CLASS} ${Tooltip._defaults.class}`;
} else {
return BASE_CLASS;
}
}
/**
* Get the content
* @param {*} binding
* @return HTMLElement | String
*/
function getContent ({value}, vnode) {
if (value !== null && isObject(value)) {
if (value.content !== undefined) {
return `${value.content}`;
} else if (value.id && document.getElementById(value.id)) {
return document.getElementById(value.id);
} else if (value.html && document.getElementById(value.html)) {
return document.getElementById(value.html);
} else if (isElement(value.html)) {
return value.html;
} else if (value.ref && vnode) {
return vnode.context.$refs[value.ref] || '';
} else {
return '';
}
} else {
return `${value}`;
}
}
/**
* Action on element update
* @param {*} el Vue element
* @param {*} binding
*/
function update (el, binding, vnode, oldVnode) {
if (typeof binding.value === 'string') {
el.tooltip.content(binding.value);
} else {
if (binding.value && binding.value.class && binding.value.class.trim() !== el.tooltip.options.class.replace(BASE_CLASS, '').trim()) {
el.tooltip.class = `${BASE_CLASS} ${binding.value.class.trim()}`;
}
el.tooltip.content(getContent(binding, vnode));
if (!binding.modifiers.notrigger && binding.value && typeof binding.value.visible === 'boolean') {
el.tooltip.disabled = !binding.value.visible;
return;
} else if (binding.modifiers.notrigger) {
el.tooltip.disabled = false;
}
const dir = vnode.data.directives[0];
if (dir.oldValue.visible !== dir.value.visible) {
if (!el.tooltip.disabled) {
el.tooltip.toggle(dir.value.visible);
}
}
}
}
<template>
<div>
<h2 class="text-h4">{{ name }}</h2>
<button @click="score++" class="btn">
{{ score }} twice is {{ double }}
</button>
<hr />
<button @click="score2++" class="btn">
{{ score2 }} triple is {{ triple }}
</button>
<hr />
<ul>
<li v-for="data in dataList" :key="data.id">{{ data.name }}</li>
</ul>
<hr />
<button v-if="!divVisible" @click="showDiv">Show div</button>
<button v-if="divVisible" @click="hideDiv">Hide div</button>
<div v-if="divVisible" class="bg-red-100">My super hidden div :)</div>
<hr />
<form @submit.prevent="submitForm">
<input type="text" v-model="title" />
</form>
</div>
</template>
<script>
import { ref, computed, reactive, toRefs, onMounted } from 'vue'
import { data } from '@/frontapp/components/data.js'
export default {
components: {},
props: ['name'],
// props, context nebo { emit } nebo { emit, slots }
setup(props, { emit }) {
console.log(props, 'our props')
// data
const score = ref(1)
const dude = ref('Kcko')
const dataList = ref(data)
const state = reactive({
score2: 12,
triple: computed(() => state.score2 * 3),
divVisible: false
})
// computed
const double = computed(() => score.value * 2 + 7)
const hello = computed(() => 'Hello, I am ' + dude.value)
// methods
const showDiv = () => {
state.divVisible = true
}
const hideDiv = () => {
state.divVisible = false
}
// v nadrazenem prvku / komponentne nebo standardne -> view @new-list-coming="nejakaMetoda($event)"
const title = ref('')
const submitForm = () => {
emit('new-list-coming', title.value)
}
onMounted(() => {
console.log('Mounted yeah!')
})
return {
score,
double,
hello,
...toRefs(state),
dataList,
showDiv,
hideDiv,
submitForm
}
}
}
</script>
<template>
<video-player v-bind="mergedVideoSettings" />
</template>
<script>
import VideoPlayer from './VideoPlayer.local.vue'
export default {
props: {
videoSettings: Object
},
components: {
VideoPlayer
},
computed: {
mergedVideoSettings() {
return {
...this.defaultVideoSettings,
...this.videoSettings
}
}
},
data() {
return {
defaultVideoSettings: {
mask: false,
colors: 'var(--primaryColor)'
}
}
},
mounted() {}
}
</script>
<style lang="scss" scoped></style>
<!--Emit + props-->
<!--PARENT-->
<template>
<div>
<h1>A1 - parent</h1>
<input
:value="time"
@input="time = $event.target.value"
class="border border-gray-400"
/>
<b1 @on-parent="this.time = $event" :time="time" />
</div>
</template>
<script>
export default {
data() {
return {
time: null
}
},
methods: {},
computed: {},
mounted() {}
}
</script>
<!--CHILD-->
<template>
<div>
<h1>B1 - child</h1>
<input
:value="time"
@input="sendData($event.target.value)"
class="border border-gray-400"
/>
</div>
</template>
<script>
export default {
emits: ['on-parent'],
props: ['time'],
data() {
return {}
},
methods: {
sendData(val) {
this.$emit('on-parent', val)
}
},
computed: {},
mounted() {}
}
</script>
// import store from '../store' <-- To access your Vuex store
import Vue from 'vue' // <-- used for vue-toastification
class Utils {
// Copy a string to user's clipboard
copyToClipboard(text) {
let copyText = document.createElement('input')
document.body.appendChild(copyText)
copyText.value = text
copyText.select()
document.execCommand('copy')
document.body.removeChild(copyText)
// Show toast on copy success
// (using the vue-toastification package here)
Vue.$toast.success('Copied address to clipboard: ' + text, {
position: 'top-right',
timeout: 3000
})
}
}
export default new Utils()
export default {
install (Vue) {
Vue.directive('test-demo', {
mounted(el, binding) {
const modifiers = binding.modifiers
const state = binding.arg === "a" ? "a" : "b"
if (state === 'a') {
el.style.color = 'red'
} else {
el.style.color = 'green'
}
if (modifiers.underline) {
el.style.textDecoration = "underline"
}
if (modifiers.overline) {
el.style.textDecoration = "overline"
}
}
})
Vue.directive('width', {
mounted: function (el, binding) {
el.style.width = binding.value + 'px'
}
})
// mounted + update both
Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value
})
Vue.directive('demo', function (el, binding) {
el.style.color = binding.value.color // => "white"
el.textContent = binding.value.text
})
}
}