qtip2
Version:
Introducing... qTip2. The second generation of the advanced qTip plugin for the ever popular jQuery framework.
163 lines (128 loc) • 5.06 kB
JavaScript
// Initialization method
function init(elem, id, opts) {
var obj, posOptions, attr, config, title,
// Setup element references
docBody = $(document.body),
// Use document body instead of document element if needed
newTarget = elem[0] === document ? docBody : elem,
// Grab metadata from element if plugin is present
metadata = elem.metadata ? elem.metadata(opts.metadata) : NULL,
// If metadata type if HTML5, grab 'name' from the object instead, or use the regular data object otherwise
metadata5 = opts.metadata.type === 'html5' && metadata ? metadata[opts.metadata.name] : NULL,
// Grab data from metadata.name (or data-qtipopts as fallback) using .data() method,
html5 = elem.data(opts.metadata.name || 'qtipopts');
// If we don't get an object returned attempt to parse it manualyl without parseJSON
/* eslint-disable no-empty */
try { html5 = typeof html5 === 'string' ? $.parseJSON(html5) : html5; }
catch(e) {}
/* eslint-enable no-empty */
// Merge in and sanitize metadata
config = $.extend(TRUE, {}, QTIP.defaults, opts,
typeof html5 === 'object' ? sanitizeOptions(html5) : NULL,
sanitizeOptions(metadata5 || metadata));
// Re-grab our positioning options now we've merged our metadata and set id to passed value
posOptions = config.position;
config.id = id;
// Setup missing content if none is detected
if('boolean' === typeof config.content.text) {
attr = elem.attr(config.content.attr);
// Grab from supplied attribute if available
if(config.content.attr !== FALSE && attr) { config.content.text = attr; }
// No valid content was found, abort render
else { return FALSE; }
}
// Setup target options
if(!posOptions.container.length) { posOptions.container = docBody; }
if(posOptions.target === FALSE) { posOptions.target = newTarget; }
if(config.show.target === FALSE) { config.show.target = newTarget; }
if(config.show.solo === TRUE) { config.show.solo = posOptions.container.closest('body'); }
if(config.hide.target === FALSE) { config.hide.target = newTarget; }
if(config.position.viewport === TRUE) { config.position.viewport = posOptions.container; }
// Ensure we only use a single container
posOptions.container = posOptions.container.eq(0);
// Convert position corner values into x and y strings
posOptions.at = new CORNER(posOptions.at, TRUE);
posOptions.my = new CORNER(posOptions.my);
// Destroy previous tooltip if overwrite is enabled, or skip element if not
if(elem.data(NAMESPACE)) {
if(config.overwrite) {
elem.qtip('destroy', true);
}
else if(config.overwrite === FALSE) {
return FALSE;
}
}
// Add has-qtip attribute
elem.attr(ATTR_HAS, id);
// Remove title attribute and store it if present
if(config.suppress && (title = elem.attr('title'))) {
// Final attr call fixes event delegatiom and IE default tooltip showing problem
elem.removeAttr('title').attr(oldtitle, title).attr('title', '');
}
// Initialize the tooltip and add API reference
obj = new QTip(elem, config, id, !!attr);
elem.data(NAMESPACE, obj);
return obj;
}
// jQuery $.fn extension method
QTIP = $.fn.qtip = function(options, notation, newValue)
{
var command = ('' + options).toLowerCase(), // Parse command
returned = NULL,
args = $.makeArray(arguments).slice(1),
event = args[args.length - 1],
opts = this[0] ? $.data(this[0], NAMESPACE) : NULL;
// Check for API request
if(!arguments.length && opts || command === 'api') {
return opts;
}
// Execute API command if present
else if('string' === typeof options) {
this.each(function() {
var api = $.data(this, NAMESPACE);
if(!api) { return TRUE; }
// Cache the event if possible
if(event && event.timeStamp) { api.cache.event = event; }
// Check for specific API commands
if(notation && (command === 'option' || command === 'options')) {
if(newValue !== undefined || $.isPlainObject(notation)) {
api.set(notation, newValue);
}
else {
returned = api.get(notation);
return FALSE;
}
}
// Execute API command
else if(api[command]) {
api[command].apply(api, args);
}
});
return returned !== NULL ? returned : this;
}
// No API commands. validate provided options and setup qTips
else if('object' === typeof options || !arguments.length) {
// Sanitize options first
opts = sanitizeOptions($.extend(TRUE, {}, options));
return this.each(function(i) {
var api, id;
// Find next available ID, or use custom ID if provided
id = $.isArray(opts.id) ? opts.id[i] : opts.id;
id = !id || id === FALSE || id.length < 1 || QTIP.api[id] ? QTIP.nextid++ : id;
// Initialize the qTip and re-grab newly sanitized options
api = init($(this), id, opts);
if(api === FALSE) { return TRUE; }
else { QTIP.api[id] = api; }
// Initialize plugins
$.each(PLUGINS, function() {
if(this.initialize === 'initialize') { this(api); }
});
// Assign initial pre-render events
api._assignInitialEvents(event);
});
}
};
// Expose class
$.qtip = QTip;
// Populated in render method
QTIP.api = {};