mirror of
https://github.com/overte-org/overte.git
synced 2025-04-09 17:22:28 +02:00
169 lines
6.9 KiB
JavaScript
169 lines
6.9 KiB
JavaScript
/* eslint-env jquery, browser */
|
|
/* eslint-disable comma-dangle, no-empty */
|
|
/* global PARAMS, signal, assert, log, debugPrint */
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// manage jquery-tooltipster hover tooltips
|
|
var TooltipManager = (function(global) {
|
|
Object.assign(TooltipManager, {
|
|
BASECONFIG: {
|
|
theme: ['tooltipster-noir'],
|
|
side: ['right','top','bottom', 'left'],
|
|
updateAnimation: 'scale',
|
|
delay: [750, 1000],
|
|
distance: { right: 24, left: 8, top: 8, bottom: 8 },
|
|
contentAsHTML: true,
|
|
},
|
|
});
|
|
|
|
function TooltipManager(options) {
|
|
assert(options.elements && options.tooltips, 'TooltipManager constructor expects .elements and .tooltips');
|
|
Object.assign(this, {
|
|
instances: [],
|
|
options: options,
|
|
config: Object.assign({}, TooltipManager.BASECONFIG, {
|
|
trigger: !options.testmode ? 'hover' : 'click',
|
|
interactive: options.testmode,
|
|
minWidth: options.viewport && options.viewport.min.width,
|
|
maxWidth: options.viewport && options.viewport.max.width,
|
|
}),
|
|
});
|
|
options.enabled && this.initialize();
|
|
}
|
|
|
|
TooltipManager.prototype = {
|
|
constructor: TooltipManager,
|
|
initialize: function() {
|
|
var options = this.options,
|
|
_config = this.config,
|
|
_self = this,
|
|
candidates = $(options.elements);
|
|
|
|
candidates.add($('button')).each(function() {
|
|
var id = this.id,
|
|
input = $(this),
|
|
tip = options.tooltips[id] || options.tooltips[input.data('for')];
|
|
|
|
var alreadyTipped = input.is('.tooltipstered') || input.closest('.tooltipstered').get(0);
|
|
if (alreadyTipped || !tip) {
|
|
return !tip && _debugPrint('!tooltippable -- missing tooltip for ' + (id || input.data('for') || input.text()));
|
|
}
|
|
var config = Object.assign({ content: tip }, _config);
|
|
|
|
function mergeConfig() {
|
|
var attr = $(this).attr('data-tooltipster'),
|
|
object = $(this).data('tooltipster');
|
|
typeof object === 'object' && Object.assign(config, object);
|
|
attr && Object.assign(config, JSON.parse(attr));
|
|
}
|
|
try {
|
|
input.parents(':data(tooltipster),[data-tooltipster]').each(mergeConfig);
|
|
input.each(mergeConfig); // prioritize own settings
|
|
} catch(e) {
|
|
console.error('error extracting tooltipster data:' + [e, id]);
|
|
}
|
|
|
|
var target = $(input.closest('.tooltip-target').get(0) ||
|
|
(input.is('input') && input) || null);
|
|
|
|
assert(target && target[0] && tip);
|
|
debugPrint('binding tooltip', config, target[0].nodeName, id || target[0]);
|
|
var instance = target.tooltipster(config)
|
|
.tooltipster('instance');
|
|
|
|
instance.on('close', function(event) {
|
|
if (options.keepopen === target) {
|
|
debugPrint(event.type, 'canceling close keepopen === target', id);
|
|
event.stop();
|
|
options.keepopen = null;
|
|
}
|
|
});
|
|
instance.on('before', function(event) {
|
|
debugPrint(event.type, 'before', event);
|
|
!options.testmode && _self.closeAll();
|
|
!options.enabled && event.stop();
|
|
});
|
|
target.find(':focusable, input, [tabindex], button, .control')
|
|
.add(target).add(input)
|
|
.add(input.closest(':focusable, input, [tabindex]'))
|
|
.on({
|
|
click: function(evt) {
|
|
if (input.is('button')) {
|
|
return setTimeout(instance.close.bind(instance,null),50);
|
|
}
|
|
options.keepopen = target;
|
|
},
|
|
focus: instance.open.bind(instance, null),
|
|
blur: function(evt) {
|
|
instance.close(); _self.openFocusedTooltip();
|
|
},
|
|
});
|
|
_self.instances.push(instance);
|
|
});
|
|
return this.instances;
|
|
},
|
|
openFocusedTooltip: function() {
|
|
if (!this.options.enabled) {
|
|
return;
|
|
}
|
|
setTimeout(function() {
|
|
if (!document.activeElement || document.activeElement === document.body ||
|
|
!$(document.activeElement).closest('section')) {
|
|
return;
|
|
}
|
|
var tip = $([])
|
|
.add($(document.activeElement))
|
|
.add($(document.activeElement).find('.tooltipstered'))
|
|
.add($(document.activeElement).closest('.tooltipstered'))
|
|
.filter('.tooltipstered');
|
|
if (tip.is('.tooltipstered')) {
|
|
// log('opening focused tooltip', tip.length, tip[0].id);
|
|
tip.tooltipster('open');
|
|
}
|
|
}, 1);
|
|
},
|
|
rapidClose: function(instance, reopen) {
|
|
if (!instance.status().open) {
|
|
return;
|
|
}
|
|
instance.elementTooltip() && $(instance.elementTooltip()).hide();
|
|
instance.close(function() {
|
|
reopen && instance.open();
|
|
});
|
|
},
|
|
openAll: function() {
|
|
$('.tooltipstered').tooltipster('open');
|
|
},
|
|
closeAll: function() {
|
|
$.tooltipster.instances().forEach(function(instance) {
|
|
this.rapidClose(instance);
|
|
}.bind(this));
|
|
},
|
|
updateViewport: function(viewport) {
|
|
var options = {
|
|
minWidth: viewport.min.width,
|
|
maxWidth: viewport.max.width,
|
|
};
|
|
Object.assign(this.config, options);
|
|
$.tooltipster.setDefaults(options);
|
|
debugPrint('updating tooltipster options', JSON.stringify(options));
|
|
$.tooltipster.instances().forEach(function(instance) {
|
|
instance.option('minWidth', options.minWidth);
|
|
instance.option('maxWidth', options.maxWidth);
|
|
this.rapidClose(instance, instance.status().open);
|
|
}.bind(this));
|
|
},
|
|
enable: function() {
|
|
this.options.enabled = true;
|
|
if (this.options.testmode) {
|
|
this.openAll();
|
|
}
|
|
},
|
|
disable: function() {
|
|
this.options.enabled = false;
|
|
this.closeAll();
|
|
},
|
|
};// prototype
|
|
|
|
return TooltipManager;
|
|
})(this);
|