2 * jquery.qtip. The jQuery tooltip plugin
4 * Copyright (c) 2009 Craig Thompson
5 * http://craigsworks.com
8 * http://www.opensource.org/licenses/mit-license.php
10 * Launch : February 2009
12 * Released: Tuesday 12th May, 2009 - 00:00
13 * Debug: jquery.qtip.debug.js
18 $.fn
.qtip = function(options
, blanket
)
20 var i
, id
, interfaces
, opts
, obj
, command
, config
, api
;
22 // Return API / Interfaces if requested
23 if(typeof options
== 'string')
25 // Make sure API data exists if requested
26 if(typeof $(this).data('qtip') !== 'object')
27 $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.NO_TOOLTIP_PRESENT
, false);
29 // Return requested object
31 return $(this).data('qtip').interfaces
[ $(this).data('qtip').current
];
32 else if(options
== 'interfaces')
33 return $(this).data('qtip').interfaces
;
36 // Validate provided options
39 // Set null options object if no options are provided
40 if(!options
) options
= {};
42 // Sanitize option data
43 if(typeof options
.content
!== 'object' || (options
.content
.jquery
&& options
.content
.length
> 0)) options
.content
= { text
: options
.content
};
44 if(typeof options
.content
.title
!== 'object') options
.content
.title
= { text
: options
.content
.title
};
45 if(typeof options
.position
!== 'object') options
.position
= { corner
: options
.position
};
46 if(typeof options
.position
.corner
!== 'object') options
.position
.corner
= { target
: options
.position
.corner
, tooltip
: options
.position
.corner
};
47 if(typeof options
.show
!== 'object') options
.show
= { when
: options
.show
};
48 if(typeof options
.show
.when
!== 'object') options
.show
.when
= { event
: options
.show
.when
};
49 if(typeof options
.show
.effect
!== 'object') options
.show
.effect
= { type
: options
.show
.effect
};
50 if(typeof options
.hide
!== 'object') options
.hide
= { when
: options
.hide
};
51 if(typeof options
.hide
.when
!== 'object') options
.hide
.when
= { event
: options
.hide
.when
};
52 if(typeof options
.hide
.effect
!== 'object') options
.hide
.effect
= { type
: options
.hide
.effect
};
53 if(typeof options
.style
!== 'object') options
.style
= { name
: options
.style
};
54 options
.style
= sanitizeStyle(options
.style
);
56 // Build main options object
57 opts
= $.extend(true, {}, $.fn
.qtip
.defaults
, options
);
59 // Inherit all style properties into one syle object and include original options
60 opts
.style
= buildStyle
.call({ options
: opts
}, opts
.style
);
61 opts
.user
= $.extend(true, {}, options
);
64 // Iterate each matched element
65 return $(this).each(function() // Return original elements as per jQuery guidelines
67 // Check for API commands
68 if(typeof options
== 'string')
70 command
= options
.toLowerCase();
71 interfaces
= $(this).qtip('interfaces');
73 // Make sure API data exists$('.qtip').qtip('destroy')
74 if(typeof interfaces
== 'object')
76 // Check if API call is a BLANKET DESTROY command
77 if(blanket
=== true && command
== 'destroy')
78 while(interfaces
.length
> 0) interfaces
[interfaces
.length
-1].destroy();
80 // API call is not a BLANKET DESTROY command
83 // Check if supplied command effects this tooltip only (NOT BLANKET)
84 if(blanket
!== true) interfaces
= [ $(this).qtip('api') ];
86 // Execute command on chosen qTips
87 for(i
= 0; i
< interfaces
.length
; i
++)
89 // Destroy command doesn't require tooltip to be rendered
90 if(command
== 'destroy') interfaces
[i
].destroy();
92 // Only call API if tooltip is rendered and it wasn't a destroy call
93 else if(interfaces
[i
].status
.rendered
=== true)
95 if(command
== 'show') interfaces
[i
].show();
96 else if(command
== 'hide') interfaces
[i
].hide();
97 else if(command
== 'focus') interfaces
[i
].focus();
98 else if(command
== 'disable') interfaces
[i
].disable(true);
99 else if(command
== 'enable') interfaces
[i
].disable(false);
106 // No API commands, continue with qTip creation
109 // Create unique configuration object
110 config
= $.extend(true, {}, opts
);
111 config
.hide
.effect
.length
= opts
.hide
.effect
.length
;
112 config
.show
.effect
.length
= opts
.show
.effect
.length
;
114 // Sanitize target options
115 if(config
.position
.container
=== false) config
.position
.container
= $(document
.body
);
116 if(config
.position
.target
=== false) config
.position
.target
= $(this);
117 if(config
.show
.when
.target
=== false) config
.show
.when
.target
= $(this);
118 if(config
.hide
.when
.target
=== false) config
.hide
.when
.target
= $(this);
120 // Determine tooltip ID (Reuse array slots if possible)
121 id
= $.fn
.qtip
.interfaces
.length
;
122 for(i
= 0; i
< id
; i
++)
124 if(typeof $.fn
.qtip
.interfaces
[i
] == 'undefined'){ id
= i
; break; };
127 // Instantiate the tooltip
128 obj
= new qTip($(this), config
, id
);
130 // Add API references
131 $.fn
.qtip
.interfaces
[id
] = obj
;
133 // Check if element already has qTip data assigned
134 if(typeof $(this).data('qtip') == 'object')
136 // Set new current interface id
137 if(typeof $(this).attr('qtip') === 'undefined')
138 $(this).data('qtip').current
= $(this).data('qtip').interfaces
.length
;
140 // Push new API interface onto interfaces array
141 $(this).data('qtip').interfaces
.push(obj
);
144 // No qTip data is present, create now
145 else $(this).data('qtip', { current
: 0, interfaces
: [obj
] });
147 // If prerendering is disabled, create tooltip on showEvent
148 if(config
.content
.prerender
=== false && config
.show
.when
.event
!== false && config
.show
.ready
!== true)
150 config
.show
.when
.target
.bind(config
.show
.when
.event
+'.qtip-'+id
+'-create', { qtip
: id
}, function(event
)
152 // Retrieve API interface via passed qTip Id
153 api
= $.fn
.qtip
.interfaces
[ event
.data
.qtip
];
155 // Unbind show event and cache mouse coords
156 api
.options
.show
.when
.target
.unbind(api
.options
.show
.when
.event
+'.qtip-'+event
.data
.qtip
+'-create');
157 api
.cache
.mouse
= { x
: event
.pageX
, y
: event
.pageY
};
159 // Render tooltip and start the event sequence
160 construct
.call( api
);
161 api
.options
.show
.when
.target
.trigger(api
.options
.show
.when
.event
);
165 // Prerendering is enabled, create tooltip now
168 // Set mouse position cache to top left of the element
170 x
: config
.show
.when
.target
.offset().left
,
171 y
: config
.show
.when
.target
.offset().top
174 // Construct the tooltip
182 function qTip(target
, options
, id
)
184 // Declare this reference
187 // Setup class attributes
189 self
.options
= options
;
197 target
: target
.addClass(self
.options
.style
.classes
.target
),
201 contentWrapper
: null,
214 // Define exposed API methods
215 $.extend(self
, self
.options
.api
,
217 show: function(event
)
221 // Make sure tooltip is rendered and if not, return
222 if(!self
.status
.rendered
)
223 return $.fn
.qtip
.log
.error
.call(self
, 2, $.fn
.qtip
.constants
.TOOLTIP_NOT_RENDERED
, 'show');
225 // Only continue if element is visible
226 if(self
.elements
.tooltip
.css('display') !== 'none') return self
;
228 // Clear animation queue
229 self
.elements
.tooltip
.stop(true, false);
231 // Call API method and if return value is false, halt
232 returned
= self
.beforeShow
.call(self
, event
);
233 if(returned
=== false) return self
;
235 // Define afterShow callback method
238 // Call API method and focus if it isn't static
239 if(self
.options
.position
.type
!== 'static') self
.focus();
240 self
.onShow
.call(self
, event
);
242 // Prevent antialias from disappearing in IE7 by removing filter attribute
243 if($.browser
.msie
) self
.elements
.tooltip
.get(0).style
.removeAttribute('filter');
246 // Maintain toggle functionality if enabled
247 self
.cache
.toggle
= 1;
249 // Update tooltip position if it isn't static
250 if(self
.options
.position
.type
!== 'static')
251 self
.updatePosition(event
, (self
.options
.show
.effect
.length
> 0));
253 // Hide other tooltips if tooltip is solo
254 if(typeof self
.options
.show
.solo
== 'object') solo
= $(self
.options
.show
.solo
);
255 else if(self
.options
.show
.solo
=== true) solo
= $('div.qtip').not(self
.elements
.tooltip
);
256 if(solo
) solo
.each(function(){ if($(this).qtip('api').status
.rendered
=== true) $(this).qtip('api').hide(); });
259 if(typeof self
.options
.show
.effect
.type
== 'function')
261 self
.options
.show
.effect
.type
.call(self
.elements
.tooltip
, self
.options
.show
.effect
.length
);
262 self
.elements
.tooltip
.queue(function(){ afterShow(); $(this).dequeue(); });
266 switch(self
.options
.show
.effect
.type
.toLowerCase())
269 self
.elements
.tooltip
.fadeIn(self
.options
.show
.effect
.length
, afterShow
);
272 self
.elements
.tooltip
.slideDown(self
.options
.show
.effect
.length
, function()
275 if(self
.options
.position
.type
!== 'static') self
.updatePosition(event
, true);
279 self
.elements
.tooltip
.show(self
.options
.show
.effect
.length
, afterShow
);
282 self
.elements
.tooltip
.show(null, afterShow
);
286 // Add active class to tooltip
287 self
.elements
.tooltip
.addClass(self
.options
.style
.classes
.active
);
290 // Log event and return
291 return $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.EVENT_SHOWN
, 'show');
294 hide: function(event
)
298 // Make sure tooltip is rendered and if not, return
299 if(!self
.status
.rendered
)
300 return $.fn
.qtip
.log
.error
.call(self
, 2, $.fn
.qtip
.constants
.TOOLTIP_NOT_RENDERED
, 'hide');
302 // Only continue if element is visible
303 else if(self
.elements
.tooltip
.css('display') === 'none') return self
;
305 // Stop show timer and animation queue
306 clearTimeout(self
.timers
.show
);
307 self
.elements
.tooltip
.stop(true, false);
309 // Call API method and if return value is false, halt
310 returned
= self
.beforeHide
.call(self
, event
);
311 if(returned
=== false) return self
;
313 // Define afterHide callback method
314 function afterHide(){ self
.onHide
.call(self
, event
); };
316 // Maintain toggle functionality if enabled
317 self
.cache
.toggle
= 0;
320 if(typeof self
.options
.hide
.effect
.type
== 'function')
322 self
.options
.hide
.effect
.type
.call(self
.elements
.tooltip
, self
.options
.hide
.effect
.length
);
323 self
.elements
.tooltip
.queue(function(){ afterHide(); $(this).dequeue(); });
327 switch(self
.options
.hide
.effect
.type
.toLowerCase())
330 self
.elements
.tooltip
.fadeOut(self
.options
.hide
.effect
.length
, afterHide
);
333 self
.elements
.tooltip
.slideUp(self
.options
.hide
.effect
.length
, afterHide
);
336 self
.elements
.tooltip
.hide(self
.options
.hide
.effect
.length
, afterHide
);
339 self
.elements
.tooltip
.hide(null, afterHide
);
343 // Remove active class to tooltip
344 self
.elements
.tooltip
.removeClass(self
.options
.style
.classes
.active
);
347 // Log event and return
348 return $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.EVENT_HIDDEN
, 'hide');
351 updatePosition: function(event
, animate
)
353 var i
, target
, tooltip
, coords
, mapName
, imagePos
, newPosition
, ieAdjust
, ie6Adjust
, borderAdjust
, mouseAdjust
, offset
, curPosition
, returned
355 // Make sure tooltip is rendered and if not, return
356 if(!self
.status
.rendered
)
357 return $.fn
.qtip
.log
.error
.call(self
, 2, $.fn
.qtip
.constants
.TOOLTIP_NOT_RENDERED
, 'updatePosition');
359 // If tooltip is static, return
360 else if(self
.options
.position
.type
== 'static')
361 return $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.CANNOT_POSITION_STATIC
, 'updatePosition');
363 // Define property objects
365 position
: { left
: 0, top
: 0 },
366 dimensions
: { height
: 0, width
: 0 },
367 corner
: self
.options
.position
.corner
.target
370 position
: self
.getPosition(),
371 dimensions
: self
.getDimensions(),
372 corner
: self
.options
.position
.corner
.tooltip
375 // Target is an HTML element
376 if(self
.options
.position
.target
!== 'mouse')
378 // If the HTML element is AREA, calculate position manually
379 if(self
.options
.position
.target
.get(0).nodeName
.toLowerCase() == 'area')
381 // Retrieve coordinates from coords attribute and parse into integers
382 coords
= self
.options
.position
.target
.attr('coords').split(',');
383 for(i
= 0; i
< coords
.length
; i
++) coords
[i
] = parseInt(coords
[i
]);
385 // Setup target position object
386 mapName
= self
.options
.position
.target
.parent('map').attr('name');
387 imagePos
= $('img[usemap="#'+mapName
+'"]:first').offset();
389 left
: Math
.floor(imagePos
.left
+ coords
[0]),
390 top
: Math
.floor(imagePos
.top
+ coords
[1])
393 // Determine width and height of the area
394 switch(self
.options
.position
.target
.attr('shape').toLowerCase())
397 target
.dimensions
= {
398 width
: Math
.ceil(Math
.abs(coords
[2] - coords
[0])),
399 height
: Math
.ceil(Math
.abs(coords
[3] - coords
[1]))
404 target
.dimensions
= {
405 width
: coords
[2] + 1,
406 height
: coords
[2] + 1
411 target
.dimensions
= {
416 for(i
= 0; i
< coords
.length
; i
++)
420 if(coords
[i
] > target
.dimensions
.width
)
421 target
.dimensions
.width
= coords
[i
];
422 if(coords
[i
] < coords
[0])
423 target
.position
.left
= Math
.floor(imagePos
.left
+ coords
[i
]);
427 if(coords
[i
] > target
.dimensions
.height
)
428 target
.dimensions
.height
= coords
[i
];
429 if(coords
[i
] < coords
[1])
430 target
.position
.top
= Math
.floor(imagePos
.top
+ coords
[i
]);
434 target
.dimensions
.width
= target
.dimensions
.width
- (target
.position
.left
- imagePos
.left
);
435 target
.dimensions
.height
= target
.dimensions
.height
- (target
.position
.top
- imagePos
.top
);
439 return $.fn
.qtip
.log
.error
.call(self
, 4, $.fn
.qtip
.constants
.INVALID_AREA_SHAPE
, 'updatePosition');
443 // Adjust position by 2 pixels (Positioning bug?)
444 target
.dimensions
.width
-= 2; target
.dimensions
.height
-= 2;
447 // Target is the document
448 else if(self
.options
.position
.target
.add(document
.body
).length
=== 1)
450 target
.position
= { left
: $(document
).scrollLeft(), top
: $(document
).scrollTop() };
451 target
.dimensions
= { height
: $(window
).height(), width
: $(window
).width() };
454 // Target is a regular HTML element, find position normally
457 // Check if the target is another tooltip. If its animated, retrieve position from newPosition data
458 if(typeof self
.options
.position
.target
.attr('qtip') !== 'undefined')
459 target
.position
= self
.options
.position
.target
.qtip('api').cache
.position
;
461 target
.position
= self
.options
.position
.target
.offset();
463 // Setup dimensions objects
464 target
.dimensions
= {
465 height
: self
.options
.position
.target
.outerHeight(),
466 width
: self
.options
.position
.target
.outerWidth()
470 // Calculate correct target corner position
471 newPosition
= $.extend({}, target
.position
);
472 if(target
.corner
.search(/right/i) !== -1)
473 newPosition
.left
+= target
.dimensions
.width
;
475 if(target
.corner
.search(/bottom/i) !== -1)
476 newPosition
.top
+= target
.dimensions
.height
;
478 if(target
.corner
.search(/((top|bottom)Middle)|center/) !== -1)
479 newPosition
.left
+= (target
.dimensions
.width
/ 2);
481 if(target
.corner
.search(/((left|right)Middle)|center/) !== -1)
482 newPosition
.top
+= (target
.dimensions
.height
/ 2);
485 // Mouse is the target, set position to current mouse coordinates
488 // Setup target position and dimensions objects
489 target
.position
= newPosition
= { left
: self
.cache
.mouse
.x
, top
: self
.cache
.mouse
.y
};
490 target
.dimensions
= { height
: 1, width
: 1 };
493 // Calculate correct target corner position
494 if(tooltip
.corner
.search(/right/i) !== -1)
495 newPosition
.left
-= tooltip
.dimensions
.width
;
497 if(tooltip
.corner
.search(/bottom/i) !== -1)
498 newPosition
.top
-= tooltip
.dimensions
.height
;
500 if(tooltip
.corner
.search(/((top|bottom)Middle)|center/) !== -1)
501 newPosition
.left
-= (tooltip
.dimensions
.width
/ 2);
503 if(tooltip
.corner
.search(/((left|right)Middle)|center/) !== -1)
504 newPosition
.top
-= (tooltip
.dimensions
.height
/ 2);
506 // Setup IE adjustment variables (Pixel gap bugs)
507 ieAdjust
= ($.browser
.msie
) ? 1 : 0; // And this is why I hate IE...
508 ie6Adjust
= ($.browser
.msie
&& parseInt($.browser
.version
.charAt(0)) === 6) ? 1 : 0; // ...and even more so IE6!
510 // Adjust for border radius
511 if(self
.options
.style
.border
.radius
> 0)
513 if(tooltip
.corner
.search(/Left/) !== -1)
514 newPosition
.left
-= self
.options
.style
.border
.radius
;
515 else if(tooltip
.corner
.search(/Right/) !== -1)
516 newPosition
.left
+= self
.options
.style
.border
.radius
;
518 if(tooltip
.corner
.search(/Top/) !== -1)
519 newPosition
.top
-= self
.options
.style
.border
.radius
;
520 else if(tooltip
.corner
.search(/Bottom/) !== -1)
521 newPosition
.top
+= self
.options
.style
.border
.radius
;
524 // IE only adjustments (Pixel perfect!)
527 if(tooltip
.corner
.search(/top/) !== -1)
528 newPosition
.top
-= ieAdjust
529 else if(tooltip
.corner
.search(/bottom/) !== -1)
530 newPosition
.top
+= ieAdjust
532 if(tooltip
.corner
.search(/left/) !== -1)
533 newPosition
.left
-= ieAdjust
534 else if(tooltip
.corner
.search(/right/) !== -1)
535 newPosition
.left
+= ieAdjust
537 if(tooltip
.corner
.search(/leftMiddle|rightMiddle/) !== -1)
541 // If screen adjustment is enabled, apply adjustments
542 if(self
.options
.position
.adjust
.screen
=== true)
543 newPosition
= screenAdjust
.call(self
, newPosition
, target
, tooltip
);
545 // If mouse is the target, prevent tooltip appearing directly under the mouse
546 if(self
.options
.position
.target
=== 'mouse' && self
.options
.position
.adjust
.mouse
=== true)
548 if(self
.options
.position
.adjust
.screen
=== true && self
.elements
.tip
)
549 mouseAdjust
= self
.elements
.tip
.attr('rel');
551 mouseAdjust
= self
.options
.position
.corner
.tooltip
;
553 newPosition
.left
+= (mouseAdjust
.search(/right/i) !== -1) ? -6 : 6;
554 newPosition
.top
+= (mouseAdjust
.search(/bottom/i) !== -1) ? -6 : 6;
557 // Initiate bgiframe plugin in IE6 if tooltip overlaps a select box or object element
558 if(!self
.elements
.bgiframe
&& $.browser
.msie
&& parseInt($.browser
.version
.charAt(0)) == 6)
560 $('select, object').each(function()
562 offset
= $(this).offset();
563 offset
.bottom
= offset
.top
+ $(this).height();
564 offset
.right
= offset
.left
+ $(this).width();
566 if(newPosition
.top
+ tooltip
.dimensions
.height
>= offset
.top
567 && newPosition
.left
+ tooltip
.dimensions
.width
>= offset
.left
)
572 // Add user xy adjustments
573 newPosition
.left
+= self
.options
.position
.adjust
.x
;
574 newPosition
.top
+= self
.options
.position
.adjust
.y
;
576 // Set new tooltip position if its moved, animate if enabled
577 curPosition
= self
.getPosition();
578 if(newPosition
.left
!= curPosition
.left
|| newPosition
.top
!= curPosition
.top
)
580 // Call API method and if return value is false, halt
581 returned
= self
.beforePositionUpdate
.call(self
, event
);
582 if(returned
=== false) return self
;
584 // Cache new position
585 self
.cache
.position
= newPosition
;
587 // Check if animation is enabled
590 // Set animated status
591 self
.status
.animated
= true;
593 // Animate and reset animated status on animation end
594 self
.elements
.tooltip
.animate(newPosition
, 200, 'swing', function(){ self
.status
.animated
= false });
597 // Set new position via CSS
598 else self
.elements
.tooltip
.css(newPosition
);
600 // Call API method and log event if its not a mouse move
601 self
.onPositionUpdate
.call(self
, event
);
602 if(typeof event
!== 'undefined' && event
.type
&& event
.type
!== 'mousemove')
603 $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.EVENT_POSITION_UPDATED
, 'updatePosition');
609 updateWidth: function(newWidth
)
613 // Make sure tooltip is rendered and if not, return
614 if(!self
.status
.rendered
)
615 return $.fn
.qtip
.log
.error
.call(self
, 2, $.fn
.qtip
.constants
.TOOLTIP_NOT_RENDERED
, 'updateWidth');
617 // Make sure supplied width is a number and if not, return
618 else if(newWidth
&& typeof newWidth
!== 'number')
619 return $.fn
.qtip
.log
.error
.call(self
, 2, 'newWidth must be of type number', 'updateWidth');
621 // Setup elements which must be hidden during width update
622 hidden
= self
.elements
.contentWrapper
.siblings().add(self
.elements
.tip
).add(self
.elements
.button
);
624 // Calculate the new width if one is not supplied
627 // Explicit width is set
628 if(typeof self
.options
.style
.width
.value
== 'number')
629 newWidth
= self
.options
.style
.width
.value
;
631 // No width is set, proceed with auto detection
634 // Set width to auto initally to determine new width and hide other elements
635 self
.elements
.tooltip
.css({ width
: 'auto' });
636 self
.elements
.wrapper
.css({ width
: 'auto' });
639 // Set position and zoom to defaults to prevent IE hasLayout bug
641 self
.elements
.wrapper
.add(self
.elements
.contentWrapper
.children()).css({ zoom
: 'normal' });
644 newWidth
= self
.getDimensions().width
+ 1;
646 // Make sure its within the maximum and minimum width boundries
647 if(!self
.options
.style
.width
.value
)
649 if(newWidth
> self
.options
.style
.width
.max
) newWidth
= self
.options
.style
.width
.max
650 if(newWidth
< self
.options
.style
.width
.min
) newWidth
= self
.options
.style
.width
.min
655 // Adjust newWidth by 1px if width is odd (IE6 rounding bug fix)
656 if(newWidth
% 2 !== 0) newWidth
-= 1;
658 // Set the new calculated width and unhide other elements
659 self
.elements
.tooltip
.width(newWidth
);
662 // Set the border width, if enabled
663 if(self
.options
.style
.border
.radius
)
665 self
.elements
.tooltip
.find('.qtip-betweenCorners').each(function(i
)
667 $(this).width(newWidth
- (self
.options
.style
.border
.radius
* 2));
671 // IE only adjustments
674 // Reset position and zoom to give the wrapper layout (IE hasLayout bug)
675 self
.elements
.wrapper
.add(self
.elements
.contentWrapper
.children()).css({ zoom
: '1' });
678 self
.elements
.wrapper
.width(newWidth
);
680 // Adjust BGIframe height and width if enabled
681 if(self
.elements
.bgiframe
) self
.elements
.bgiframe
.width(newWidth
).height(self
.getDimensions
.height
);
684 // Log event and return
685 return $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.EVENT_WIDTH_UPDATED
, 'updateWidth');
688 updateStyle: function(name
)
690 var tip
, borders
, context
, corner
, coordinates
;
692 // Make sure tooltip is rendered and if not, return
693 if(!self
.status
.rendered
)
694 return $.fn
.qtip
.log
.error
.call(self
, 2, $.fn
.qtip
.constants
.TOOLTIP_NOT_RENDERED
, 'updateStyle');
696 // Return if style is not defined or name is not a string
697 else if(typeof name
!== 'string' || !$.fn
.qtip
.styles
[name
])
698 return $.fn
.qtip
.log
.error
.call(self
, 2, $.fn
.qtip
.constants
.STYLE_NOT_DEFINED
, 'updateStyle');
700 // Set the new style object
701 self
.options
.style
= buildStyle
.call(self
, $.fn
.qtip
.styles
[name
], self
.options
.user
.style
);
703 // Update initial styles of content and title elements
704 self
.elements
.content
.css( jQueryStyle(self
.options
.style
) );
705 if(self
.options
.content
.title
.text
!== false)
706 self
.elements
.title
.css( jQueryStyle(self
.options
.style
.title
, true) );
708 // Update CSS border colour
709 self
.elements
.contentWrapper
.css({ borderColor
: self
.options
.style
.border
.color
});
711 // Update tip color if enabled
712 if(self
.options
.style
.tip
.corner
!== false)
714 if($('<canvas>').get(0).getContext
)
716 // Retrieve canvas context and clear
717 tip
= self
.elements
.tooltip
.find('.qtip-tip canvas:first');
718 context
= tip
.get(0).getContext('2d');
719 context
.clearRect(0,0,300,300);
722 corner
= tip
.parent('div[rel]:first').attr('rel');
723 coordinates
= calculateTip(corner
, self
.options
.style
.tip
.size
.width
, self
.options
.style
.tip
.size
.height
);
724 drawTip
.call(self
, tip
, coordinates
, self
.options
.style
.tip
.color
|| self
.options
.style
.border
.color
);
726 else if($.browser
.msie
)
728 // Set new fillcolor attribute
729 tip
= self
.elements
.tooltip
.find('.qtip-tip [nodeName="shape"]');
730 tip
.attr('fillcolor', self
.options
.style
.tip
.color
|| self
.options
.style
.border
.color
);
734 // Update border colors if enabled
735 if(self
.options
.style
.border
.radius
> 0)
737 self
.elements
.tooltip
.find('.qtip-betweenCorners').css({ backgroundColor
: self
.options
.style
.border
.color
});
739 if($('<canvas>').get(0).getContext
)
741 borders
= calculateBorders(self
.options
.style
.border
.radius
)
742 self
.elements
.tooltip
.find('.qtip-wrapper canvas').each(function()
744 // Retrieve canvas context and clear
745 context
= $(this).get(0).getContext('2d');
746 context
.clearRect(0,0,300,300);
749 corner
= $(this).parent('div[rel]:first').attr('rel')
750 drawBorder
.call(self
, $(this), borders
[corner
],
751 self
.options
.style
.border
.radius
, self
.options
.style
.border
.color
);
754 else if($.browser
.msie
)
756 // Set new fillcolor attribute on each border corner
757 self
.elements
.tooltip
.find('.qtip-wrapper [nodeName="arc"]').each(function()
759 $(this).attr('fillcolor', self
.options
.style
.border
.color
)
764 // Log event and return
765 return $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.EVENT_STYLE_UPDATED
, 'updateStyle');
768 updateContent: function(content
, reposition
)
770 var parsedContent
, images
, loadedImages
;
772 // Make sure tooltip is rendered and if not, return
773 if(!self
.status
.rendered
)
774 return $.fn
.qtip
.log
.error
.call(self
, 2, $.fn
.qtip
.constants
.TOOLTIP_NOT_RENDERED
, 'updateContent');
776 // Make sure content is defined before update
778 return $.fn
.qtip
.log
.error
.call(self
, 2, $.fn
.qtip
.constants
.NO_CONTENT_PROVIDED
, 'updateContent');
780 // Call API method and set new content if a string is returned
781 parsedContent
= self
.beforeContentUpdate
.call(self
, content
);
782 if(typeof parsedContent
== 'string') content
= parsedContent
;
783 else if(parsedContent
=== false) return;
785 // Set position and zoom to defaults to prevent IE hasLayout bug
786 if($.browser
.msie
) self
.elements
.contentWrapper
.children().css({ zoom
: 'normal' });
788 // Append new content if its a DOM array and show it if hidden
789 if(content
.jquery
&& content
.length
> 0)
790 content
.clone(true).appendTo(self
.elements
.content
).show();
792 // Content is a regular string, insert the new content
793 else self
.elements
.content
.html(content
);
795 // Check if images need to be loaded before position is updated to prevent mis-positioning
796 images
= self
.elements
.content
.find('img[complete=false]');
797 if(images
.length
> 0)
800 images
.each(function(i
)
802 $('<img src="'+ $(this).attr('src') +'" />')
803 .load(function(){ if(++loadedImages
== images
.length
) afterLoad(); });
810 // Update the tooltip width
813 // If repositioning is enabled, update positions
814 if(reposition
!== false)
816 // Update position if tooltip isn't static
817 if(self
.options
.position
.type
!== 'static')
818 self
.updatePosition(self
.elements
.tooltip
.is(':visible'), true);
820 // Reposition the tip if enabled
821 if(self
.options
.style
.tip
.corner
!== false)
822 positionTip
.call(self
);
826 // Call API method and log event
827 self
.onContentUpdate
.call(self
);
828 return $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.EVENT_CONTENT_UPDATED
, 'loadContent');
831 loadContent: function(url
, data
, method
)
835 // Make sure tooltip is rendered and if not, return
836 if(!self
.status
.rendered
)
837 return $.fn
.qtip
.log
.error
.call(self
, 2, $.fn
.qtip
.constants
.TOOLTIP_NOT_RENDERED
, 'loadContent');
839 // Call API method and if return value is false, halt
840 returned
= self
.beforeContentLoad
.call(self
);
841 if(returned
=== false) return self
;
843 // Load content using specified request type
845 $.post(url
, data
, setupContent
);
847 $.get(url
, data
, setupContent
);
849 function setupContent(content
)
851 // Call API method and log event
852 self
.onContentLoad
.call(self
);
853 $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.EVENT_CONTENT_LOADED
, 'loadContent');
855 // Update the content
856 self
.updateContent(content
);
862 updateTitle: function(content
)
864 // Make sure tooltip is rendered and if not, return
865 if(!self
.status
.rendered
)
866 return $.fn
.qtip
.log
.error
.call(self
, 2, $.fn
.qtip
.constants
.TOOLTIP_NOT_RENDERED
, 'updateTitle');
868 // Make sure content is defined before update
870 return $.fn
.qtip
.log
.error
.call(self
, 2, $.fn
.qtip
.constants
.NO_CONTENT_PROVIDED
, 'updateTitle');
872 // Call API method and if return value is false, halt
873 returned
= self
.beforeTitleUpdate
.call(self
);
874 if(returned
=== false) return self
;
876 // Set the new content and reappend the button if enabled
877 if(self
.elements
.button
) self
.elements
.button
= self
.elements
.button
.clone(true);
878 self
.elements
.title
.html(content
)
879 if(self
.elements
.button
) self
.elements
.title
.prepend(self
.elements
.button
);
881 // Call API method and log event
882 self
.onTitleUpdate
.call(self
);
883 return $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.EVENT_TITLE_UPDATED
, 'updateTitle');
886 focus: function(event
)
888 var curIndex
, newIndex
, elemIndex
, returned
;
890 // Make sure tooltip is rendered and if not, return
891 if(!self
.status
.rendered
)
892 return $.fn
.qtip
.log
.error
.call(self
, 2, $.fn
.qtip
.constants
.TOOLTIP_NOT_RENDERED
, 'focus');
894 else if(self
.options
.position
.type
== 'static')
895 return $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.CANNOT_FOCUS_STATIC
, 'focus');
897 // Set z-index variables
898 curIndex
= parseInt( self
.elements
.tooltip
.css('z-index') );
899 newIndex
= 6000 + $('div.qtip[qtip]').length
- 1;
901 // Only update the z-index if it has changed and tooltip is not already focused
902 if(!self
.status
.focused
&& curIndex
!== newIndex
)
904 // Call API method and if return value is false, halt
905 returned
= self
.beforeFocus
.call(self
, event
);
906 if(returned
=== false) return self
;
908 // Loop through all other tooltips
909 $('div.qtip[qtip]').not(self
.elements
.tooltip
).each(function()
911 if($(this).qtip('api').status
.rendered
=== true)
913 elemIndex
= parseInt($(this).css('z-index'));
915 // Reduce all other tooltip z-index by 1
916 if(typeof elemIndex
== 'number' && elemIndex
> -1)
917 $(this).css({ zIndex
: parseInt( $(this).css('z-index') ) - 1 });
919 // Set focused status to false
920 $(this).qtip('api').status
.focused
= false;
924 // Set the new z-index and set focus status to true
925 self
.elements
.tooltip
.css({ zIndex
: newIndex
});
926 self
.status
.focused
= true;
928 // Call API method and log event
929 self
.onFocus
.call(self
, event
);
930 $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.EVENT_FOCUSED
, 'focus');
936 disable: function(state
)
938 // Make sure tooltip is rendered and if not, return
939 if(!self
.status
.rendered
)
940 return $.fn
.qtip
.log
.error
.call(self
, 2, $.fn
.qtip
.constants
.TOOLTIP_NOT_RENDERED
, 'disable');
944 // Tooltip is not already disabled, proceed
945 if(!self
.status
.disabled
)
947 // Set the disabled flag and log event
948 self
.status
.disabled
= true;
949 $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.EVENT_DISABLED
, 'disable');
952 // Tooltip is already disabled, inform user via log
953 else $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.TOOLTIP_ALREADY_DISABLED
, 'disable');
957 // Tooltip is not already enabled, proceed
958 if(self
.status
.disabled
)
960 // Reassign events, set disable status and log
961 self
.status
.disabled
= false;
962 $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.EVENT_ENABLED
, 'disable');
965 // Tooltip is already enabled, inform the user via log
966 else $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.TOOLTIP_ALREADY_ENABLED
, 'disable');
974 var i
, returned
, interfaces
;
976 // Call API method and if return value is false, halt
977 returned
= self
.beforeDestroy
.call(self
);
978 if(returned
=== false) return self
;
980 // Check if tooltip is rendered
981 if(self
.status
.rendered
)
983 // Remove event handlers and remove element
984 self
.options
.show
.when
.target
.unbind('mousemove.qtip', self
.updatePosition
);
985 self
.options
.show
.when
.target
.unbind('mouseout.qtip', self
.hide
);
986 self
.options
.show
.when
.target
.unbind(self
.options
.show
.when
.event
+ '.qtip');
987 self
.options
.hide
.when
.target
.unbind(self
.options
.hide
.when
.event
+ '.qtip');
988 self
.elements
.tooltip
.unbind(self
.options
.hide
.when
.event
+ '.qtip');
989 self
.elements
.tooltip
.unbind('mouseover.qtip', self
.focus
);
990 self
.elements
.tooltip
.remove();
993 // Tooltip isn't yet rendered, remove render event
994 else self
.options
.show
.when
.target
.unbind(self
.options
.show
.when
.event
+'.qtip-create');
996 // Check to make sure qTip data is present on target element
997 if(typeof self
.elements
.target
.data('qtip') == 'object')
999 // Remove API references from interfaces object
1000 interfaces
= self
.elements
.target
.data('qtip').interfaces
;
1001 if(typeof interfaces
== 'object' && interfaces
.length
> 0)
1003 // Remove API from interfaces array
1004 for(i
= 0; i
< interfaces
.length
- 1; i
++)
1005 if(interfaces
[i
].id
== self
.id
) interfaces
.splice(i
, 1)
1008 delete $.fn
.qtip
.interfaces
[self
.id
];
1010 // Set qTip current id to previous tooltips API if available
1011 if(typeof interfaces
== 'object' && interfaces
.length
> 0)
1012 self
.elements
.target
.data('qtip').current
= interfaces
.length
-1;
1014 self
.elements
.target
.removeData('qtip');
1016 // Call API method and log destroy
1017 self
.onDestroy
.call(self
);
1018 $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.EVENT_DESTROYED
, 'destroy');
1020 return self
.elements
.target
1023 getPosition: function()
1027 // Make sure tooltip is rendered and if not, return
1028 if(!self
.status
.rendered
)
1029 return $.fn
.qtip
.log
.error
.call(self
, 2, $.fn
.qtip
.constants
.TOOLTIP_NOT_RENDERED
, 'getPosition');
1031 show
= (self
.elements
.tooltip
.css('display') !== 'none') ? false : true;
1033 // Show and hide tooltip to make sure coordinates are returned
1034 if(show
) self
.elements
.tooltip
.css({ visiblity
: 'hidden' }).show();
1035 offset
= self
.elements
.tooltip
.offset();
1036 if(show
) self
.elements
.tooltip
.css({ visiblity
: 'visible' }).hide();
1041 getDimensions: function()
1043 var show
, dimensions
;
1045 // Make sure tooltip is rendered and if not, return
1046 if(!self
.status
.rendered
)
1047 return $.fn
.qtip
.log
.error
.call(self
, 2, $.fn
.qtip
.constants
.TOOLTIP_NOT_RENDERED
, 'getDimensions');
1049 show
= (!self
.elements
.tooltip
.is(':visible')) ? true : false;
1051 // Show and hide tooltip to make sure dimensions are returned
1052 if(show
) self
.elements
.tooltip
.css({ visiblity
: 'hidden' }).show();
1054 height
: self
.elements
.tooltip
.outerHeight(),
1055 width
: self
.elements
.tooltip
.outerWidth()
1057 if(show
) self
.elements
.tooltip
.css({ visiblity
: 'visible' }).hide();
1064 // Define priamry construct function
1065 function construct()
1067 var self
, adjust
, content
, url
, data
, method
, tempLength
;
1071 self
.beforeRender
.call(self
);
1073 // Set rendered status to true
1074 self
.status
.rendered
= true;
1076 // Create initial tooltip elements
1077 self
.elements
.tooltip
= '<div qtip="'+self
.id
+'" ' +
1078 'class="qtip '+(self
.options
.style
.classes
.tooltip
|| self
.options
.style
)+'"' +
1079 'style="display:none; -moz-border-radius:0; -webkit-border-radius:0; border-radius:0;' +
1080 'position:'+self
.options
.position
.type
+';">' +
1081 ' <div class="qtip-wrapper" style="position:relative; overflow:hidden; text-align:left;">' +
1082 ' <div class="qtip-contentWrapper" style="overflow:hidden;">' +
1083 ' <div class="qtip-content '+self
.options
.style
.classes
.content
+'"></div>' +
1084 '</div></div></div>';
1086 // Append to container element
1087 self
.elements
.tooltip
= $(self
.elements
.tooltip
);
1088 self
.elements
.tooltip
.appendTo(self
.options
.position
.container
)
1090 // Setup tooltip qTip data
1091 self
.elements
.tooltip
.data('qtip', { current
: 0, interfaces
: [self
] });
1093 // Setup element references
1094 self
.elements
.wrapper
= self
.elements
.tooltip
.children('div:first');
1095 self
.elements
.contentWrapper
= self
.elements
.wrapper
.children('div:first').css({ background
: self
.options
.style
.background
});
1096 self
.elements
.content
= self
.elements
.contentWrapper
.children('div:first').css( jQueryStyle(self
.options
.style
) );
1098 // Apply IE hasLayout fix to wrapper and content elements
1099 if($.browser
.msie
) self
.elements
.wrapper
.add(self
.elements
.content
).css({ zoom
: 1 });
1101 // Setup tooltip attributes
1102 if(self
.options
.hide
.when
.event
== 'unfocus') self
.elements
.tooltip
.attr('unfocus', true);
1104 // If an explicit width is set, updateWidth prior to setting content to prevent dirty rendering
1105 if(typeof self
.options
.style
.width
.value
== 'number') self
.updateWidth();
1107 // Create borders and tips if supported by the browser
1108 if($('<canvas>').get(0).getContext
|| $.browser
.msie
)
1111 if(self
.options
.style
.border
.radius
> 0)
1112 createBorder
.call(self
);
1114 self
.elements
.contentWrapper
.css({ border
: self
.options
.style
.border
.width
+'px solid '+self
.options
.style
.border
.color
});
1116 // Create tip if enabled
1117 if(self
.options
.style
.tip
.corner
!== false)
1118 createTip
.call(self
);
1121 // Neither canvas or VML is supported, tips and borders cannot be drawn!
1124 // Set defined border width
1125 self
.elements
.contentWrapper
.css({ border
: self
.options
.style
.border
.width
+'px solid '+self
.options
.style
.border
.color
});
1127 // Reset border radius and tip
1128 self
.options
.style
.border
.radius
= 0;
1129 self
.options
.style
.tip
.corner
= false;
1132 $.fn
.qtip
.log
.error
.call(self
, 2, $.fn
.qtip
.constants
.CANVAS_VML_NOT_SUPPORTED
, 'render');
1135 // Use the provided content string or DOM array
1136 if((typeof self
.options
.content
.text
== 'string' && self
.options
.content
.text
.length
> 0)
1137 || (self
.options
.content
.text
.jquery
&& self
.options
.content
.text
.length
> 0))
1138 content
= self
.options
.content
.text
;
1140 // Use title string for content if present
1141 else if(typeof self
.elements
.target
.attr('title') == 'string' && self
.elements
.target
.attr('title').length
> 0)
1143 content
= self
.elements
.target
.attr('title').replace("\\n", '<br />');
1144 self
.elements
.target
.attr('title', ''); // Remove title attribute to prevent default tooltip showing
1147 // No title is present, use alt attribute instead
1148 else if(typeof self
.elements
.target
.attr('alt') == 'string' && self
.elements
.target
.attr('alt').length
> 0)
1150 content
= self
.elements
.target
.attr('alt').replace("\\n", '<br />');
1151 self
.elements
.target
.attr('alt', ''); // Remove alt attribute to prevent default tooltip showing
1154 // No valid content was provided, inform via log
1158 $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.NO_VALID_CONTENT
, 'render');
1161 // Set the tooltips content and create title if enabled
1162 if(self
.options
.content
.title
.text
!== false) createTitle
.call(self
);
1163 self
.updateContent(content
);
1165 // Assign events and toggle tooltip with focus
1166 assignEvents
.call(self
);
1167 if(self
.options
.show
.ready
=== true) self
.show();
1169 // Retrieve ajax content if provided
1170 if(self
.options
.content
.url
!== false)
1172 url
= self
.options
.content
.url
;
1173 data
= self
.options
.content
.data
;
1174 method
= self
.options
.content
.method
|| 'get';
1175 self
.loadContent(url
, data
, method
);
1178 // Call API method and log event
1179 self
.onRender
.call(self
);
1180 $.fn
.qtip
.log
.error
.call(self
, 1, $.fn
.qtip
.constants
.EVENT_RENDERED
, 'render');
1183 // Create borders using canvas and VML
1184 function createBorder()
1186 var self
, i
, width
, radius
, color
, coordinates
, containers
, size
, betweenWidth
, betweenCorners
, borderTop
, borderBottom
, borderCoord
, sideWidth
, vertWidth
;
1189 // Destroy previous border elements, if present
1190 self
.elements
.wrapper
.find('.qtip-borderBottom, .qtip-borderTop').remove();
1192 // Setup local variables
1193 width
= self
.options
.style
.border
.width
;
1194 radius
= self
.options
.style
.border
.radius
;
1195 color
= self
.options
.style
.border
.color
|| self
.options
.style
.tip
.color
;
1197 // Calculate border coordinates
1198 coordinates
= calculateBorders(radius
);
1200 // Create containers for the border shapes
1202 for(i
in coordinates
)
1204 // Create shape container
1205 containers
[i
] = '<div rel="'+i
+'" style="'+((i
.search(/Left/) !== -1) ? 'left' : 'right') + ':0; ' +
1206 'position:absolute; height:'+radius
+'px; width:'+radius
+'px; overflow:hidden; line-height:0.1px; font-size:1px">';
1208 // Canvas is supported
1209 if($('<canvas>').get(0).getContext
)
1210 containers
[i
] += '<canvas height="'+radius
+'" width="'+radius
+'" style="vertical-align: top"></canvas>';
1212 // No canvas, but if it's IE use VML
1213 else if($.browser
.msie
)
1215 size
= radius
* 2 + 3;
1216 containers
[i
] += '<v:arc stroked="false" fillcolor="'+color
+'" startangle="'+coordinates
[i
][0]+'" endangle="'+coordinates
[i
][1]+'" ' +
1217 'style="width:'+size
+'px; height:'+size
+'px; margin-top:'+((i
.search(/bottom/) !== -1) ? -2 : -1)+'px; ' +
1218 'margin-left:'+((i
.search(/Right/) !== -1) ? coordinates
[i
][2] - 3.5 : -1)+'px; ' +
1219 'vertical-align:top; display:inline-block; behavior:url(#default#VML)"></v:arc>';
1223 containers
[i
] += '</div>';
1226 // Create between corners elements
1227 betweenWidth
= self
.getDimensions().width
- (Math
.max(width
, radius
) * 2);
1228 betweenCorners
= '<div class="qtip-betweenCorners" style="height:'+radius
+'px; width:'+betweenWidth
+'px; ' +
1229 'overflow:hidden; background-color:'+color
+'; line-height:0.1px; font-size:1px;">';
1231 // Create top border container
1232 borderTop
= '<div class="qtip-borderTop" dir="ltr" style="height:'+radius
+'px; ' +
1233 'margin-left:'+radius
+'px; line-height:0.1px; font-size:1px; padding:0;">' +
1234 containers
['topLeft'] + containers
['topRight'] + betweenCorners
;
1235 self
.elements
.wrapper
.prepend(borderTop
);
1237 // Create bottom border container
1238 borderBottom
= '<div class="qtip-borderBottom" dir="ltr" style="height:'+radius
+'px; ' +
1239 'margin-left:'+radius
+'px; line-height:0.1px; font-size:1px; padding:0;">' +
1240 containers
['bottomLeft'] + containers
['bottomRight'] + betweenCorners
;
1241 self
.elements
.wrapper
.append(borderBottom
);
1243 // Draw the borders if canvas were used (Delayed til after DOM creation)
1244 if($('<canvas>').get(0).getContext
)
1246 self
.elements
.wrapper
.find('canvas').each(function()
1248 borderCoord
= coordinates
[ $(this).parent('[rel]:first').attr('rel') ];
1249 drawBorder
.call(self
, $(this), borderCoord
, radius
, color
);
1253 // Create a phantom VML element (IE won't show the last created VML element otherwise)
1254 else if($.browser
.msie
) self
.elements
.tooltip
.append('<v:image style="behavior:url(#default#VML);"></v:image>');
1256 // Setup contentWrapper border
1257 sideWidth
= Math
.max(radius
, (radius
+ (width
- radius
)) )
1258 vertWidth
= Math
.max(width
- radius
, 0);
1259 self
.elements
.contentWrapper
.css({
1260 border
: '0px solid ' + color
,
1261 borderWidth
: vertWidth
+ 'px ' + sideWidth
+ 'px'
1265 // Border canvas draw method
1266 function drawBorder(canvas
, coordinates
, radius
, color
)
1269 var context
= canvas
.get(0).getContext('2d');
1270 context
.fillStyle
= color
;
1271 context
.beginPath();
1272 context
.arc(coordinates
[0], coordinates
[1], radius
, 0, Math
.PI
* 2, false);
1276 // Create tip using canvas and VML
1277 function createTip(corner
)
1279 var self
, color
, coordinates
, coordsize
, path
;
1282 // Destroy previous tip, if there is one
1283 if(self
.elements
.tip
!== null) self
.elements
.tip
.remove();
1285 // Setup color and corner values
1286 color
= self
.options
.style
.tip
.color
|| self
.options
.style
.border
.color
;
1287 if(self
.options
.style
.tip
.corner
=== false) return;
1288 else if(!corner
) corner
= self
.options
.style
.tip
.corner
;
1290 // Calculate tip coordinates
1291 coordinates
= calculateTip(corner
, self
.options
.style
.tip
.size
.width
, self
.options
.style
.tip
.size
.height
);
1293 // Create tip element
1294 self
.elements
.tip
= '<div class="'+self
.options
.style
.classes
.tip
+'" dir="ltr" rel="'+corner
+'" style="position:absolute; ' +
1295 'height:'+self
.options
.style
.tip
.size
.height
+'px; width:'+self
.options
.style
.tip
.size
.width
+'px; ' +
1296 'margin:0 auto; line-height:0.1px; font-size:1px;">';
1298 // Use canvas element if supported
1299 if($('<canvas>').get(0).getContext
)
1300 self
.elements
.tip
+= '<canvas height="'+self
.options
.style
.tip
.size
.height
+'" width="'+self
.options
.style
.tip
.size
.width
+'"></canvas>';
1302 // Canvas not supported - Use VML (IE)
1303 else if($.browser
.msie
)
1305 // Create coordize and tip path using tip coordinates
1306 coordsize
= self
.options
.style
.tip
.size
.width
+ ',' + self
.options
.style
.tip
.size
.height
;
1307 path
= 'm' + coordinates
[0][0] + ',' + coordinates
[0][1];
1308 path
+= ' l' + coordinates
[1][0] + ',' + coordinates
[1][1];
1309 path
+= ' ' + coordinates
[2][0] + ',' + coordinates
[2][1];
1312 // Create VML element
1313 self
.elements
.tip
+= '<v:shape fillcolor="'+color
+'" stroked="false" filled="true" path="'+path
+'" coordsize="'+coordsize
+'" ' +
1314 'style="width:'+self
.options
.style
.tip
.size
.width
+'px; height:'+self
.options
.style
.tip
.size
.height
+'px; ' +
1315 'line-height:0.1px; display:inline-block; behavior:url(#default#VML); ' +
1316 'vertical-align:'+((corner
.search(/top/) !== -1) ? 'bottom' : 'top')+'"></v:shape>';
1318 // Create a phantom VML element (IE won't show the last created VML element otherwise)
1319 self
.elements
.tip
+= '<v:image style="behavior:url(#default#VML);"></v:image>';
1321 // Prevent tooltip appearing above the content (IE z-index bug)
1322 self
.elements
.contentWrapper
.css('position', 'relative');
1325 // Attach new tip to tooltip element
1326 self
.elements
.tooltip
.prepend(self
.elements
.tip
+ '</div>');
1328 // Create element reference and draw the canvas tip (Delayed til after DOM creation)
1329 self
.elements
.tip
= self
.elements
.tooltip
.find('.'+self
.options
.style
.classes
.tip
).eq(0);
1330 if($('<canvas>').get(0).getContext
)
1331 drawTip
.call(self
, self
.elements
.tip
.find('canvas:first'), coordinates
, color
);
1333 // Fix IE small tip bug
1334 if(corner
.search(/top/) !== -1 && $.browser
.msie
&& parseInt($.browser
.version
.charAt(0)) === 6)
1335 self
.elements
.tip
.css({ marginTop
: -4 });
1337 // Set the tip position
1338 positionTip
.call(self
, corner
);
1341 // Canvas tip drawing method
1342 function drawTip(canvas
, coordinates
, color
)
1345 var context
= canvas
.get(0).getContext('2d');
1346 context
.fillStyle
= color
;
1349 context
.beginPath();
1350 context
.moveTo(coordinates
[0][0], coordinates
[0][1]);
1351 context
.lineTo(coordinates
[1][0], coordinates
[1][1]);
1352 context
.lineTo(coordinates
[2][0], coordinates
[2][1]);
1356 function positionTip(corner
)
1358 var self
, ieAdjust
, paddingCorner
, paddingSize
, newMargin
;
1361 // Return if tips are disabled or tip is not yet rendered
1362 if(self
.options
.style
.tip
.corner
=== false || !self
.elements
.tip
) return;
1363 if(!corner
) corner
= self
.elements
.tip
.attr('rel');
1365 // Setup adjustment variables
1366 ieAdjust
= positionAdjust
= ($.browser
.msie
) ? 1 : 0;
1368 // Set initial position
1369 self
.elements
.tip
.css(corner
.match(/left|right|top|bottom/)[0], 0);
1371 // Set position of tip to correct side
1372 if(corner
.search(/top|bottom/) !== -1)
1374 // Adjustments for IE6 - 0.5px border gap bug
1377 if(parseInt($.browser
.version
.charAt(0)) === 6)
1378 positionAdjust
= (corner
.search(/top/) !== -1) ? -3 : 1;
1380 positionAdjust
= (corner
.search(/top/) !== -1) ? 1 : 2;
1383 if(corner
.search(/Middle/) !== -1)
1384 self
.elements
.tip
.css({ left
: '50%', marginLeft
: -(self
.options
.style
.tip
.size
.width
/ 2) });
1386 else if(corner
.search(/Left/) !== -1)
1387 self
.elements
.tip
.css({ left
: self
.options
.style
.border
.radius
- ieAdjust
});
1389 else if(corner
.search(/Right/) !== -1)
1390 self
.elements
.tip
.css({ right
: self
.options
.style
.border
.radius
+ ieAdjust
});
1392 if(corner
.search(/top/) !== -1)
1393 self
.elements
.tip
.css({ top
: -positionAdjust
});
1395 self
.elements
.tip
.css({ bottom
: positionAdjust
});
1398 else if(corner
.search(/left|right/) !== -1)
1400 // Adjustments for IE6 - 0.5px border gap bug
1402 positionAdjust
= (parseInt($.browser
.version
.charAt(0)) === 6) ? 1 : ((corner
.search(/left/) !== -1) ? 1 : 2);
1404 if(corner
.search(/Middle/) !== -1)
1405 self
.elements
.tip
.css({ top
: '50%', marginTop
: -(self
.options
.style
.tip
.size
.height
/ 2) });
1407 else if(corner
.search(/Top/) !== -1)
1408 self
.elements
.tip
.css({ top
: self
.options
.style
.border
.radius
- ieAdjust
});
1410 else if(corner
.search(/Bottom/) !== -1)
1411 self
.elements
.tip
.css({ bottom
: self
.options
.style
.border
.radius
+ ieAdjust
});
1413 if(corner
.search(/left/) !== -1)
1414 self
.elements
.tip
.css({ left
: -positionAdjust
});
1416 self
.elements
.tip
.css({ right
: positionAdjust
});
1419 // Adjust tooltip padding to compensate for tip
1420 paddingCorner
= 'padding-' + corner
.match(/left|right|top|bottom/)[0];
1421 paddingSize
= self
.options
.style
.tip
.size
[ (paddingCorner
.search(/left|right/) !== -1) ? 'width' : 'height' ];
1422 self
.elements
.tooltip
.css('padding', 0);
1423 self
.elements
.tooltip
.css(paddingCorner
, paddingSize
);
1425 // Match content margin to prevent gap bug in IE6 ONLY
1426 if($.browser
.msie
&& parseInt($.browser
.version
.charAt(0)) == 6)
1428 newMargin
= parseInt(self
.elements
.tip
.css('margin-top')) || 0;
1429 newMargin
+= parseInt(self
.elements
.content
.css('margin-top')) || 0;
1431 self
.elements
.tip
.css({ marginTop
: newMargin
});
1435 // Create title bar for content
1436 function createTitle()
1440 // Destroy previous title element, if present
1441 if(self
.elements
.title
!== null) self
.elements
.title
.remove();
1443 // Create title element
1444 self
.elements
.title
= $('<div class="'+self
.options
.style
.classes
.title
+'">')
1445 .css( jQueryStyle(self
.options
.style
.title
, true) )
1446 .css({ zoom
: ($.browser
.msie
) ? 1 : 0 })
1447 .prependTo(self
.elements
.contentWrapper
);
1449 // Update title with contents if enabled
1450 if(self
.options
.content
.title
.text
) self
.updateTitle
.call(self
, self
.options
.content
.title
.text
);
1452 // Create title close buttons if enabled
1453 if(self
.options
.content
.title
.button
!== false
1454 && typeof self
.options
.content
.title
.button
== 'string')
1456 self
.elements
.button
= $('<a class="'+self
.options
.style
.classes
.button
+'" style="float:right; position: relative"></a>')
1457 .css( jQueryStyle(self
.options
.style
.button
, true) )
1458 .html(self
.options
.content
.title
.button
)
1459 .prependTo(self
.elements
.title
)
1460 .click(function(event
){ if(!self
.status
.disabled
) self
.hide(event
) });
1464 // Assign hide and show events
1465 function assignEvents()
1467 var self
, showTarget
, hideTarget
, inactiveEvents
;
1470 // Setup event target variables
1471 showTarget
= self
.options
.show
.when
.target
;
1472 hideTarget
= self
.options
.hide
.when
.target
;
1474 // Add tooltip as a hideTarget is its fixed
1475 if(self
.options
.hide
.fixed
) hideTarget
= hideTarget
.add(self
.elements
.tooltip
);
1477 // Check if the hide event is special 'inactive' type
1478 if(self
.options
.hide
.when
.event
== 'inactive')
1480 // Define events which reset the 'inactive' event handler
1481 inactiveEvents
= ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove',
1482 'mouseout', 'mouseenter', 'mouseleave', 'mouseover' ];
1484 // Define 'inactive' event timer method
1485 function inactiveMethod(event
)
1487 if(self
.status
.disabled
=== true) return;
1489 //Clear and reset the timer
1490 clearTimeout(self
.timers
.inactive
);
1491 self
.timers
.inactive
= setTimeout(function()
1493 // Unassign 'inactive' events
1494 $(inactiveEvents
).each(function()
1496 hideTarget
.unbind(this+'.qtip-inactive');
1497 self
.elements
.content
.unbind(this+'.qtip-inactive');
1503 , self
.options
.hide
.delay
);
1507 // Check if the tooltip is 'fixed'
1508 else if(self
.options
.hide
.fixed
=== true)
1510 self
.elements
.tooltip
.bind('mouseover.qtip', function()
1512 if(self
.status
.disabled
=== true) return;
1514 // Reset the hide timer
1515 clearTimeout(self
.timers
.hide
);
1519 // Define show event method
1520 function showMethod(event
)
1522 if(self
.status
.disabled
=== true) return;
1524 // If set, hide tooltip when inactive for delay period
1525 if(self
.options
.hide
.when
.event
== 'inactive')
1527 // Assign each reset event
1528 $(inactiveEvents
).each(function()
1530 hideTarget
.bind(this+'.qtip-inactive', inactiveMethod
);
1531 self
.elements
.content
.bind(this+'.qtip-inactive', inactiveMethod
);
1534 // Start the inactive timer
1538 // Clear hide timers
1539 clearTimeout(self
.timers
.show
);
1540 clearTimeout(self
.timers
.hide
);
1543 self
.timers
.show
= setTimeout(function(){ self
.show(event
); }, self
.options
.show
.delay
);
1546 // Define hide event method
1547 function hideMethod(event
)
1549 if(self
.status
.disabled
=== true) return;
1551 // Prevent hiding if tooltip is fixed and event target is the tooltip
1552 if(self
.options
.hide
.fixed
=== true
1553 && self
.options
.hide
.when
.event
.search(/mouse(out|leave)/i) !== -1
1554 && $(event
.relatedTarget
).parents('div.qtip[qtip]').length
> 0)
1556 // Prevent default and popagation
1557 event
.stopPropagation();
1558 event
.preventDefault();
1560 // Reset the hide timer
1561 clearTimeout(self
.timers
.hide
);
1565 // Clear timers and stop animation queue
1566 clearTimeout(self
.timers
.show
);
1567 clearTimeout(self
.timers
.hide
);
1568 self
.elements
.tooltip
.stop(true, true);
1570 // If tooltip has displayed, start hide timer
1571 self
.timers
.hide
= setTimeout(function(){ self
.hide(event
); }, self
.options
.hide
.delay
);
1574 // Both events and targets are identical, apply events using a toggle
1575 if((self
.options
.show
.when
.target
.add(self
.options
.hide
.when
.target
).length
=== 1
1576 && self
.options
.show
.when
.event
== self
.options
.hide
.when
.event
1577 && self
.options
.hide
.when
.event
!== 'inactive')
1578 || self
.options
.hide
.when
.event
== 'unfocus')
1580 self
.cache
.toggle
= 0;
1581 // Use a toggle to prevent hide/show conflicts
1582 showTarget
.bind(self
.options
.show
.when
.event
+ '.qtip', function(event
)
1584 if(self
.cache
.toggle
== 0) showMethod(event
);
1585 else hideMethod(event
);
1589 // Events are not identical, bind normally
1592 showTarget
.bind(self
.options
.show
.when
.event
+ '.qtip', showMethod
);
1594 // If the hide event is not 'inactive', bind the hide method
1595 if(self
.options
.hide
.when
.event
!== 'inactive')
1596 hideTarget
.bind(self
.options
.hide
.when
.event
+ '.qtip', hideMethod
);
1599 // Focus the tooltip on mouseover
1600 if(self
.options
.position
.type
.search(/(fixed|absolute)/) !== -1)
1601 self
.elements
.tooltip
.bind('mouseover.qtip', self
.focus
);
1603 // If mouse is the target, update tooltip position on mousemove
1604 if(self
.options
.position
.target
=== 'mouse' && self
.options
.position
.type
!== 'static')
1606 showTarget
.bind('mousemove.qtip', function(event
)
1608 // Set the new mouse positions if adjustment is enabled
1609 self
.cache
.mouse
= { x
: event
.pageX
, y
: event
.pageY
};
1611 // Update the tooltip position only if the tooltip is visible and adjustment is enabled
1612 if(self
.status
.disabled
=== false
1613 && self
.options
.position
.adjust
.mouse
=== true
1614 && self
.options
.position
.type
!== 'static'
1615 && self
.elements
.tooltip
.css('display') !== 'none')
1616 self
.updatePosition(event
);
1621 // Screen position adjustment
1622 function screenAdjust(position
, target
, tooltip
)
1624 var self
, adjustedPosition
, adjust
, newCorner
, overflow
, corner
;
1627 // Setup corner and adjustment variable
1628 if(tooltip
.corner
== 'center') return target
.position
// TODO: 'center' corner adjustment
1629 adjustedPosition
= $.extend({}, position
);
1630 newCorner
= { x
: false, y
: false };
1632 // Define overflow properties
1634 left
: (adjustedPosition
.left
< $.fn
.qtip
.cache
.screen
.scroll
.left
),
1635 right
: (adjustedPosition
.left
+ tooltip
.dimensions
.width
+ 2 >= $.fn
.qtip
.cache
.screen
.width
+ $.fn
.qtip
.cache
.screen
.scroll
.left
),
1636 top
: (adjustedPosition
.top
< $.fn
.qtip
.cache
.screen
.scroll
.top
),
1637 bottom
: (adjustedPosition
.top
+ tooltip
.dimensions
.height
+ 2 >= $.fn
.qtip
.cache
.screen
.height
+ $.fn
.qtip
.cache
.screen
.scroll
.top
)
1640 // Determine new positioning properties
1642 left
: (overflow
.left
&& (tooltip
.corner
.search(/right/i) != -1 || (tooltip
.corner
.search(/right/i) == -1 && !overflow
.right
))),
1643 right
: (overflow
.right
&& (tooltip
.corner
.search(/left/i) != -1 || (tooltip
.corner
.search(/left/i) == -1 && !overflow
.left
))),
1644 top
: (overflow
.top
&& tooltip
.corner
.search(/top/i) == -1),
1645 bottom
: (overflow
.bottom
&& tooltip
.corner
.search(/bottom/i) == -1)
1648 // Tooltip overflows off the left side of the screen
1651 if(self
.options
.position
.target
!== 'mouse')
1652 adjustedPosition
.left
= target
.position
.left
+ target
.dimensions
.width
;
1654 adjustedPosition
.left
= self
.cache
.mouse
.x
1656 newCorner
.x
= 'Left';
1659 // Tooltip overflows off the right side of the screen
1660 else if(adjust
.right
)
1662 if(self
.options
.position
.target
!== 'mouse')
1663 adjustedPosition
.left
= target
.position
.left
- tooltip
.dimensions
.width
;
1665 adjustedPosition
.left
= self
.cache
.mouse
.x
- tooltip
.dimensions
.width
;
1667 newCorner
.x
= 'Right';
1670 // Tooltip overflows off the top of the screen
1673 if(self
.options
.position
.target
!== 'mouse')
1674 adjustedPosition
.top
= target
.position
.top
+ target
.dimensions
.height
;
1676 adjustedPosition
.top
= self
.cache
.mouse
.y
1678 newCorner
.y
= 'top';
1681 // Tooltip overflows off the bottom of the screen
1682 else if(adjust
.bottom
)
1684 if(self
.options
.position
.target
!== 'mouse')
1685 adjustedPosition
.top
= target
.position
.top
- tooltip
.dimensions
.height
;
1687 adjustedPosition
.top
= self
.cache
.mouse
.y
- tooltip
.dimensions
.height
;
1689 newCorner
.y
= 'bottom';
1692 // Don't adjust if resulting position is negative
1693 if(adjustedPosition
.left
< 0)
1695 adjustedPosition
.left
= position
.left
;
1696 newCorner
.x
= false;
1698 if(adjustedPosition
.top
< 0)
1700 adjustedPosition
.top
= position
.top
;
1701 newCorner
.y
= false;
1704 // Change tip corner if positioning has changed and tips are enabled
1705 if(self
.options
.style
.tip
.corner
!== false)
1707 // Determine new corner properties
1708 adjustedPosition
.corner
= new String(tooltip
.corner
);
1709 if(newCorner
.x
!== false) adjustedPosition
.corner
= adjustedPosition
.corner
.replace(/Left|Right|Middle/, newCorner
.x
);
1710 if(newCorner
.y
!== false) adjustedPosition
.corner
= adjustedPosition
.corner
.replace(/top|bottom/, newCorner
.y
);
1712 // Adjust tip if position has changed and tips are enabled
1713 if(adjustedPosition
.corner
!== self
.elements
.tip
.attr('rel'))
1714 createTip
.call(self
, adjustedPosition
.corner
);
1717 return adjustedPosition
;
1720 // Build a jQuery style object from supplied style object
1721 function jQueryStyle(style
, sub
)
1725 styleObj
= $.extend(true, {}, style
);
1728 if(sub
=== true && i
.search(/(tip|classes)/i) !== -1)
1730 else if(!sub
&& i
.search(/(width|border|tip|title|classes|user)/i) !== -1)
1738 function sanitizeStyle(style
)
1740 if(typeof style
.tip
!== 'object') style
.tip
= { corner
: style
.tip
};
1741 if(typeof style
.tip
.size
!== 'object') style
.tip
.size
= { width
: style
.tip
.size
, height
: style
.tip
.size
};
1742 if(typeof style
.border
!== 'object') style
.border
= { width
: style
.border
};
1743 if(typeof style
.width
!== 'object') style
.width
= { value
: style
.width
};
1744 if(typeof style
.width
.max
== 'string') style
.width
.max
= parseInt(style
.width
.max
.replace(/([0-9]+)/i, "$1"));
1745 if(typeof style
.width
.min
== 'string') style
.width
.min
= parseInt(style
.width
.min
.replace(/([0-9]+)/i, "$1"));
1747 // Convert deprecated x and y tip values to width/height
1748 if(typeof style
.tip
.size
.x
== 'number')
1750 style
.tip
.size
.width
= style
.tip
.size
.x
;
1751 delete style
.tip
.size
.x
;
1753 if(typeof style
.tip
.size
.y
== 'number')
1755 style
.tip
.size
.height
= style
.tip
.size
.y
;
1756 delete style
.tip
.size
.y
;
1762 // Build styles recursively with inheritance
1763 function buildStyle()
1765 var self
, i
, styleArray
, styleExtend
, finalStyle
, ieAdjust
;
1768 // Build style options from supplied arguments
1769 styleArray
= [true, {}];
1770 for(i
= 0; i
< arguments
.length
; i
++)
1771 styleArray
.push(arguments
[i
]);
1772 styleExtend
= [ $.extend
.apply($, styleArray
) ];
1774 // Loop through each named style inheritance
1775 while(typeof styleExtend
[0].name
== 'string')
1777 // Sanitize style data and append to extend array
1778 styleExtend
.unshift( sanitizeStyle($.fn
.qtip
.styles
[ styleExtend
[0].name
]) );
1781 // Make sure resulting tooltip className represents final style
1782 styleExtend
.unshift(true, {classes
:{ tooltip
: 'qtip-' + (arguments
[0].name
|| 'defaults') }}, $.fn
.qtip
.styles
.defaults
);
1784 // Extend into a single style object
1785 finalStyle
= $.extend
.apply($, styleExtend
);
1787 // Adjust tip size if needed (IE 1px adjustment bug fix)
1788 ieAdjust
= ($.browser
.msie
) ? 1 : 0;
1789 finalStyle
.tip
.size
.width
+= ieAdjust
;
1790 finalStyle
.tip
.size
.height
+= ieAdjust
;
1792 // Force even numbers for pixel precision
1793 if(finalStyle
.tip
.size
.width
% 2 > 0) finalStyle
.tip
.size
.width
+= 1;
1794 if(finalStyle
.tip
.size
.height
% 2 > 0) finalStyle
.tip
.size
.height
+= 1;
1796 // Sanitize final styles tip corner value
1797 if(finalStyle
.tip
.corner
=== true)
1798 finalStyle
.tip
.corner
= (self
.options
.position
.corner
.tooltip
=== 'center') ? false : self
.options
.position
.corner
.tooltip
;
1803 // Tip coordinates calculator
1804 function calculateTip(corner
, width
, height
)
1806 // Define tip coordinates in terms of height and width values
1808 bottomRight
: [[0,0], [width
,height
], [width
,0]],
1809 bottomLeft
: [[0,0], [width
,0], [0,height
]],
1810 topRight
: [[0,height
], [width
,0], [width
,height
]],
1811 topLeft
: [[0,0], [0,height
], [width
,height
]],
1812 topMiddle
: [[0,height
], [width
/ 2,0], [width
,height
]],
1813 bottomMiddle
: [[0,0], [width
,0], [width
/ 2,height
]],
1814 rightMiddle
: [[0,0], [width
,height
/ 2], [0,height
]],
1815 leftMiddle
: [[width
,0], [width
,height
], [0,height
/ 2]]
1817 tips
.leftTop
= tips
.bottomRight
;
1818 tips
.rightTop
= tips
.bottomLeft
;
1819 tips
.leftBottom
= tips
.topRight
;
1820 tips
.rightBottom
= tips
.topLeft
;
1822 return tips
[corner
];
1825 // Border coordinates calculator
1826 function calculateBorders(radius
)
1830 // Use canvas element if supported
1831 if($('<canvas>').get(0).getContext
)
1834 topLeft
: [radius
,radius
], topRight
: [0,radius
],
1835 bottomLeft
: [radius
,0], bottomRight
: [0,0]
1839 // Canvas not supported - Use VML (IE)
1840 else if($.browser
.msie
)
1843 topLeft
: [-90,90,0], topRight
: [-90,90,-radius
],
1844 bottomLeft
: [90,270,0], bottomRight
: [90, 270,-radius
]
1851 // BGIFRAME JQUERY PLUGIN ADAPTION
1852 // Special thanks to Brandon Aaron for this plugin
1853 // http://plugins.jquery.com/project/bgiframe
1856 var self
, html
, dimensions
;
1858 dimensions
= self
.getDimensions();
1860 // Setup iframe HTML string
1861 html
= '<iframe class="qtip-bgiframe" frameborder="0" tabindex="-1" src="javascript:false" '+
1862 'style="display:block; position:absolute; z-index:-1; filter:alpha(opacity=\'0\'); border: 1px solid red; ' +
1863 'height:'+dimensions
.height
+'px; width:'+dimensions
.width
+'px" />';
1865 // Append the new HTML and setup element reference
1866 self
.elements
.bgiframe
= self
.elements
.wrapper
.prepend(html
).children('.qtip-bgiframe:first');
1869 // Assign cache and event initialisation on document load
1870 $(document
).ready(function()
1872 // Setup library cache with window scroll and dimensions of document
1875 scroll
: { left
: $(window
).scrollLeft(), top
: $(window
).scrollTop() },
1876 width
: $(window
).width(),
1877 height
: $(window
).height()
1881 // Adjust positions of the tooltips on window resize or scroll if enabled
1883 $(window
).bind('resize scroll', function(event
)
1885 clearTimeout(adjustTimer
);
1886 adjustTimer
= setTimeout(function()
1888 // Readjust cached screen values
1889 if(event
.type
=== 'scroll')
1890 $.fn
.qtip
.cache
.screen
.scroll
= { left
: $(window
).scrollLeft(), top
: $(window
).scrollTop() };
1893 $.fn
.qtip
.cache
.screen
.width
= $(window
).width();
1894 $.fn
.qtip
.cache
.screen
.height
= $(window
).height();
1897 for(i
= 0; i
< $.fn
.qtip
.interfaces
.length
; i
++)
1899 // Access current elements API
1900 var api
= $.fn
.qtip
.interfaces
[i
];
1902 // Update position if resize or scroll adjustments are enabled
1903 if(api
.status
.rendered
=== true
1904 && (api
.options
.position
.type
!== 'static'
1905 || api
.options
.position
.adjust
.scroll
&& event
.type
=== 'scroll'
1906 || api
.options
.position
.adjust
.resize
&& event
.type
=== 'resize'))
1908 // Queue the animation so positions are updated correctly
1909 api
.updatePosition(event
, true);
1916 // Hide unfocus toolipts on document mousedown
1917 $(document
).bind('mousedown.qtip', function(event
)
1919 if($(event
.target
).parents('div.qtip').length
=== 0)
1921 $('.qtip[unfocus]').each(function()
1923 var api
= $(this).qtip("api");
1925 // Only hide if its visible and not the tooltips target
1926 if($(this).is(':visible') && !api
.status
.disabled
1927 && $(event
.target
).add(api
.elements
.target
).length
> 1)
1934 // Define qTip API interfaces array
1935 $.fn
.qtip
.interfaces
= []
1937 // Define log and constant place holders
1938 $.fn
.qtip
.log
= { error: function(){ return this; } };
1939 $.fn
.qtip
.constants
= {};
1941 // Define configuration defaults
1942 $.fn
.qtip
.defaults
= {
1958 target
: 'bottomRight',
1999 beforeRender: function(){},
2000 onRender: function(){},
2001 beforePositionUpdate: function(){},
2002 onPositionUpdate: function(){},
2003 beforeShow: function(){},
2004 onShow: function(){},
2005 beforeHide: function(){},
2006 onHide: function(){},
2007 beforeContentUpdate: function(){},
2008 onContentUpdate: function(){},
2009 beforeContentLoad: function(){},
2010 onContentLoad: function(){},
2011 beforeTitleUpdate: function(){},
2012 onTitleUpdate: function(){},
2013 beforeDestroy: function(){},
2014 onDestroy: function(){},
2015 beforeFocus: function(){},
2016 onFocus: function(){}
2020 $.fn
.qtip
.styles
= {
2022 background
: 'white',
2039 size
: { width
: 13, height
: 13 },
2043 background
: '#e1e1e1',
2053 title
: 'qtip-title',
2054 button
: 'qtip-button',
2055 content
: 'qtip-content',
2056 active
: 'qtip-active'
2066 background
: '#F0DE7D',
2069 background
: '#FBF7AA',
2072 classes
: { tooltip
: 'qtip-cream' }
2081 background
: '#f1f1f1',
2084 background
: 'white',
2087 classes
: { tooltip
: 'qtip-light' }
2096 background
: '#404040',
2099 background
: '#505050',
2102 classes
: { tooltip
: 'qtip-dark' }
2111 background
: '#f28279',
2114 background
: '#F79992',
2117 classes
: { tooltip
: 'qtip-red' }
2126 background
: '#b9db8c',
2129 background
: '#CDE6AC',
2132 classes
: { tooltip
: 'qtip-green' }
2141 background
: '#D0E9F5',
2144 background
: '#E5F6FE',
2147 classes
: { tooltip
: 'qtip-blue' }