From 147f118df4e65ef193daa8ad1d0e9df23a1ad661 Mon Sep 17 00:00:00 2001 From: Craig Michael Thompson Date: Fri, 8 Apr 2011 19:32:29 +0100 Subject: [PATCH] Added new 'basic' build comparised or only core.js. See dist/ --- dist/jquery.qtip.basic.js | 1701 +++++++++++++++++++++++++++++++++++++ dist/jquery.qtip.css | 2 +- dist/jquery.qtip.js | 2 +- dist/jquery.qtip.min.js | 2 +- dist/jquery.qtip.pack.js | 2 +- 5 files changed, 1705 insertions(+), 4 deletions(-) create mode 100644 dist/jquery.qtip.basic.js diff --git a/dist/jquery.qtip.basic.js b/dist/jquery.qtip.basic.js new file mode 100644 index 00000000..202ee510 --- /dev/null +++ b/dist/jquery.qtip.basic.js @@ -0,0 +1,1701 @@ +/* +* qTip2 - Pretty powerful tooltips +* http://craigsworks.com/projects/qtip2/ +* +* Version: 2.0.0pre +* Copyright 2009-2010 Craig Michael Thompson - http://craigsworks.com +* +* Dual licensed under MIT or GPLv2 licenses +* http://en.wikipedia.org/wiki/MIT_License +* http://en.wikipedia.org/wiki/GNU_General_Public_License +* +* Date: Fri Apr 8 19:25:39 2011 +0100 +*/ + +"use strict"; // Enable ECMAScript "strict" operation for this function. See more: http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/ +/*jslint browser: true, onevar: true, undef: true, nomen: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: true */ +/*global window: false, jQuery: false */ + + +(function($, window, undefined) { + + // Munge the primitives - Paul Irish tip + var TRUE = true, + FALSE = false, + NULL = null, + + // Shortcut vars + QTIP, PLUGINS, MOUSE, + uitooltip = 'ui-tooltip', + widget = 'ui-widget', + disabled = 'ui-state-disabled', + selector = 'div.qtip.'+uitooltip, + focusClass = uitooltip + '-focus', + hideOffset = '-31000px', + replaceSuffix = '_replacedByqTip', + oldtitle = 'oldtitle'; + + // Simple console.error wrapper + function debug() { + var c = window.console; + return c && (c.error || c.log || $.noop).apply(c, arguments); + } +// Option object sanitizer +function sanitizeOptions(opts) +{ + var content; + + if(!opts || 'object' !== typeof opts) { return FALSE; } + + if('object' !== typeof opts.metadata) { + opts.metadata = { + type: opts.metadata + }; + } + + if('content' in opts) { + if('object' !== typeof opts.content || opts.content.jquery) { + opts.content = { + text: opts.content + }; + } + + content = opts.content.text || FALSE; + if(!$.isFunction(content) && ((!content && !content.attr) || content.length < 1 || ('object' === typeof content && !content.jquery))) { + opts.content.text = FALSE; + } + + if('title' in opts.content) { + if('object' !== typeof opts.content.title) { + opts.content.title = { + text: opts.content.title + }; + } + + content = opts.content.title.text || FALSE; + if(!$.isFunction(content) && ((!content && !content.attr) || content.length < 1 || ('object' === typeof content && !content.jquery))) { + opts.content.title.text = FALSE; + } + } + } + + if('position' in opts) { + if('object' !== typeof opts.position) { + opts.position = { + my: opts.position, + at: opts.position + }; + } + } + + if('show' in opts) { + if('object' !== typeof opts.show) { + if(opts.show.jquery) { + opts.show = { target: opts.show }; + } + else { + opts.show = { event: opts.show }; + } + } + } + + if('hide' in opts) { + if('object' !== typeof opts.hide) { + if(opts.hide.jquery) { + opts.hide = { target: opts.hide }; + } + else { + opts.hide = { event: opts.hide }; + } + } + } + + if('style' in opts) { + if('object' !== typeof opts.style) { + opts.style = { + classes: opts.style + }; + } + } + + // Sanitize plugin options + $.each(PLUGINS, function() { + if(this.sanitize) { this.sanitize(opts); } + }); + + return opts; +} + +/* +* Core plugin implementation +*/ +function QTip(target, options, id, attr) +{ + // Declare this reference + var self = this, + docBody = document.body, + tooltipID = uitooltip + '-' + id, + isPositioning = 0, + isDrawing = 0, + tooltip = $(), + elements, cache; + + // Setup class attributes + self.id = id; + self.rendered = FALSE; + self.elements = elements = { target: target }; + self.timers = { img: [] }; + self.options = options; + self.checks = {}; + self.plugins = {}; + self.cache = cache = { + event: {}, + target: NULL, + disabled: FALSE, + attr: attr + }; + + /* + * Private core functions + */ + function convertNotation(notation) + { + var i = 0, obj, option = options, + + // Split notation into array + levels = notation.split('.'); + + // Loop through + while( option = option[ levels[i++] ] ) { + if(i < levels.length) { obj = option; } + } + + return [obj || options, levels.pop()]; + } + + function setWidget() { + var on = options.style.widget; + + tooltip.toggleClass(widget, on); + elements.content.toggleClass(widget+'-content', on); + + if(elements.titlebar){ + elements.titlebar.toggleClass(widget+'-header', on); + } + if(elements.button){ + elements.button.toggleClass(uitooltip+'-icon', !on); + } + } + + function removeTitle() + { + if(elements.title) { + elements.titlebar.remove(); + elements.titlebar = elements.title = elements.button = NULL; + self.reposition(); + } + } + + function createButton() + { + var button = options.content.title.button, + isString = typeof button === 'string', + close = isString ? button : 'Close tooltip'; + + if(elements.button) { elements.button.remove(); } + + // Use custom button if one was supplied by user, else use default + if(button.jquery) { + elements.button = button; + } + else { + elements.button = $('', { + 'class': 'ui-state-default ' + (options.style.widget ? '' : uitooltip+'-icon'), + 'title': close, + 'aria-label': close + }) + .prepend( + $('', { + 'class': 'ui-icon ui-icon-close', + 'html': '×' + }) + ); + } + + // Create button and setup attributes + elements.button.appendTo(elements.titlebar) + .attr('role', 'button') + .hover(function(event){ $(this).toggleClass('ui-state-hover', event.type === 'mouseenter'); }) + .click(function(event) { + if(!tooltip.hasClass(disabled)) { self.hide(event); } + return FALSE; + }) + .bind('mousedown keydown mouseup keyup mouseout', function(event) { + $(this).toggleClass('ui-state-active ui-state-focus', event.type.substr(-4) === 'down'); + }); + + // Redraw the tooltip when we're done + self.redraw(); + } + + function createTitle() + { + var id = tooltipID+'-title'; + + // Destroy previous title element, if present + if(elements.titlebar) { removeTitle(); } + + // Create title bar and title elements + elements.titlebar = $('
', { + 'class': uitooltip + '-titlebar ' + (options.style.widget ? 'ui-widget-header' : '') + }) + .append( + elements.title = $('
', { + 'id': id, + 'class': uitooltip + '-title', + 'aria-atomic': TRUE + }) + ) + .insertBefore(elements.content); + + // Create button if enabled + if(options.content.title.button) { createButton(); } + + // Redraw the tooltip dimensions if it's rendered + else if(self.rendered){ self.redraw(); } + } + + function updateButton(button) + { + var elem = elements.button, + title = elements.title; + + // Make sure tooltip is rendered and if not, return + if(!self.rendered) { return FALSE; } + + if(!button) { + elem.remove(); + } + else { + if(!title) { + createTitle(); + } + createButton(); + } + } + + function updateTitle(content) + { + var elem = elements.title; + + // Make sure tooltip is rendered and if not, return + if(!self.rendered || !content) { return FALSE; } + + // Use function to parse content + if($.isFunction(content)) { + content = content.call(target, self) || ''; + } + + // Append new content if its a DOM array and show it if hidden + if(content.jquery && content.length > 0) { + elem.empty().append(content.css({ display: 'block' })); + } + + // Content is a regular string, insert the new content + else { elem.html(content); } + + // Redraw and reposition + self.redraw(); + if(self.rendered && tooltip.is(':visible')) { + self.reposition(cache.event); + } + } + + function updateContent(content, reposition) + { + var elem = elements.content; + + // Make sure tooltip is rendered and content is defined. If not return + if(!self.rendered || !content) { return FALSE; } + + // Use function to parse content + if($.isFunction(content)) { + content = content.call(target, self) || ''; + } + + // Append new content if its a DOM array and show it if hidden + if(content.jquery && content.length > 0) { + elem.empty().append(content.css({ display: 'block' })); + } + + // Content is a regular string, insert the new content + else { elem.html(content); } + + // Image detection + function detectImages(next) { + var images; + + function imageLoad(event, i) { + // If queue is empty after image removal, update tooltip and continue the queue + if((images = images.not(this)).length === 0) { + self.redraw(); + self.reposition(cache.event); + + next(); + } + } + + // Find all content images without dimensions, and if no images were found, continue + if((images = elem.find('img:not([height]):not([width])')).length === 0) { return imageLoad.call(images); } + + // Apply the callback to img events to ensure queue continues no matter what! + images.one(['abort','error','load','unload',''].join('.qtip-image '), imageLoad) + + // Apply a recursive method that polls the image for dimensions every 20ms + .each(function(i, elem) { + (function timer(){ + // When the dimensions are found, remove the image from the queue and stop timer + if(elem.height && elem.width) { return imageLoad.call(elem, NULL); } + self.timers.img[i] = setTimeout(timer, 20); + }()); + }); + } + + /* + * If we're still rendering... insert into 'fx' queue our image dimension + * checker which will halt the showing of the tooltip until image dimensions + * can be detected properly. + */ + if(self.rendered < 0) { tooltip.queue('fx', detectImages); } + + // We're fully rendered, so reset isDrawing flag and proceed without queue delay + else { isDrawing = 0; detectImages($.noop); } + + return self; + } + + function assignEvents(show, hide, tip, doc) + { + var namespace = '.qtip-'+id, + posOptions = options.position, + targets = { + show: options.show.target, + hide: options.hide.target, + container: posOptions.container[0] === docBody ? $(document) : posOptions.container, + doc: $(document) + }, + events = { + show: $.trim('' + options.show.event).split(' '), + hide: $.trim('' + options.hide.event).split(' ') + }, + IE6 = $.browser.msie && parseInt($.browser.version, 10) === 6; + + // Define show event method + function showMethod(event) + { + if(tooltip.hasClass(disabled)) { return FALSE; } + + // If set, hide tooltip when inactive for delay period + targets.show.trigger('qtip-'+id+'-inactive'); + + // Clear hide timers + clearTimeout(self.timers.show); + clearTimeout(self.timers.hide); + + // Start show timer + var callback = function(){ self.show(event); }; + if(options.show.delay > 0) { + self.timers.show = setTimeout(callback, options.show.delay); + } + else{ callback(); } + } + + // Define hide method + function hideMethod(event) + { + if(tooltip.hasClass(disabled)) { return FALSE; } + + // Check if new target was actually the tooltip element + var relatedTarget = $(event.relatedTarget || event.target), + ontoTooltip = relatedTarget.closest(selector)[0] === tooltip[0], + ontoTarget = relatedTarget[0] === targets.show[0]; + + // Clear timers and stop animation queue + clearTimeout(self.timers.show); + clearTimeout(self.timers.hide); + + // Prevent hiding if tooltip is fixed and event target is the tooltip. Or if mouse positioning is enabled and cursor momentarily overlaps + if((posOptions.target === 'mouse' && ontoTooltip) || (options.hide.fixed && ((/mouse(out|leave|move)/).test(event.type) && (ontoTooltip || ontoTarget)))) + { + // Prevent default and popagation + event.stopPropagation(); + event.preventDefault(); + return FALSE; + } + + // If tooltip has displayed, start hide timer + if(options.hide.delay > 0) { + self.timers.hide = setTimeout(function(){ self.hide(event); }, options.hide.delay); + } + else{ self.hide(event); } + } + + // Define inactive method + function inactiveMethod(event) + { + if(tooltip.hasClass(disabled)) { return FALSE; } + + // Clear timer + clearTimeout(self.timers.inactive); + self.timers.inactive = setTimeout(function(){ self.hide(event); }, options.hide.inactive); + } + + function repositionMethod(event) { + if(tooltip.is(':visible')) { self.reposition(event); } + } + + // Assign tooltip events + if(tip) { + // Enable hide.fixed + if(options.hide.fixed) { + // Add tooltip as a hide target + targets.hide = targets.hide.add(tooltip); + + // Clear hide timer on tooltip hover to prevent it from closing + tooltip.bind('mouseover'+namespace, function() { + if(!tooltip.hasClass(disabled)) { + clearTimeout(self.timers.hide); + } + }); + } + + // If mouse positioning is on, apply a mouseleave event so we don't get problems with overlapping + if(posOptions.target === 'mouse' && posOptions.adjust.mouse && options.hide.event) { + tooltip.bind('mouseleave'+namespace, function(event) { + if((event.relatedTarget || event.target) !== targets.show[0]) { self.hide(event); } + }); + } + + // Focus/blur the tooltip + tooltip.bind('mouseenter'+namespace+' mouseleave'+namespace, function(event) { + self[ event.type === 'mouseenter' ? 'focus' : 'blur' ](event); + }); + } + + // Assign hide events + if(hide) { + // Check if the tooltip hides when inactive + if('number' === typeof options.hide.inactive) + { + // Bind inactive method to target as a custom event + targets.show.bind('qtip-'+id+'-inactive', inactiveMethod); + + // Define events which reset the 'inactive' event handler + $.each(QTIP.inactiveEvents, function(index, type){ + targets.hide.add(elements.tooltip).bind(type+namespace+'-inactive', inactiveMethod); + }); + } + + // Apply hide events + $.each(events.hide, function(index, type) { + var showIndex = $.inArray(type, events.show), + targetHide = $(targets.hide); + + // Both events and targets are identical, apply events using a toggle + if((showIndex > -1 && targetHide.add(targets.show).length === targetHide.length) || type === 'unfocus') + { + targets.show.bind(type+namespace, function(event) + { + if(tooltip.is(':visible')) { hideMethod(event); } + else{ showMethod(event); } + }); + + // Don't bind the event again + delete events.show[ showIndex ]; + } + + // Events are not identical, bind normally + else{ targets.hide.bind(type+namespace, hideMethod); } + }); + } + + // Apply show events + if(show) { + $.each(events.show, function(index, type) { + targets.show.bind(type+namespace, showMethod); + }); + } + + // Apply document events + if(doc) { + // Adjust positions of the tooltip on window resize if enabled + if(posOptions.adjust.resize || posOptions.viewport) { + $($.event.special.resize ? posOptions.viewport : window).bind('resize'+namespace, repositionMethod); + } + + // Adjust tooltip position on scroll if screen adjustment is enabled + if(posOptions.viewport || (IE6 && tooltip.css('position') === 'fixed')) { + $(posOptions.viewport).bind('scroll'+namespace, repositionMethod); + } + + // Hide tooltip on document mousedown if unfocus events are enabled + if((/unfocus/i).test(options.hide.event)) { + targets.doc.bind('mousedown'+namespace, function(event) { + var $target = $(event.target); + + if($target.parents(selector).length === 0 && $target.add(target).length > 1 && tooltip.is(':visible') && !tooltip.hasClass(disabled)) { + self.hide(event); + } + }); + } + + // Hide mouseleave/mouseout tooltips on window blur/mouseleave + if((/mouseleave|mouseout/i).test(options.hide.event)) { + $(window).bind('blur mouseout', function(event) { + if(!event.relatedTarget) { self.hide(event); } + }); + } + + // If mouse is the target, update tooltip position on document mousemove + if(posOptions.target === 'mouse') { + targets.doc.bind('mousemove'+namespace, function(event) { + // Update the tooltip position only if the tooltip is visible and adjustment is enabled + if(posOptions.adjust.mouse && !tooltip.hasClass(disabled) && tooltip.is(':visible')) { + self.reposition(event || MOUSE); + } + }); + } + } + } + + function unassignEvents(show, hide, tooltip, doc) + { + doc = parseInt(doc, 10) !== 0; + var namespace = '.qtip-'+id, + targets = { + show: show && options.show.target[0], + hide: hide && options.hide.target[0], + tooltip: tooltip && self.rendered && elements.tooltip[0], + content: tooltip && self.rendered && elements.content[0], + container: doc && options.position.container[0] === docBody ? document : options.position.container[0], + window: doc && window + }; + + // Check if tooltip is rendered + if(self.rendered) + { + $([]).pushStack( + $.grep( + [ targets.show, targets.hide, targets.tooltip, targets.container, targets.content, targets.window ], + function(i){ return typeof i === 'object'; } + ) + ) + .unbind(namespace); + } + + // Tooltip isn't yet rendered, remove render event + else if(show) { options.show.target.unbind(namespace+'-create'); } + } + + // Setup builtin .set() option checks + self.checks.builtin = { + // Core checks + '^id$': function(obj, o, v) { + var id = v === TRUE ? QTIP.nextid : v, + tooltipID = uitooltip + '-' + id; + + if(id !== FALSE && id.length > 0 && !$('#'+tooltipID).length) { + tooltip[0].id = tooltipID; + elements.content[0].id = tooltipID + '-content'; + elements.title[0].id = tooltipID + '-title'; + } + }, + + // Content checks + '^content.text$': function(obj, o, v){ updateContent(v); }, + '^content.title.text$': function(obj, o, v) { + // Remove title if content is null + if(!v) { return removeTitle(); } + + // If title isn't already created, create it now and update + if(!elements.title && v) { createTitle(); } + updateTitle(v); + }, + '^content.title.button$': function(obj, o, v){ updateButton(v); }, + + // Position checks + '^position.(my|at)$': function(obj, o, v){ + // Parse new corner value into Corner objecct + if('string' === typeof v) { + obj[o] = new PLUGINS.Corner(v); + } + }, + + '^position.container$': function(obj, o, v){ + if(self.rendered) { tooltip.appendTo(v); } + }, + + // Show & hide checks + '^(show|hide).(event|target|fixed|delay|inactive)$': function(obj, o, v, p, match) { + // Setup arguments + var args = [1,0,0]; + args[match[1] === 'show' ? 'push' : 'unshift'](0); + + unassignEvents.apply(self, args); + assignEvents.apply(self, [1,1,0,0]); + }, + '^show.ready$': function() { + if(!self.rendered) { self.render(1); } + else { self.show(); } + }, + + // Style checks + '^style.classes$': function(obj, o, v) { + $.attr(tooltip[0], 'class', uitooltip + ' qtip ui-helper-reset ' + v); + }, + '^style.widget|content.title': setWidget, + + // Events check + '^events.(render|show|move|hide|focus|blur)$': function(obj, o, v) { + tooltip[($.isFunction(v) ? '' : 'un') + 'bind']('tooltip'+o, v); + } + }; + + /* + * Public API methods + */ + $.extend(self, { + render: function(show) + { + if(self.rendered) { return self; } // If tooltip has already been rendered, exit + + var content = options.content.text, + title = options.content.title.text, + callback = $.Event('tooltiprender'); + + // Add ARIA attributes to target + $.attr(target[0], 'aria-describedby', tooltipID); + + // Create tooltip element + tooltip = elements.tooltip = $('
') + .attr({ + 'id': tooltipID, + 'class': uitooltip + ' qtip ui-helper-reset ' + options.style.classes, + + /* ARIA specific attributes */ + 'role': 'alert', + 'aria-live': 'polite', + 'aria-atomic': FALSE, + 'aria-describedby': tooltipID + '-content', + 'aria-hidden': TRUE + }) + .toggleClass(disabled, cache.disabled) + .data('qtip', self) + .appendTo(options.position.container) + .append( + // Create content element + elements.content = $('
', { + 'class': uitooltip + '-content', + 'id': tooltipID + '-content', + 'aria-atomic': TRUE + }) + ); + + // Set rendered flag and prevent redundant redraw calls for npw + self.rendered = -1; + isDrawing = 1; + + // Update title + if(title) { + createTitle(); + updateTitle(title); + } + + // Set proper rendered flag and update content + updateContent(content); + self.rendered = TRUE; + + // Setup widget classes + setWidget(); + + // Assign passed event callbacks (before plugins!) + $.each(options.events, function(name, callback) { + if($.isFunction(callback)) { + tooltip.bind(name === 'toggle' ? 'tooltipshow tooltiphide' : 'tooltip'+name, callback); + } + }); + + // Initialize 'render' plugins + $.each(PLUGINS, function() { + if(this.initialize === 'render') { this(self); } + }); + + // Assign events + assignEvents(1, 1, 1, 1); + + /* Queue this part of the render process in our fx queue so we can + * load images before the tooltip renders fully. + * + * See: updateContent method + */ + tooltip.queue('fx', function(next) { + // Trigger tooltiprender event and pass original triggering event as original + callback.originalEvent = cache.event; + tooltip.trigger(callback, [self]); + + // Redraw the tooltip manually now we're fully rendered + isDrawing = 0; self.redraw(); + + // Update tooltip position and show tooltip if needed + if(options.show.ready || show) { + self.show(cache.event); + } + + next(); // Move on to next method in queue + }); + + return self; + }, + + get: function(notation) + { + var result, o; + + switch(notation.toLowerCase()) + { + case 'dimensions': + result = { + height: tooltip.outerHeight(), width: tooltip.outerWidth() + }; + break; + + case 'offset': + result = PLUGINS.offset(tooltip, options.position.container); + break; + + default: + o = convertNotation(notation.toLowerCase()); + result = o[0][ o[1] ]; + result = result.precedance ? result.string() : result; + break; + } + + return result; + }, + + set: function(option, value) + { + var rmove = /^position\.(my|at|adjust|target|container)|style|content|show\.ready/i, + reposition = FALSE, + checks = self.checks, + name; + + function callback(notation, args) { + var category, rule, match; + + for(category in checks) { + for(rule in checks[category]) { + if(match = (new RegExp(rule, 'i')).exec(notation)) { + args.push(match); + checks[category][rule].apply(self, args); + } + } + } + } + + // Convert singular option/value pair into object form + if('string' === typeof option) { + name = option; option = {}; option[name] = value; + } + else { option = $.extend(TRUE, {}, option); } + + // Set all of the defined options to their new values + $.each(option, function(notation, value) { + var obj = convertNotation( notation.toLowerCase() ), previous; + + // Set new obj value + previous = obj[0][ obj[1] ]; + obj[0][ obj[1] ] = 'object' === typeof value && value.nodeType ? $(value) : value; + + // Set the new params for the callback and test it against reposition + option[notation] = [obj[0], obj[1], value, previous]; + reposition = rmove.test(notation) || reposition; + }); + + // Re-sanitize options + sanitizeOptions(options); + + /* + * Execute any valid callbacks for the set options + * Also set isPositioning/isDrawing so we don't get loads of redundant repositioning + * and redraw calls + */ + isPositioning = isDrawing = 1; $.each(option, callback); isPositioning = isDrawing = 0; + + // Update position on ANY style/position/content change if shown and rendered + if(reposition && tooltip.is(':visible') && self.rendered) { self.reposition(); } + + return self; + }, + + toggle: function(state, event) + { + // Make sure tooltip is rendered + if(!self.rendered) { + if(state) { self.render(1); } // Render the tooltip if showing and it isn't already + else { return self; } + } + + var type = state ? 'show' : 'hide', + opts = options[type], + visible = tooltip.is(':visible'), + callback; + + // Detect state if valid one isn't provided + if((typeof state).search('boolean|number')) { state = !visible; } + + // Return if element is already in correct state + if(visible === state) { return self; } + + // Try to prevent flickering when tooltip overlaps show element + if(event) { + if((/over|enter/).test(event.type) && (/out|leave/).test(cache.event.type) && + event.target === options.show.target[0] && tooltip.has(event.relatedTarget).length) { + return self; + } + + // Cache event + cache.event = $.extend({}, event); + } + + // Call API methods + callback = $.Event('tooltip'+type); + callback.originalEvent = event ? cache.event : NULL; + tooltip.trigger(callback, [self, 90]); + if(callback.isDefaultPrevented()){ return self; } + + // Set ARIA hidden status attribute + $.attr(tooltip[0], 'aria-hidden', !!!state); + + // Execute state specific properties + if(state) { + // Focus the tooltip + self.focus(event); + + // Update tooltip position + self.reposition(event); + + // Hide other tooltips if tooltip is solo, using it as the context + if(opts.solo) { $(selector, opts.solo).not(tooltip).qtip('hide', callback); } + } + else { + // Clear show timer if we're hiding + clearTimeout(self.timers.show); + + // Blur the tooltip + self.blur(event); + } + + // Define post-animation state specific properties + function after() { + if(!state) { + // Reset CSS states + tooltip.css({ + display: '', + visibility: '', + width: '', + opacity: '', + left: '', + top: '' + }); + } + else { + // Prevent antialias from disappearing in IE by removing filter + if($.browser.msie) { tooltip[0].style.removeAttribute('filter'); } + + // Remove overflow setting to prevent tip bugs + tooltip.css('overflow', ''); + } + } + + // Clear animation queue + tooltip.stop(0, 1); + + // Use custom function if provided + if($.isFunction(opts.effect)) { + opts.effect.call(tooltip, self); + tooltip.queue('fx', function(n){ after(); n(); }); + } + + // If no effect type is supplied, use a simple toggle + else if(opts.effect === FALSE) { + tooltip[ type ](); + after.call(tooltip); + } + + // Use basic fade function by default + else { tooltip.fadeTo(90, state ? 1 : 0, after); } + + // If inactive hide method is set, active it + if(state) { opts.target.trigger('qtip-'+id+'-inactive'); } + + return self; + }, + + show: function(event){ return self.toggle(TRUE, event); }, + + hide: function(event){ return self.toggle(FALSE, event); }, + + focus: function(event) + { + if(!self.rendered) { return self; } + + var qtips = $(selector), + curIndex = parseInt(tooltip[0].style.zIndex, 10), + newIndex = QTIP.zindex + qtips.length, + cachedEvent = $.extend({}, event), + focusedElem, callback; + + // Only update the z-index if it has changed and tooltip is not already focused + if(!tooltip.hasClass(focusClass)) + { + // Only update z-index's if they've changed' + if(curIndex !== newIndex) { + // Reduce our z-index's and keep them properly ordered + qtips.each(function() { + if(this.style.zIndex > curIndex) { + this.style.zIndex = this.style.zIndex - 1; + } + }); + + // Fire blur event for focused tooltip + qtips.filter('.' + focusClass).qtip('blur', cachedEvent); + } + + // Call API method + callback = $.Event('tooltipfocus'); + callback.originalEvent = cachedEvent; + tooltip.trigger(callback, [self, newIndex]); + + // If callback wasn't FALSE + if(!callback.isDefaultPrevented()) { + // Set the new z-index + tooltip.addClass(focusClass)[0].style.zIndex = newIndex; + } + } + + return self; + }, + + blur: function(event) { + var cachedEvent = $.extend({}, event), + callback; + + // Set focused status to FALSE + tooltip.removeClass(focusClass); + + // Trigger blur event + callback = $.Event('tooltipblur'); + callback.originalEvent = cachedEvent; + tooltip.trigger(callback, [self]); + + return self; + }, + + reposition: function(event, effect) + { + if(!self.rendered || isPositioning) { return self; } + + // Set positioning flag + isPositioning = 1; + + var target = options.position.target, + posOptions = options.position, + my = posOptions.my, + at = posOptions.at, + adjust = posOptions.adjust, + elemWidth = tooltip.outerWidth(), + elemHeight = tooltip.outerHeight(), + targetWidth = 0, + targetHeight = 0, + callback = $.Event('tooltipmove'), + fixed = tooltip.css('position') === 'fixed', + viewport = posOptions.viewport.jquery ? posOptions.viewport : $(window), + position = { left: 0, top: 0 }, + tip = (self.plugins.tip || {}).corner, + readjust = { + left: function(posLeft) { + var viewportScroll = viewport.scrollLeft, + myWidth = my.x === 'left' ? elemWidth : my.x === 'right' ? -elemWidth : -elemWidth / 2, + atWidth = at.x === 'left' ? targetWidth : at.x === 'right' ? -targetWidth : -targetWidth / 2, + tipAdjust = tip && tip.precedance === 'x' ? QTIP.defaults.style.tip.width : 0, + overflowLeft = viewportScroll - posLeft - tipAdjust, + overflowRight = posLeft + elemWidth - viewport.width - viewportScroll + tipAdjust, + offset = myWidth - (my.precedance === 'x' || my.x === my.y ? atWidth : 0), + isCenter = my.x === 'center'; + + if(overflowLeft > 0 && (my.x !== 'left' || overflowRight > 0)) { + position.left -= offset + (isCenter ? 0 : 2 * adjust.x); + } + else if(overflowRight > 0 && (my.x !== 'right' || overflowLeft > 0) ) { + position.left -= isCenter ? -offset : offset + (2 * adjust.x); + } + if(position.left !== posLeft && isCenter) { position.left -= adjust.x; } + + // Make sure we haven't made things worse with the adjustment and return the adjusted difference + if(position.left < 0 && -position.left > overflowRight) { position.left = posLeft; } + return position.left - posLeft; + }, + top: function(posTop) { + var viewportScroll = viewport.scrollTop, + myHeight = my.y === 'top' ? elemHeight : my.y === 'bottom' ? -elemHeight : -elemHeight / 2, + atHeight = at.y === 'top' ? targetHeight : at.y === 'bottom' ? -targetHeight : -targetHeight / 2, + tipAdjust = tip && tip.precedance === 'y' ? QTIP.defaults.style.tip.height : 0, + overflowTop = viewportScroll - posTop - tipAdjust, + overflowBottom = posTop + elemHeight - viewport.height - viewportScroll + tipAdjust, + offset = myHeight - (my.precedance === 'y' || my.x === my.y ? atHeight : 0), + isCenter = my.y === 'center'; + + if(overflowTop > 0 && (my.y !== 'top' || overflowBottom > 0)) { + position.top -= offset + (isCenter ? 0 : 2 * adjust.y); + } + else if(overflowBottom > 0 && (my.y !== 'bottom' || overflowTop > 0) ) { + position.top -= isCenter ? -offset : offset + (2 * adjust.y); + } + if(position.top !== posTop && isCenter) { position.top -= adjust.y; } + + // Make sure we haven't made things worse with the adjustment and return the adjusted difference + if(position.top < 0 && -position.top > overflowBottom) { position.top = posTop; } + return position.top - posTop; + } + }; + effect = effect === undefined || !!effect; + + // Cache our viewport details + viewport = !viewport ? FALSE : { + elem: viewport, + height: viewport[ (viewport[0] === window ? 'h' : 'outerH') + 'eight' ](), + width: viewport[ (viewport[0] === window ? 'w' : 'outerW') + 'idth' ](), + scrollLeft: viewport.scrollLeft(), + scrollTop: viewport.scrollTop() + }; + + // Check if mouse was the target + if(target === 'mouse') { + // Force left top to allow flipping + at = { x: 'left', y: 'top' }; + + // Use cached event if one isn't available for positioning + event = event && (event.type === 'resize' || event.type === 'scroll') ? cache.event : + adjust.mouse || !event || !event.pageX ? $.extend({}, MOUSE) : event; + + // Use event coordinates for position + position = { top: event.pageY, left: event.pageX }; + } + else { + // Check if event targetting is being used + if(target === 'event') { + if(event && event.target && event.type !== 'scroll' && event.type !== 'resize') { + target = cache.target = $(event.target); + } + else { + target = cache.target; + } + } + + // Parse the target into a jQuery object and make sure there's an element present + target = $(target).eq(0); + if(target.length === 0) { return self; } + + // Check if window or document is the target + else if(target[0] === document || target[0] === window) { + targetWidth = target.width(); + targetHeight = target.height(); + + if(target[0] === window) { + position = { + top: fixed ? 0 : viewport.scrollTop, + left: fixed ? 0 : viewport.scrollLeft + }; + } + } + + // Use Imagemap/SVG plugins if needed + else if(target.is('area') && PLUGINS.imagemap) { + position = PLUGINS.imagemap(target, at); + } + else if(target[0].namespaceURI == 'http://www.w3.org/2000/svg' && PLUGINS.svg) { + position = PLUGINS.svg(target, at); + } + + else { + targetWidth = target.outerWidth(); + targetHeight = target.outerHeight(); + + position = PLUGINS.offset(target, posOptions.container); + } + + // Parse returned plugin values into proper variables + if(position.offset) { + targetWidth = position.width; + targetHeight = position.height; + position = position.offset; + } + + // Adjust position relative to target + position.left += at.x === 'right' ? targetWidth : at.x === 'center' ? targetWidth / 2 : 0; + position.top += at.y === 'bottom' ? targetHeight : at.y === 'center' ? targetHeight / 2 : 0; + } + + // Adjust position relative to tooltip + position.left += adjust.x + (my.x === 'right' ? -elemWidth : my.x === 'center' ? -elemWidth / 2 : 0); + position.top += adjust.y + (my.y === 'bottom' ? -elemHeight : my.y === 'center' ? -elemHeight / 2 : 0); + + // Calculate collision offset values + if(posOptions.viewport.jquery && target[0] !== window && target[0] !== docBody) { + position.adjusted = { left: readjust.left(position.left), top: readjust.top(position.top) }; + } + else { + position.adjusted = { left: 0, top: 0 }; + } + + // Set tooltip position class + tooltip.attr('class', function(i, val) { + return $.attr(this, 'class').replace(/ui-tooltip-pos-\w+/i, ''); + }) + .addClass(uitooltip + '-pos-' + my.abbreviation()); + + // Call API method + callback.originalEvent = $.extend({}, event); + tooltip.trigger(callback, [self, position, viewport.elem]); + if(callback.isDefaultPrevented()){ return self; } + delete position.adjusted; + + // If effect is disabled or positioning gives NaN out, set CSS directly + if(!effect || !isNaN(position.left) || !isNaN(position.top)) { + tooltip.css(position); + } + + // Use custom function if provided + else if($.isFunction(posOptions.effect)) { + posOptions.effect.call(tooltip, self, $.extend({}, position)); + tooltip.queue(function(next) { + // Reset attributes to avoid cross-browser rendering bugs + $(this).css({ opacity: '', height: '' }); + if($.browser.msie) { this.style.removeAttribute('filter'); } + + next(); + }); + } + + // Set positioning flag + isPositioning = 0; + + return self; + }, + + // IMax/min width simulator function for all browsers.. yeaaah! + redraw: function() + { + if(self.rendered < 1 || isDrawing) { return self; } + + var fluid = uitooltip + '-fluid', width, max, min; + isDrawing = 1; // Set drawing flag + + // Reset the width and add the fluid class to reset max/min + tooltip.css('width', 'auto').addClass(fluid); + + // Grab our tooltip width (add 1 so we don't get wrapping problems in Gecko) + width = tooltip.width() + ($.browser.mozilla ? 1 : 0); + + // Parse our max/min properties + max = parseInt(tooltip.css('max-width'), 10) || 0; + min = parseInt(tooltip.css('min-width'), 10) || 0; + + // Determine new dimension size based on max/min/current values + width = max + min ? Math.min(Math.max(width, min), max) : width; + + // Set the newly calculated width and remvoe fluid class + tooltip.css('width', width).removeClass(fluid); + + // Set drawing flag + isDrawing = 0; + + return self; + }, + + disable: function(state) + { + var c = disabled; + + if('boolean' !== typeof state) { + state = !(tooltip.hasClass(c) || cache.disabled); + } + + if(self.rendered) { + tooltip.toggleClass(c, state); + $.attr(tooltip[0], 'aria-disabled', state); + } + else { + cache.disabled = !!state; + } + + return self; + }, + + enable: function() { return self.disable(FALSE); }, + + destroy: function() + { + var t = target[0], + title = $.attr(t, oldtitle); + + // Destroy tooltip and any associated plugins if rendered + if(self.rendered) { + tooltip.remove(); + + $.each(self.plugins, function() { + if(this.destroy) { this.destroy(); } + }); + } + + // Clear timers and remove bound events + clearTimeout(self.timers.show); + clearTimeout(self.timers.hide); + unassignEvents(1, 1, 1, 1); + + // Remove api object + $.removeData(t, 'qtip'); + + // Reset old title attribute if removed + if(title) { + $.attr(t, 'title', title); + target.removeAttr(oldtitle); + } + + // Remove ARIA attributes and bound qtip events + target.removeAttr('aria-describedby').unbind('.qtip'); + + return target; + } + }); +} + +// Initialization method +function init(id, opts) +{ + var obj, posOptions, attr, config, + + // Setup element references + elem = $(this), + docBody = $(document.body), + + // Use document body instead of document element if needed + newTarget = this === 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 + try { html5 = typeof html5 === 'string' ? (new Function("return " + html5))() : html5; } + catch(e) { debug('Unable to parse HTML5 attribute data: ' + html5); } + + // Merge in and sanitize metadata + config = $.extend(TRUE, {}, QTIP.defaults, opts, + typeof html5 === 'object' ? sanitizeOptions(html5) : NULL, + sanitizeOptions(metadata5 || metadata)); + + // Remove metadata object so we don't interfere with other metadata calls + if(metadata) { $.removeData(this, '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 === FALSE) { 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 = docBody; } + if(config.hide.target === FALSE) { config.hide.target = newTarget; } + if(config.position.viewport === TRUE) { config.position.viewport = posOptions.container; } + + // Convert position corner values into x and y strings + posOptions.at = new PLUGINS.Corner(posOptions.at); + posOptions.my = new PLUGINS.Corner(posOptions.my); + + // Destroy previous tooltip if overwrite is enabled, or skip element if not + if($.data(this, 'qtip')) { + if(config.overwrite) { + elem.qtip('destroy'); + } + else if(config.overwrite === FALSE) { + return FALSE; + } + } + + // Remove title attribute and store it if present + if($.attr(this, 'title')) { + $.attr(this, oldtitle, $.attr(this, 'title')); + this.removeAttribute('title'); + } + + // Initialize the tooltip and add API reference + obj = new QTip(elem, config, id, !!attr); + $.data(this, 'qtip', obj); + + // Catch remove events on target element to destroy redundant tooltip + elem.bind('remove.qtip', function(){ obj.destroy(); }); + + return obj; +} + +// jQuery $.fn extension method +QTIP = $.fn.qtip = function(options, notation, newValue) +{ + var command = ('' + options).toLowerCase(), // Parse command + returned = NULL, + args = command === 'disable' ? [TRUE] : $.makeArray(arguments).slice(1, 10), + event = args[args.length - 1], + opts = this[0] ? $.data(this[0], 'qtip') : 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, 'qtip'); + if(!api) { return TRUE; } + + // Cache the event if possible + if(event && event.timeStamp) { api.cache.event = event; } + + // Check for specific API commands + if((command === 'option' || command === 'options') && notation) { + if($.isPlainObject(notation) || newValue !== undefined) { + api.set(notation, newValue); + } + else { + returned = api.get(notation); + return FALSE; + } + } + + // Execute API command + else if(api[command]) { + api[command].apply(api[command], args); + } + }); + + return returned !== NULL ? returned : this; + } + + // No API commands. validate provided options and setup qTips + else if('object' === typeof options || !arguments.length) + { + opts = sanitizeOptions($.extend(TRUE, {}, options)); + + // Bind the qTips + return QTIP.bind.call(this, opts, event); + } +}; + +// $.fn.qtip Bind method +QTIP.bind = function(opts, event) +{ + return this.each(function(i) { + var options, targets, events, + + // Find next available ID, or use custom ID if provided + id = (!opts.id || opts.id === FALSE || opts.id.length < 1 || $('#'+uitooltip+'-'+opts.id).length) ? QTIP.nextid++ : opts.id, + + // Setup events namespace + namespace = '.qtip-'+id+'-create', + + // Initialize the qTip and re-grab newly sanitized options + api = init.call(this, id, opts); + if(api === FALSE) { return TRUE; } + options = api.options; + + // Initialize plugins + $.each(PLUGINS, function() { + if(this.initialize === 'initialize') { this(api); } + }); + + // Determine hide and show targets + targets = { show: options.show.target, hide: options.hide.target }; + events = { + show: $.trim('' + options.show.event).replace(/ /g, namespace+' ') + namespace, + hide: $.trim('' + options.hide.event).replace(/ /g, namespace+' ') + namespace + }; + + /* + * If hide event is just 'unfocus', we'll use mouseleave as the hide event... + * since unfocus is actually library specific and won't fire as an event anywho. + */ + if(options.hide.event === 'unfocus') { events.hide = 'mouseleave' + namespace; } + + // Define hoverIntent function + function hoverIntent(event) { + function render() { + // Cache mouse coords,render and render the tooltip + api.render(typeof event === 'object' || options.show.ready); + + // Unbind show and hide event + targets.show.unbind(events.show); + targets.hide.unbind(events.hide); + } + + // Only continue if tooltip isn't disabled + if(api.cache.disabled) { return FALSE; } + + // Cache the event data + api.cache.event = $.extend({}, event); + + // Start the event sequence + if(options.show.delay > 0) { + clearTimeout(api.timers.show); + api.timers.show = setTimeout(render, options.show.delay); + if(events.show !== events.hide) { + targets.hide.bind(events.hide, function() { clearTimeout(api.timers.show); }); + } + } + else { render(); } + } + + // Bind show events to target + targets.show.bind(events.show, hoverIntent); + + // Prerendering is enabled, create tooltip now + if(options.show.ready || options.prerender) { hoverIntent(event); } + }); +}; + +// Setup base plugins +PLUGINS = QTIP.plugins = { + // Corner object parser + Corner: function(corner) { + corner = ('' + corner).replace(/([A-Z])/, ' $1').replace(/middle/gi, 'center').toLowerCase(); + this.x = (corner.match(/left|right/i) || corner.match(/center/) || ['inherit'])[0].toLowerCase(); + this.y = (corner.match(/top|bottom|center/i) || ['inherit'])[0].toLowerCase(); + + this.precedance = (corner.charAt(0).search(/^(t|b)/) > -1) ? 'y' : 'x'; + this.string = function() { return this.precedance === 'y' ? this.y+this.x : this.x+this.y; }; + this.abbreviation = function() { + var x = this.x.substr(0,1), y = this.y.substr(0,1); + return x === y ? x : (x === 'c' || (x !== 'c' && y !== 'c')) ? y + x : x + y; + }; + }, + + // Custom (more correct for qTip!) offset calculator + offset: function(elem, container) { + var pos = elem.offset(), + parent = container, + deep = 0, + docBody = document.body, + coffset; + + function scroll(e, i) { + pos.left += i * e.scrollLeft(); + pos.top += i * e.scrollTop(); + } + + if(parent) { + // Compensate for non-static containers offset + do { + if(parent[0] === docBody) { break; } + else if(parent.css('position') !== 'static') { + coffset = parent.position(); + pos.left -= coffset.left + (parseInt(parent.css('borderLeftWidth'), 10) || 0); + pos.top -= coffset.top + (parseInt(parent.css('borderTopWidth'), 10) || 0); + + deep++; + } + } + while(parent = parent.offsetParent()); + + // Compensate for containers scroll if it also has an offsetParent + if(container[0] !== docBody || deep > 1) { scroll( container, 1 ); } + if(PLUGINS.iOS) { scroll( $(window), -1 ); } + } + + return pos; + }, + + /* + * iOS 4.0 and below scroll fix detection used in offset() function. + */ + iOS: parseFloat( + ('' + (/CPU.*OS ([0-9_]{2,3})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0,'4_2'])[1]) + .replace('undefined', '3_2').replace('_','.') + ) < 4.1, + + /* + * jQuery-secpfic $.fn overrides + */ + fn: { + /* Allow other plugins to successfully retrieve the title of an element with a qTip applied */ + attr: function(attr, val) { + if(!this.length) { return; } + + var self = this[0], + title = 'title', + api = $.data(self, 'qtip'); + + if(attr === title) { + if(arguments.length < 2) { + return $.attr(self, oldtitle); + } + else if(typeof api === 'object') { + // If qTip is rendered and title was originally used as content, update it + if(api && api.rendered && api.options.content.attr === title && api.cache.attr) { + api.set('content.text', val); + } + + // Use the regular attr method to set, then cache the result + $.fn['attr'+replaceSuffix].apply(this, arguments); + $.attr(self, oldtitle, $.attr(self, title)); + return this.removeAttr(title); + } + } + }, + + /* Allow clone to correctly retrieve cached title attributes */ + clone: function(keepData) { + var titles = $([]), title = 'title', elem; + + // Clone our element using the real clone method + elem = $.fn['clone'+replaceSuffix].apply(this, arguments) + + // Grab all elements with an oldtitle set, and change it to regular title attribute + .filter('[oldtitle]').each(function() { + $.attr(this, title, $.attr(this, oldtitle)); + this.removeAttribute(oldtitle); + }) + .end(); + + return elem; + }, + + /* + * Taken directly from jQuery 1.8.2 widget source code + * Trigger 'remove' event on all elements on removal if jQuery UI isn't present + */ + remove: $.ui ? NULL : function( selector, keepData ) { + $(this).each(function() { + if (!keepData) { + if (!selector || $.filter( selector, [ this ] ).length) { + $('*', this).add(this).each(function() { + $(this).triggerHandler('remove'); + }); + } + } + }); + } + } +}; + +// Apply the fn overrides above +$.each(PLUGINS.fn, function(name, func) { + if(!func) { return TRUE; } + + var old = $.fn[name+replaceSuffix] = $.fn[name]; + $.fn[name] = function() { + return func.apply(this, arguments) || old.apply(this, arguments); + }; +}); + +// Cache mousemove events for positioning purposes +$(window).one('load', function() { + var type = 'mousemove'; + $(document).bind(type+'.qtip', function(event) { + MOUSE = { pageX: event.pageX, pageY: event.pageY, type: type }; + }); +}); + +// Set global qTip properties +QTIP.version = '2.0.0pre'; +QTIP.nextid = 0; +QTIP.inactiveEvents = 'click dblclick mousedown mouseup mousemove mouseleave mouseenter'.split(' '); +QTIP.zindex = 15000; + +// Define configuration defaults +QTIP.defaults = { + prerender: FALSE, + id: FALSE, + overwrite: TRUE, + content: { + text: TRUE, + attr: 'title', + title: { + text: FALSE, + button: FALSE + } + }, + position: { + my: 'top left', + at: 'bottom right', + target: FALSE, + container: FALSE, + viewport: FALSE, + adjust: { + x: 0, y: 0, + mouse: TRUE, + resize: TRUE, + method: 'flip' + }, + effect: TRUE + }, + show: { + target: FALSE, + event: 'mouseenter', + effect: TRUE, + delay: 90, + solo: FALSE, + ready: FALSE + }, + hide: { + target: FALSE, + event: 'mouseleave', + effect: TRUE, + delay: 0, + fixed: FALSE, + inactive: FALSE + }, + style: { + classes: '', + widget: FALSE + }, + events: { + render: NULL, + move: NULL, + show: NULL, + hide: NULL, + toggle: NULL, + focus: NULL, + blur: NULL + } +}; +}(jQuery, window)); \ No newline at end of file diff --git a/dist/jquery.qtip.css b/dist/jquery.qtip.css index ef9deb72..6cf2e728 100644 --- a/dist/jquery.qtip.css +++ b/dist/jquery.qtip.css @@ -9,7 +9,7 @@ * http://en.wikipedia.org/wiki/MIT_License * http://en.wikipedia.org/wiki/GNU_General_Public_License * -* Date: Fri Apr 8 19:19:32 2011 +0100 +* Date: Fri Apr 8 19:25:39 2011 +0100 */ /* Fluid class for determining actual width in IE */ diff --git a/dist/jquery.qtip.js b/dist/jquery.qtip.js index 3c399dd2..1115fc62 100644 --- a/dist/jquery.qtip.js +++ b/dist/jquery.qtip.js @@ -9,7 +9,7 @@ * http://en.wikipedia.org/wiki/MIT_License * http://en.wikipedia.org/wiki/GNU_General_Public_License * -* Date: Fri Apr 8 19:19:32 2011 +0100 +* Date: Fri Apr 8 19:25:39 2011 +0100 */ "use strict"; // Enable ECMAScript "strict" operation for this function. See more: http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/ diff --git a/dist/jquery.qtip.min.js b/dist/jquery.qtip.min.js index 7d4294d8..832ff873 100644 --- a/dist/jquery.qtip.min.js +++ b/dist/jquery.qtip.min.js @@ -9,5 +9,5 @@ * http://en.wikipedia.org/wiki/MIT_License * http://en.wikipedia.org/wiki/GNU_General_Public_License * -* Date: Fri Apr 8 19:19:32 2011 +0100 +* Date: Fri Apr 8 19:25:39 2011 +0100 */"use strict",function(a,b,c){function z(b){var c=this,d=b.elements,e=d.tooltip,f=".bgiframe-"+b.id;a.extend(c,{init:function(){d.bgiframe=a(''),d.bgiframe.appendTo(e),e.bind("tooltipmove"+f,c.adjust)},adjust:function(){var a=b.get("dimensions"),c=b.plugins.tip,f=d.tip,g,h;h=parseInt(e.css("border-left-width"),10)||0,h={left:-h,top:-h},c&&f&&(g=c.corner.precedance==="x"?["width","left"]:["height","top"],h[g[1]]-=f[g[0]]()),d.bgiframe.css(h).css(a)},destroy:function(){d.bgiframe.remove(),e.unbind(f)}}),c.init()}function y(c){var f=this,h=c.options.show.modal,i=c.elements,j=i.tooltip,k="#qtip-overlay",l=".qtipmodal",m="tooltipshow"+l+" tooltiphide"+l;c.checks.modal={"^show.modal.(on|blur)$":function(){f.init(),i.overlay.toggle(j.is(":visible"))}},a.extend(f,{init:function(){h.on&&(j.unbind(l).bind(m,function(b,c,d){var e=b.type.replace("tooltip","");a.isFunction(h[e])?h[e].call(i.overlay,d,c):f[e](d)}),f.create(),h.blur===d&&i.overlay.unbind(l+c.id).bind("click"+l+c.id,function(){c.hide.call(c)}),i.overlay.css("cursor",h.blur?"pointer":""))},create:function(){var c=a(k),d;if(c.length){i.overlay=c;return c}d=i.overlay=a("
",{id:k.substr(1),css:{position:"absolute",top:0,left:0,display:"none"},mousedown:function(){return e}}).appendTo(document.body),a(b).bind("resize"+l,function(){d.css({height:Math.max(a(b).height(),a(document).height()),width:Math.max(a(b).width(),a(document).width())})}).trigger("resize");return d},toggle:function(b){var h=i.overlay,k=c.options.show.modal.effect,l=b?"show":"hide",m;h||(h=f.create());if(!h.is(":animated")||b)h.stop(d,e),b&&(m=parseInt(a.css(j[0],"z-index"),10),h.css("z-index",(m||g.zindex)-1)),a.isFunction(k)?k.call(h,b):k===e?h[l]():h.fadeTo(90,b?.7:0,function(){b||a(this).hide()})},show:function(){f.toggle(d)},hide:function(){f.toggle(e)},destroy:function(){var d=i.overlay;d&&(a(k).each(function(){var b=a(this).data("qtip");if(b&&b.id!==b.id&&b.options.show.modal)return d=e}),d?(i.overlay.remove(),a(b).unbind(l)):i.overlay.unbind(l+c.id)),j.unbind(m)}}),f.init()}function x(b,g){function v(a){var b=a.precedance==="y",c=n[b?"width":"height"],d=n[b?"height":"width"],e=a.string().indexOf("center")>-1,f=c*(e?.5:1),g=Math.pow,h=Math.round,i,j,k,l=Math.sqrt(g(f,2)+g(d,2)),m=[p/f*l,p/d*l];m[2]=Math.sqrt(g(m[0],2)-g(p,2)),m[3]=Math.sqrt(g(m[1],2)-g(p,2)),i=l+m[2]+m[3]+(e?0:m[0]),j=i/l,k=[h(j*d),h(j*c)];return{height:k[b?0:1],width:k[b?1:0]}}function u(b){var c=k.titlebar&&b.y==="top",d=c?k.titlebar:k.content,e=a.browser.mozilla,f=e?"-moz-":a.browser.webkit?"-webkit-":"",g=b.y+(e?"":"-")+b.x,h=f+(e?"border-radius-"+g:"border-"+g+"-radius");return parseInt(d.css(h),10)||parseInt(l.css(h),10)||0}function t(a,b,c){b=b?b:a[a.precedance];var d=k.titlebar&&a.y==="top",e=d?k.titlebar:k.content,f="border-"+b+"-width",g=parseInt(e.css(f),10);return(c?g||parseInt(l.css(f),10):g)||0}function s(b,e,f,g){if(k.tip){var h=a.extend({},i.corner),l=f.adjusted,n;i.corner.fixed!==d&&(l.left&&(h.x=h.x==="center"?l.left>0?"left":"right":h.x==="left"?"right":"left"),l.top&&(h.y=h.y==="center"?l.top>0?"top":"bottom":h.y==="top"?"bottom":"top"),h.string()!==m.corner&&(m.top!==l.top||m.left!==l.left)&&(n=i.update(h))),n||(n=i.position(h,0)),n.right!==c&&(n.left=n.right),n.bottom!==c&&(n.top=n.bottom),n.option=Math.max(0,j.offset),f.left-=n.left.charAt?n.option:(n.right?-1:1)*n.left,f.top-=n.top.charAt?n.option:(n.bottom?-1:1)*n.top,m.left=l.left,m.top=l.top,m.corner=h.string()}}var i=this,j=b.options.style.tip,k=b.elements,l=k.tooltip,m={top:0,left:0,corner:""},n={width:j.width,height:j.height},o={},p=j.border||0,q=".qtip-tip",r=a("")[0].getContext;i.corner=f,i.mimic=f,b.checks.tip={"^position.my|style.tip.(corner|mimic|border)$":function(){i.init()||i.destroy(),b.reposition()},"^style.tip.(height|width)$":function(){n={width:j.width,height:j.height},i.create(),i.update(),b.reposition()},"^content.title.text|style.(classes|widget)$":function(){k.tip&&i.update()}},a.extend(i,{init:function(){var b=i.detectCorner()&&(r||a.browser.msie);b&&(i.create(),i.update(),l.unbind(q).bind("tooltipmove"+q,s));return b},detectCorner:function(){var a=j.corner,c=b.options.position,f=c.at,g=c.my.string?c.my.string():c.my;if(a===e||g===e&&f===e)return e;a===d?i.corner=new h.Corner(g):a.string||(i.corner=new h.Corner(a),i.corner.fixed=d);return i.corner.string()!=="centercenter"},detectColours:function(){var c,d,e,f=k.tip.css({backgroundColor:"",border:""}),g=i.corner,h=g[g.precedance],m="border-"+h+"-color",p="border"+h.charAt(0)+h.substr(1)+"Color",q=/rgba?\(0, 0, 0(, 0)?\)|transparent/i,r="background-color",s="transparent",t="ui-tooltip-fluid",u=a(document.body).css("color"),v=b.elements.content.css("color"),w=k.titlebar&&(g.y==="top"||g.y==="center"&&f.position().top+n.height/2+j.offset",{"class":"ui-tooltip-tip"}).css({width:b,height:c}).prependTo(l),r?a("").appendTo(k.tip)[0].getContext("2d").save():(d='',k.tip.html(p?d+=d:d))},update:function(b){var c=k.tip,g=c.children(),l=n.width,m=n.height,q="px solid ",s="px dashed transparent",u=j.mimic,x=Math.round,y,z,A,B,C;b||(b=i.corner),u===e?u=b:(u=new h.Corner(u),u.precedance=b.precedance,u.x==="inherit"?u.x=b.x:u.y==="inherit"?u.y=b.y:u.x===u.y&&(u[b.precedance]=b[b.precedance])),y=u.precedance,i.detectColours(),p=o.border==="transparent"||o.border==="#123456"?0:j.border===d?t(b,f,d):j.border,A=w(u,l,m),C=v(b),c.css(C),b.precedance==="y"?B=[x(u.x==="left"?p:u.x==="right"?C.width-l-p:(C.width-l)/2),x(u.y==="top"?C.height-m:0)]:B=[x(u.x==="left"?C.width-l:0),x(u.y==="top"?p:u.y==="bottom"?C.height-m-p:(C.height-m)/2)],r?(g.attr(C),z=g[0].getContext("2d"),z.restore(),z.save(),z.clearRect(0,0,3e3,3e3),z.translate(B[0],B[1]),z.beginPath(),z.moveTo(A[0][0],A[0][1]),z.lineTo(A[1][0],A[1][1]),z.lineTo(A[2][0],A[2][1]),z.closePath(),z.fillStyle=o.fill,z.strokeStyle=o.border,z.lineWidth=p*2,z.lineJoin="miter",z.miterLimit=100,z.stroke(),z.fill()):(A="m"+A[0][0]+","+A[0][1]+" l"+A[1][0]+","+A[1][1]+" "+A[2][0]+","+A[2][1]+" xe",B[2]=p&&/^(r|b)/i.test(b.string())?parseFloat(a.browser.version,10)===8?2:1:0,g.css({antialias:""+(u.string().indexOf("center")>-1),left:B[0]-B[2]*Number(y==="x"),top:B[1]-B[2]*Number(y==="y"),width:l+p,height:m+p}).each(function(b){var c=a(this);c.attr({coordsize:l+p+" "+(m+p),path:A,fillcolor:o.fill,filled:!!b,stroked:!b}).css({display:p||b?"block":"none"}),!b&&p>0&&c.html()===""&&c.html('')}));return i.position(b,1)},position:function(b,c){var f=k.tip,g={},h=Math.max(0,j.offset),l,m,n;if(j.corner===e||!f)return e;b=b||i.corner,l=b.precedance,m=v(b),n=a.browser.msie&&parseFloat(a.browser.version,10)==8&&p&&/^(b|r)/i.test(b.string())?1:0,a.each(l==="y"?[b.x,b.y]:[b.y,b.x],function(a,c){var e,f;c==="center"?(e=l==="y"?"left":"top",g[e]="50%",g["margin-"+e]=-Math.round(m[l==="y"?"width":"height"]/2)+h):(e=t(b,c,d),f=u(b),g[c]=a||!p?t(b,c)+(a?0:f):h+(f>e?f:0))}),g[b[l]]-=m[l==="x"?"width":"height"]+n,c&&f.css({top:"",bottom:"",left:"",right:"",margin:""}).css(g);return g},destroy:function(){k.tip&&k.tip.remove(),l.unbind(q)}}),i.init()}function w(a,b,c){var d=Math.ceil(b/2),e=Math.ceil(c/2),f={bottomright:[[0,0],[b,c],[b,0]],bottomleft:[[0,0],[b,0],[0,c]],topright:[[0,c],[b,0],[b,c]],topleft:[[0,0],[0,c],[b,c]],topcenter:[[0,c],[d,0],[b,c]],bottomcenter:[[0,0],[b,0],[d,c]],rightcenter:[[0,0],[b,e],[0,c]],leftcenter:[[b,0],[b,c],[0,e]]};f.lefttop=f.bottomright,f.righttop=f.bottomleft,f.leftbottom=f.topright,f.rightbottom=f.topleft;return f[a.string()]}function v(b){var c=this,f=b.elements.tooltip,g=b.options.content.ajax,h=".qtip-ajax",i=/)<[^<]*)*<\/script>/gi,j=d;b.checks.ajax={"^content.ajax":function(a,b,d){b==="ajax"&&(g=d),b==="once"?(f.unbind(h),d&&f.bind("tooltipshow"+h,c.load)):g&&g.url?c.load():f.unbind(h)}},a.extend(c,{init:function(){g&&g.url&&f.bind("tooltipshow"+h,c.load);return c},load:function(d,h){function p(a,c,d){b.set("content.text",c+": "+d),n()}function o(c){l&&(c=a("
").append(c.replace(i,"")).find(l)),b.set("content.text",c),n()}function n(){m&&(f.css("visibility",""),h=e)}if(d.isDefaultPrevented())return c;var j=g.url.indexOf(" "),k=g.url,l,m=g.once&&!g.loading&&h;m&&f.css("visibility","hidden"),j>-1&&(l=k.substr(j),k=k.substr(0,j)),a.ajax(a.extend({success:o,error:p,context:b},g,{url:k}));return c}}),c.init()}function u(b,c){var i,j,k,l,m=a(this),n=a(document.body),o=this===document?n:m,p=m.metadata?m.metadata(c.metadata):f,u=c.metadata.type==="html5"&&p?p[c.metadata.name]:f,v=m.data(c.metadata.name||"qtipopts");try{v=typeof v==="string"?(new Function("return "+v))():v}catch(w){r("Unable to parse HTML5 attribute data: "+v)}l=a.extend(d,{},g.defaults,c,typeof v==="object"?s(v):f,s(u||p)),p&&a.removeData(this,"metadata"),j=l.position,l.id=b;if("boolean"===typeof l.content.text){k=m.attr(l.content.attr);if(l.content.attr!==e&&k)l.content.text=k;else return e}j.container===e&&(j.container=n),j.target===e&&(j.target=o),l.show.target===e&&(l.show.target=o),l.show.solo===d&&(l.show.solo=n),l.hide.target===e&&(l.hide.target=o),l.position.viewport===d&&(l.position.viewport=j.container),j.at=new h.Corner(j.at),j.my=new h.Corner(j.my);if(a.data(this,"qtip"))if(l.overwrite)m.qtip("destroy");else if(l.overwrite===e)return e;a.attr(this,"title")&&(a.attr(this,q,a.attr(this,"title")),this.removeAttribute("title")),i=new t(m,l,b,!!k),a.data(this,"qtip",i),m.bind("remove.qtip",function(){i.destroy()});return i}function t(o,p,r,t){function L(c,d,e,f){f=parseInt(f,10)!==0;var g=".qtip-"+r,h={show:c&&p.show.target[0],hide:d&&p.hide.target[0],tooltip:e&&u.rendered&&A.tooltip[0],content:e&&u.rendered&&A.content[0],container:f&&p.position.container[0]===v?document:p.position.container[0],window:f&&b};u.rendered?a([]).pushStack(a.grep([h.show,h.hide,h.tooltip,h.container,h.content,h.window],function(a){return typeof a==="object"})).unbind(g):c&&p.show.target.unbind(g+"-create")}function K(c,d,f,h){function y(a){z.is(":visible")&&u.reposition(a)}function x(a){if(z.hasClass(l))return e;clearTimeout(u.timers.inactive),u.timers.inactive=setTimeout(function(){u.hide(a)},p.hide.inactive)}function w(b){if(z.hasClass(l))return e;var c=a(b.relatedTarget||b.target),d=c.closest(m)[0]===z[0],f=c[0]===n.show[0];clearTimeout(u.timers.show),clearTimeout(u.timers.hide);if(k.target==="mouse"&&d||p.hide.fixed&&(/mouse(out|leave|move)/.test(b.type)&&(d||f))){b.stopPropagation(),b.preventDefault();return e}p.hide.delay>0?u.timers.hide=setTimeout(function(){u.hide(b)},p.hide.delay):u.hide(b)}function t(a){if(z.hasClass(l))return e;n.show.trigger("qtip-"+r+"-inactive"),clearTimeout(u.timers.show),clearTimeout(u.timers.hide);var b=function(){u.show(a)};p.show.delay>0?u.timers.show=setTimeout(b,p.show.delay):b()}var j=".qtip-"+r,k=p.position,n={show:p.show.target,hide:p.hide.target,container:k.container[0]===v?a(document):k.container,doc:a(document)},q={show:a.trim(""+p.show.event).split(" "),hide:a.trim(""+p.hide.event).split(" ")},s=a.browser.msie&&parseInt(a.browser.version,10)===6;f&&(p.hide.fixed&&(n.hide=n.hide.add(z),z.bind("mouseover"+j,function(){z.hasClass(l)||clearTimeout(u.timers.hide)})),k.target==="mouse"&&k.adjust.mouse&&p.hide.event&&z.bind("mouseleave"+j,function(a){(a.relatedTarget||a.target)!==n.show[0]&&u.hide(a)}),z.bind("mouseenter"+j+" mouseleave"+j,function(a){u[a.type==="mouseenter"?"focus":"blur"](a)})),d&&("number"===typeof p.hide.inactive&&(n.show.bind("qtip-"+r+"-inactive",x),a.each(g.inactiveEvents,function(a,b){n.hide.add(A.tooltip).bind(b+j+"-inactive",x)})),a.each(q.hide,function(b,c){var d=a.inArray(c,q.show),e=a(n.hide);d>-1&&e.add(n.show).length===e.length||c==="unfocus"?(n.show.bind(c+j,function(a){z.is(":visible")?w(a):t(a)}),delete q.show[d]):n.hide.bind(c+j,w)})),c&&a.each(q.show,function(a,b){n.show.bind(b+j,t)}),h&&((k.adjust.resize||k.viewport)&&a(a.event.special.resize?k.viewport:b).bind("resize"+j,y),(k.viewport||s&&z.css("position")==="fixed")&&a(k.viewport).bind("scroll"+j,y),/unfocus/i.test(p.hide.event)&&n.doc.bind("mousedown"+j,function(b){var c=a(b.target);c.parents(m).length===0&&c.add(o).length>1&&z.is(":visible")&&!z.hasClass(l)&&u.hide(b)}),/mouseleave|mouseout/i.test(p.hide.event)&&a(b).bind("blur mouseout",function(a){a.relatedTarget||u.hide(a)}),k.target==="mouse"&&n.doc.bind("mousemove"+j,function(a){k.adjust.mouse&&!z.hasClass(l)&&z.is(":visible")&&u.reposition(a||i)}))}function J(b,c){function g(a){function c(c,d){(b=b.not(this)).length===0&&(u.redraw(),u.reposition(B.event),a())}var b;if((b=d.find("img:not([height]):not([width])")).length===0)return c.call(b);b.one(["abort","error","load","unload",""].join(".qtip-image "),c).each(function(a,b){(function d(){if(b.height&&b.width)return c.call(b,f);u.timers.img[a]=setTimeout(d,20)})()})}var d=A.content;if(!u.rendered||!b)return e;a.isFunction(b)&&(b=b.call(o,u)||""),b.jquery&&b.length>0?d.empty().append(b.css({display:"block"})):d.html(b),u.rendered<0?z.queue("fx",g):(y=0,g(a.noop));return u}function I(b){var c=A.title;if(!u.rendered||!b)return e;a.isFunction(b)&&(b=b.call(o,u)||""),b.jquery&&b.length>0?c.empty().append(b.css({display:"block"})):c.html(b),u.redraw(),u.rendered&&z.is(":visible")&&u.reposition(B.event)}function H(a){var b=A.button,c=A.title;if(!u.rendered)return e;a?(c||G(),F()):b.remove()}function G(){var b=w+"-title";A.titlebar&&E(),A.titlebar=a("
",{"class":j+"-titlebar "+(p.style.widget?"ui-widget-header":"")}).append(A.title=a("
",{id:b,"class":j+"-title","aria-atomic":d})).insertBefore(A.content),p.content.title.button?F():u.rendered&&u.redraw()}function F(){var b=p.content.title.button,c=typeof b==="string",d=c?b:"Close tooltip";A.button&&A.button.remove(),b.jquery?A.button=b:A.button=a("",{"class":"ui-state-default "+(p.style.widget?"":j+"-icon"),title:d,"aria-label":d}).prepend(a("",{"class":"ui-icon ui-icon-close",html:"×"})),A.button.appendTo(A.titlebar).attr("role","button").hover(function(b){a(this).toggleClass("ui-state-hover",b.type==="mouseenter")}).click(function(a){z.hasClass(l)||u.hide(a);return e}).bind("mousedown keydown mouseup keyup mouseout",function(b){a(this).toggleClass("ui-state-active ui-state-focus",b.type.substr(-4)==="down")}),u.redraw()}function E(){A.title&&(A.titlebar.remove(),A.titlebar=A.title=A.button=f,u.reposition())}function D(){var a=p.style.widget;z.toggleClass(k,a),A.content.toggleClass(k+"-content",a),A.titlebar&&A.titlebar.toggleClass(k+"-header",a),A.button&&A.button.toggleClass(j+"-icon",!a)}function C(a){var b=0,c,d=p,e=a.split(".");while(d=d[e[b++]])b0&&!a("#"+i).length&&(z[0].id=i,A.content[0].id=i+"-content",A.title[0].id=i+"-title")},"^content.text$":function(a,b,c){J(c)},"^content.title.text$":function(a,b,c){if(!c)return E();!A.title&&c&&G(),I(c)},"^content.title.button$":function(a,b,c){H(c)},"^position.(my|at)$":function(a,b,c){"string"===typeof c&&(a[b]=new h.Corner(c))},"^position.container$":function(a,b,c){u.rendered&&z.appendTo(c)},"^(show|hide).(event|target|fixed|delay|inactive)$":function(a,b,c,d,e){var f=[1,0,0];f[e[1]==="show"?"push":"unshift"](0),L.apply(u,f),K.apply(u,[1,1,0,0])},"^show.ready$":function(){u.rendered?u.show():u.render(1)},"^style.classes$":function(b,c,d){a.attr(z[0],"class",j+" qtip ui-helper-reset "+d)},"^style.widget|content.title":D,"^events.(render|show|move|hide|focus|blur)$":function(b,c,d){z[(a.isFunction(d)?"":"un")+"bind"]("tooltip"+c,d)}},a.extend(u,{render:function(b){if(u.rendered)return u;var c=p.content.text,f=p.content.title.text,g=a.Event("tooltiprender");a.attr(o[0],"aria-describedby",w),z=A.tooltip=a("
").attr({id:w,"class":j+" qtip ui-helper-reset "+p.style.classes,role:"alert","aria-live":"polite","aria-atomic":e,"aria-describedby":w+"-content","aria-hidden":d}).toggleClass(l,B.disabled).data("qtip",u).appendTo(p.position.container).append(A.content=a("
",{"class":j+"-content",id:w+"-content","aria-atomic":d})),u.rendered=-1,y=1,f&&(G(),I(f)),J(c),u.rendered=d,D(),a.each(p.events,function(b,c){a.isFunction(c)&&z.bind(b==="toggle"?"tooltipshow tooltiphide":"tooltip"+b,c)}),a.each(h,function(){this.initialize==="render"&&this(u)}),K(1,1,1,1),z.queue("fx",function(a){g.originalEvent=B.event,z.trigger(g,[u]),y=0,u.redraw(),(p.show.ready||b)&&u.show(B.event),a()});return u},get:function(a){var b,c;switch(a.toLowerCase()){case"dimensions":b={height:z.outerHeight(),width:z.outerWidth()};break;case"offset":b=h.offset(z,p.position.container);break;default:c=C(a.toLowerCase()),b=c[0][c[1]],b=b.precedance?b.string():b}return b},set:function(b,c){function j(a,b){var c,d,e;for(c in h)for(d in h[c])if(e=(new RegExp(d,"i")).exec(a))b.push(e),h[c][d].apply(u,b)}var f=/^position\.(my|at|adjust|target|container)|style|content|show\.ready/i,g=e,h=u.checks,i;"string"===typeof b?(i=b,b={},b[i]=c):b=a.extend(d,{},b),a.each(b,function(c,d){var e=C(c.toLowerCase()),h;h=e[0][e[1]],e[0][e[1]]="object"===typeof d&&d.nodeType?a(d):d,b[c]=[e[0],e[1],d,h],g=f.test(c)||g}),s(p),x=y=1,a.each(b,j),x=y=0,g&&z.is(":visible")&&u.rendered&&u.reposition();return u},toggle:function(b,c){function j(){b?(a.browser.msie&&z[0].style.removeAttribute("filter"),z.css("overflow","")):z.css({display:"",visibility:"",width:"",opacity:"",left:"",top:""})}if(!u.rendered)if(b)u.render(1);else return u;var d=b?"show":"hide",g=p[d],h=z.is(":visible"),i;(typeof b).search("boolean|number")&&(b=!h);if(h===b)return u;if(c){if(/over|enter/.test(c.type)&&/out|leave/.test(B.event.type)&&c.target===p.show.target[0]&&z.has(c.relatedTarget).length)return u;B.event=a.extend({},c)}i=a.Event("tooltip"+d),i.originalEvent=c?B.event:f,z.trigger(i,[u,90]);if(i.isDefaultPrevented())return u;a.attr(z[0],"aria-hidden",!b),b?(u.focus(c),u.reposition(c),g.solo&&a(m,g.solo).not(z).qtip("hide",i)):(clearTimeout(u.timers.show),u.blur(c)),z.stop(0,1),a.isFunction(g.effect)?(g.effect.call(z,u),z.queue("fx",function(a){j(),a()})):g.effect===e?(z[d](),j.call(z)):z.fadeTo(90,b?1:0,j),b&&g.target.trigger("qtip-"+r+"-inactive");return u},show:function(a){return u.toggle(d,a)},hide:function(a){return u.toggle(e,a)},focus:function(b){if(!u.rendered)return u;var c=a(m),d=parseInt(z[0].style.zIndex,10),e=g.zindex+c.length,f=a.extend({},b),h,i;z.hasClass(n)||(d!==e&&(c.each(function(){this.style.zIndex>d&&(this.style.zIndex=this.style.zIndex-1)}),c.filter("."+n).qtip("blur",f)),i=a.Event("tooltipfocus"),i.originalEvent=f,z.trigger(i,[u,e]),i.isDefaultPrevented()||(z.addClass(n)[0].style.zIndex=e));return u},blur:function(b){var c=a.extend({},b),d;z.removeClass(n),d=a.Event("tooltipblur"),d.originalEvent=c,z.trigger(d,[u]);return u},reposition:function(d,f){if(!u.rendered||x)return u;x=1;var k=p.position.target,l=p.position,m=l.my,n=l.at,o=l.adjust,q=z.outerWidth(),r=z.outerHeight(),s=0,t=0,w=a.Event("tooltipmove"),y=z.css("position")==="fixed",A=l.viewport.jquery?l.viewport:a(b),C={left:0,top:0},D=(u.plugins.tip||{}).corner,E={left:function(a){var b=A.scrollLeft,c=m.x==="left"?q:m.x==="right"?-q:-q/2,d=n.x==="left"?s:n.x==="right"?-s:-s/2,e=D&&D.precedance==="x"?g.defaults.style.tip.width:0,f=b-a-e,h=a+q-A.width-b+e,i=c-(m.precedance==="x"||m.x===m.y?d:0),j=m.x==="center";f>0&&(m.x!=="left"||h>0)?C.left-=i+(j?0:2*o.x):h>0&&(m.x!=="right"||f>0)&&(C.left-=j?-i:i+2*o.x),C.left!==a&&j&&(C.left-=o.x),C.left<0&&-C.left>h&&(C.left=a);return C.left-a},top:function(a){var b=A.scrollTop,c=m.y==="top"?r:m.y==="bottom"?-r:-r/2,d=n.y==="top"?t:n.y==="bottom"?-t:-t/2,e=D&&D.precedance==="y"?g.defaults.style.tip.height:0,f=b-a-e,h=a+r-A.height-b+e,i=c-(m.precedance==="y"||m.x===m.y?d:0),j=m.y==="center";f>0&&(m.y!=="top"||h>0)?C.top-=i+(j?0:2*o.y):h>0&&(m.y!=="bottom"||f>0)&&(C.top-=j?-i:i+2*o.y),C.top!==a&&j&&(C.top-=o.y),C.top<0&&-C.top>h&&(C.top=a);return C.top-a}};f=f===c||!!f,A=A?{elem:A,height:A[(A[0]===b?"h":"outerH")+"eight"](),width:A[(A[0]===b?"w":"outerW")+"idth"](),scrollLeft:A.scrollLeft(),scrollTop:A.scrollTop()}:e;if(k==="mouse")n={x:"left",y:"top"},d=d&&(d.type==="resize"||d.type==="scroll")?B.event:o.mouse||!d||!d.pageX?a.extend({},i):d,C={top:d.pageY,left:d.pageX};else{k==="event"&&(d&&d.target&&d.type!=="scroll"&&d.type!=="resize"?k=B.target=a(d.target):k=B.target),k=a(k).eq(0);if(k.length===0)return u;k[0]===document||k[0]===b?(s=k.width(),t=k.height(),k[0]===b&&(C={top:y?0:A.scrollTop,left:y?0:A.scrollLeft})):k.is("area")&&h.imagemap?C=h.imagemap(k,n):k[0].namespaceURI=="http://www.w3.org/2000/svg"&&h.svg?C=h.svg(k,n):(s=k.outerWidth(),t=k.outerHeight(),C=h.offset(k,l.container)),C.offset&&(s=C.width,t=C.height,C=C.offset),C.left+=n.x==="right"?s:n.x==="center"?s/2:0,C.top+=n.y==="bottom"?t:n.y==="center"?t/2:0}C.left+=o.x+(m.x==="right"?-q:m.x==="center"?-q/2:0),C.top+=o.y+(m.y==="bottom"?-r:m.y==="center"?-r/2:0),l.viewport.jquery&&k[0]!==b&&k[0]!==v?C.adjusted={left:E.left(C.left),top:E.top(C.top)}:C.adjusted={left:0,top:0},z.attr("class",function(b,c){return a.attr(this,"class").replace(/ui-tooltip-pos-\w+/i,"")}).addClass(j+"-pos-"+m.abbreviation()),w.originalEvent=a.extend({},d),z.trigger(w,[u,C,A.elem]);if(w.isDefaultPrevented())return u;delete C.adjusted,f&&isNaN(C.left)&&isNaN(C.top)?a.isFunction(l.effect)&&(l.effect.call(z,u,a.extend({},C)),z.queue(function(b){a(this).css({opacity:"",height:""}),a.browser.msie&&this.style.removeAttribute("filter"),b()})):z.css(C),x=0;return u},redraw:function(){if(u.rendered<1||y)return u;var b=j+"-fluid",c,d,e;y=1,z.css("width","auto").addClass(b),c=z.width()+(a.browser.mozilla?1:0),d=parseInt(z.css("max-width"),10)||0,e=parseInt(z.css("min-width"),10)||0,c=d+e?Math.min(Math.max(c,e),d):c,z.css("width",c).removeClass(b),y=0;return u},disable:function(b){var c=l;"boolean"!==typeof b&&(b=!z.hasClass(c)&&!B.disabled),u.rendered?(z.toggleClass(c,b),a.attr(z[0],"aria-disabled",b)):B.disabled=!!b;return u},enable:function(){return u.disable(e)},destroy:function(){var b=o[0],c=a.attr(b,q);u.rendered&&(z.remove(),a.each(u.plugins,function(){this.destroy&&this.destroy()})),clearTimeout(u.timers.show),clearTimeout(u.timers.hide),L(1,1,1,1),a.removeData(b,"qtip"),c&&(a.attr(b,"title",c),o.removeAttr(q)),o.removeAttr("aria-describedby").unbind(".qtip");return o}})}function s(b){var c;if(!b||"object"!==typeof b)return e;"object"!==typeof b.metadata&&(b.metadata={type:b.metadata});if("content"in b){if("object"!==typeof b.content||b.content.jquery)b.content={text:b.content};c=b.content.text||e,!a.isFunction(c)&&(!c&&!c.attr||c.length<1||"object"===typeof c&&!c.jquery)&&(b.content.text=e),"title"in b.content&&("object"!==typeof b.content.title&&(b.content.title={text:b.content.title}),c=b.content.title.text||e,!a.isFunction(c)&&(!c&&!c.attr||c.length<1||"object"===typeof c&&!c.jquery)&&(b.content.title.text=e))}"position"in b&&("object"!==typeof b.position&&(b.position={my:b.position,at:b.position})),"show"in b&&("object"!==typeof b.show&&(b.show.jquery?b.show={target:b.show}:b.show={event:b.show})),"hide"in b&&("object"!==typeof b.hide&&(b.hide.jquery?b.hide={target:b.hide}:b.hide={event:b.hide})),"style"in b&&("object"!==typeof b.style&&(b.style={classes:b.style})),a.each(h,function(){this.sanitize&&this.sanitize(b)});return b}function r(){var c=b.console;return c&&(c.error||c.log||a.noop).apply(c,arguments)}var d=!0,e=!1,f=null,g,h,i,j="ui-tooltip",k="ui-widget",l="ui-state-disabled",m="div.qtip."+j,n=j+"-focus",o="-31000px",p="_replacedByqTip",q="oldtitle";g=a.fn.qtip=function(b,h,i){var j=(""+b).toLowerCase(),k=f,l=j==="disable"?[d]:a.makeArray(arguments).slice(1,10),m=l[l.length-1],n=this[0]?a.data(this[0],"qtip"):f;if(!arguments.length&&n||j==="api")return n;if("string"===typeof b){this.each(function(){var b=a.data(this,"qtip");if(!b)return d;m&&m.timeStamp&&(b.cache.event=m);if(j!=="option"&&j!=="options"||!h)b[j]&&b[j].apply(b[j],l);else if(a.isPlainObject(h)||i!==c)b.set(h,i);else{k=b.get(h);return e}});return k!==f?k:this}if("object"===typeof b||!arguments.length){n=s(a.extend(d,{},b));return g.bind.call(this,n,m)}},g.bind=function(b,c){return this.each(function(f){function p(b){function c(){o.render(typeof b==="object"||i.show.ready),k.show.unbind(l.show),k.hide.unbind(l.hide)}if(o.cache.disabled)return e;o.cache.event=a.extend({},b),i.show.delay>0?(clearTimeout(o.timers.show),o.timers.show=setTimeout(c,i.show.delay),l.show!==l.hide&&k.hide.bind(l.hide,function(){clearTimeout(o.timers.show)})):c()}var i,k,l,m=!b.id||b.id===e||b.id.length<1||a("#"+j+"-"+b.id).length?g.nextid++:b.id,n=".qtip-"+m+"-create",o=u.call(this,m,b);if(o===e)return d;i=o.options,a.each(h,function(){this.initialize==="initialize"&&this(o)}),k={show:i.show.target,hide:i.hide.target},l={show:a.trim(""+i.show.event).replace(/ /g,n+" ")+n,hide:a.trim(""+i.hide.event).replace(/ /g,n+" ")+n},i.hide.event==="unfocus"&&(l.hide="mouseleave"+n),k.show.bind(l.show,p),(i.show.ready||i.prerender)&&p(c)})},h=g.plugins={Corner:function(a){a=(""+a).replace(/([A-Z])/," $1").replace(/middle/gi,"center").toLowerCase(),this.x=(a.match(/left|right/i)||a.match(/center/)||["inherit"])[0].toLowerCase(),this.y=(a.match(/top|bottom|center/i)||["inherit"])[0].toLowerCase(),this.precedance=a.charAt(0).search(/^(t|b)/)>-1?"y":"x",this.string=function(){return this.precedance==="y"?this.y+this.x:this.x+this.y},this.abbreviation=function(){var a=this.x.substr(0,1),b=this.y.substr(0,1);return a===b?a:a==="c"||a!=="c"&&b!=="c"?b+a:a+b}},offset:function(c,d){function k(a,b){e.left+=b*a.scrollLeft(),e.top+=b*a.scrollTop()}var e=c.offset(),f=d,g=0,i=document.body,j;if(f){do{if(f[0]===i)break;f.css("position")!=="static"&&(j=f.position(),e.left-=j.left+(parseInt(f.css("borderLeftWidth"),10)||0),e.top-=j.top+(parseInt(f.css("borderTopWidth"),10)||0),g++)}while(f=f.offsetParent());(d[0]!==i||g>1)&&k(d,1),h.iOS&&k(a(b),-1)}return e},iOS:parseFloat((""+(/CPU.*OS ([0-9_]{2,3})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent)||[0,"4_2"])[1]).replace("undefined","3_2").replace("_","."))<4.1,fn:{attr:function(b,c){if(this.length){var d=this[0],e="title",f=a.data(d,"qtip");if(b===e){if(arguments.length<2)return a.attr(d,q);if(typeof f==="object"){f&&f.rendered&&f.options.content.attr===e&&f.cache.attr&&f.set("content.text",c),a.fn["attr"+p].apply(this,arguments),a.attr(d,q,a.attr(d,e));return this.removeAttr(e)}}}},clone:function(b){var c=a([]),d="title",e;e=a.fn["clone"+p].apply(this,arguments).filter("[oldtitle]").each(function(){a.attr(this,d,a.attr(this,q)),this.removeAttribute(q)}).end();return e},remove:a.ui?f:function(b,c){a(this).each(function(){c||(!b||a.filter(b,[this]).length)&&a("*",this).add(this).each(function(){a(this).triggerHandler("remove")})})}}},a.each(h.fn,function(b,c){if(!c)return d;var e=a.fn[b+p]=a.fn[b];a.fn[b]=function(){return c.apply(this,arguments)||e.apply(this,arguments)}}),a(b).one("load",function(){var b="mousemove";a(document).bind(b+".qtip",function(a){i={pageX:a.pageX,pageY:a.pageY,type:b}})}),g.version="2.0.0pre",g.nextid=0,g.inactiveEvents="click dblclick mousedown mouseup mousemove mouseleave mouseenter".split(" "),g.zindex=15e3,g.defaults={prerender:e,id:e,overwrite:d,content:{text:d,attr:"title",title:{text:e,button:e}},position:{my:"top left",at:"bottom right",target:e,container:e,viewport:e,adjust:{x:0,y:0,mouse:d,resize:d,method:"flip"},effect:d},show:{target:e,event:"mouseenter",effect:d,delay:90,solo:e,ready:e},hide:{target:e,event:"mouseleave",effect:d,delay:0,fixed:e,inactive:e},style:{classes:"",widget:e},events:{render:f,move:f,show:f,hide:f,toggle:f,focus:f,blur:f}},h.ajax=function(a){var b=a.plugins.ajax;return"object"===typeof b?b:a.plugins.ajax=new v(a)},h.ajax.initialize="render",h.ajax.sanitize=function(a){var b=a.content,c;b&&"ajax"in b&&(c=b.ajax,typeof c!=="object"&&(c=a.content.ajax={url:c}),"boolean"!==typeof c.once&&c.once&&(c.once=!!c.once))},a.extend(d,g.defaults,{content:{ajax:{loading:d,once:d}}}),h.tip=function(a){var b=a.plugins.tip;return"object"===typeof b?b:a.plugins.tip=new x(a)},h.tip.initialize="render",h.tip.sanitize=function(a){var b=a.style,c;b&&"tip"in b&&(c=a.style.tip,typeof c!=="object"&&(a.style.tip={corner:c}),/string|boolean/i.test(typeof c.corner)||(c.corner=d),typeof c.width!=="number"&&delete c.width,typeof c.height!=="number"&&delete c.height,typeof c.border!=="number"&&c.border!==d&&delete c.border,typeof c.offset!=="number"&&delete c.offset)},a.extend(d,g.defaults,{style:{tip:{corner:d,mimic:e,width:6,height:6,border:d,offset:0}}}),h.imagemap=function(b,c){function l(a,b){var d=0,e=1,f=1,g=0,h=0,i=a.width,j=a.height;while(i>0&&j>0&&e>0&&f>0){i=Math.floor(i/2),j=Math.floor(j/2),c.x==="left"?e=i:c.x==="right"?e=a.width-i:e+=Math.floor(i/2),c.y==="top"?f=j:c.y==="bottom"?f=a.height-j:f+=Math.floor(j/2),d=b.length;while(d--){if(b.length<2)break;g=b[d][0]-a.offset.left,h=b[d][1]-a.offset.top,(c.x==="left"&&g>=e||c.x==="right"&&g<=e||c.x==="center"&&(ga.width-e)||c.y==="top"&&h>=f||c.y==="bottom"&&h<=f||c.y==="center"&&(ha.height-f))&&b.splice(d,1)}}return{left:b[0][0],top:b[0][1]}}var d=b.attr("shape").toLowerCase(),e=b.attr("coords").split(","),f=[],g=a('img[usemap="#'+b.parent("map").attr("name")+'"]'),h=g.offset(),i={width:0,height:0,offset:{top:1e10,right:0,bottom:0,left:1e10}},j=0,k=0;h.left+=Math.ceil((g.outerWidth()-g.width())/2),h.top+=Math.ceil((g.outerHeight()-g.height())/2);if(d==="poly"){j=e.length;while(j--)k=[parseInt(e[--j],10),parseInt(e[j+1],10)],k[0]>i.offset.right&&(i.offset.right=k[0]),k[0]i.offset.bottom&&(i.offset.bottom=k[1]),k[1]