overte/unpublishedScripts/marketplace/camera-move/_tooltips.js
2017-06-16 16:07:50 -04:00

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);