All files / src/directives v-tooltip.js

10% Statements 1/10
0% Branches 0/6
0% Functions 0/1
10% Lines 1/10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198                                                                                                                      2x                                                                                                                                                                                                                                                                                    
import Tooltip from '../lib/tooltip'
import { addClasses, removeClasses } from '../utils'
 
export let state = {
	enabled: true,
}
 
const positions = [
	'top',
	'top-start',
	'top-end',
	'right',
	'right-start',
	'right-end',
	'bottom',
	'bottom-start',
	'bottom-end',
	'left',
	'left-start',
	'left-end',
]
 
export const defaultOptions = {
	// Default tooltip placement relative to target element
	defaultPlacement: 'top',
	// Default CSS classes applied to the tooltip element
	defaultClass: 'vue-tooltip-theme',
	// Default CSS classes applied to the target element of the tooltip
	defaultTargetClass: 'has-tooltip',
	// Default HTML template of the tooltip element
	// It must include `tooltip-arrow` & `tooltip-inner` CSS classes (can be configured, see below)
	// Change if the classes conflict with other libraries (for example bootstrap)
	defaultTemplate: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
	// Selector used to get the arrow element in the tooltip template
	defaultArrowSelector: '.tooltip-arrow, .tooltip__arrow',
	// Selector used to get the inner content element in the tooltip template
	defaultInnerSelector: '.tooltip-inner, .tooltip__inner',
	// Delay (ms)
	defaultDelay: 0,
	// Default events that trigger the tooltip
	defaultTrigger: 'hover focus',
	// Default position offset (px)
	defaultOffset: 0,
	// Default container where the tooltip will be appended
	defaultContainer: 'body',
	defaultBoundariesElement: undefined,
	defaultPopperOptions: {},
	// Hide on mouseover tooltip
	autoHide: true,
	// Auto destroy tooltip DOM nodes (ms)
	disposeTimeout: 5000,
	// Options for popover
	popover: {
		defaultPlacement: 'bottom',
		// Use the `popoverClass` prop for theming
		defaultClass: 'vue-popover-theme',
		// Base class (change if conflicts with other libraries)
		defaultBaseClass: 'tooltip popover',
		// Wrapper class (contains arrow and inner)
		defaultWrapperClass: 'wrapper',
		// Inner content class
		defaultInnerClass: 'tooltip-inner popover-inner',
		// Arrow class
		defaultArrowClass: 'tooltip-arrow popover-arrow',
		defaultDelay: 0,
		defaultTrigger: 'click',
		defaultOffset: 0,
		defaultContainer: 'body',
		defaultBoundariesElement: undefined,
		defaultPopperOptions: {},
		// Hides if clicked outside of popover
		defaultAutoHide: true,
		// Update popper on content resize
		defaultHandleResize: true,
	},
}
 
export function getOptions (options) {
	const result = {
		placement: typeof options.placement !== 'undefined' ? options.placement : directive.options.defaultPlacement,
		delay: typeof options.delay !== 'undefined' ? options.delay : directive.options.defaultDelay,
		template: typeof options.template !== 'undefined' ? options.template : directive.options.defaultTemplate,
		arrowSelector: typeof options.arrowSelector !== 'undefined' ? options.arrowSelector : directive.options.defaultArrowSelector,
		innerSelector: typeof options.innerSelector !== 'undefined' ? options.innerSelector : directive.options.defaultInnerSelector,
		trigger: typeof options.trigger !== 'undefined' ? options.trigger : directive.options.defaultTrigger,
		offset: typeof options.offset !== 'undefined' ? options.offset : directive.options.defaultOffset,
		container: typeof options.container !== 'undefined' ? options.container : directive.options.defaultContainer,
		boundariesElement: typeof options.boundariesElement !== 'undefined' ? options.boundariesElement : directive.options.defaultBoundariesElement,
		autoHide: typeof options.autoHide !== 'undefined' ? options.autoHide : directive.options.autoHide,
		popperOptions: {
			...(typeof options.popperOptions !== 'undefined' ? options.popperOptions : directive.options.defaultPopperOptions),
		},
	}
 
	if (result.offset) {
		const typeofOffset = typeof result.offset
		let offset = result.offset
 
		// One value -> switch
		if (typeofOffset === 'number' || (typeofOffset === 'string' && offset.indexOf(',') === -1)) {
			offset = `0, ${offset}`
		}
 
		if (!result.popperOptions.modifiers) {
			result.popperOptions.modifiers = {}
		}
		result.popperOptions.modifiers.offset = {
			offset,
		}
	}
 
	return result
}
 
export function getPlacement (value, modifiers) {
	var placement = value.placement
	for (var i = 0; i < positions.length; i++) {
		var pos = positions[i]
		if (modifiers[pos]) {
			placement = pos
		}
	}
	return placement
}
 
export function getContent (value) {
	const type = typeof value
	if (type === 'string') {
		return value
	} else if (value && type === 'object') {
		return value.content
	} else {
		return false
	}
}
 
export function createTooltip (el, value, modifiers) {
	const content = getContent(value)
	let classes = typeof value.classes !== 'undefined' ? value.classes : directive.options.defaultClass
	const opts = {
		title: content,
		html: true,
		...getOptions({
			...value,
			placement: getPlacement(value, modifiers),
		}),
	}
	const tooltip = el._tooltip = new Tooltip(el, opts)
	tooltip.setClasses(classes)
	tooltip._vueEl = el
 
	// Class on target
	const targetClasses = typeof value.targetClasses !== 'undefined' ? value.targetClasses : directive.options.defaultTargetClass
	el._tooltipTargetClasses = targetClasses
	addClasses(el, targetClasses)
}
 
export function destroyTooltip (el) {
	if (el._tooltip) {
		el._tooltip.dispose()
		delete el._tooltip
	}
 
	if (el._tooltipTargetClasses) {
		removeClasses(el, el._tooltipTargetClasses)
		delete el._tooltipTargetClasses
	}
}
 
export function bind (el, { value, oldValue, modifiers }) {
	const content = getContent(value)
	if (!content || !state.enabled) {
		destroyTooltip(el)
	} else if (el._tooltip) {
		const tooltip = el._tooltip
		// Content
		tooltip.setContent(content)
		// Options
		tooltip.setOptions({
			...value,
			placement: getPlacement(value, modifiers),
		})
	} else {
		createTooltip(el, value, modifiers)
	}
}
 
export const directive = {
	options: defaultOptions,
	bind,
	update: bind,
	unbind (el) {
		destroyTooltip(el)
	},
}
 
export default directive