');
+ Scrollbar.call(this, pane);
+ };
+
+ /**
+ * Inherits from Scrollbar.
+ */
+
+ inherits(Scrollbar.Vertical, Scrollbar);
+
+ /**
+ * Updates size/position of scrollbar.
+ *
+ * @api private
+ */
+
+ Scrollbar.Vertical.prototype.update = function () {
+ var paneHeight = this.pane.el.height()
+ , trackHeight = paneHeight - this.pane.padding * 2
+ , innerEl = this.innerEl
+
+ this.el
+ .css('height', trackHeight * paneHeight / innerEl.scrollHeight)
+ .css('top', trackHeight * innerEl.scrollTop / innerEl.scrollHeight)
+ };
+
+ /**
+ * Called upon drag.
+ *
+ * @api private
+ */
+
+ Scrollbar.Vertical.prototype.mousemove = function (ev) {
+ var paneHeight = this.pane.el.height()
+ , trackHeight = paneHeight - this.pane.padding * 2
+ , pos = ev.pageY - this.startPageY
+ , barHeight = this.el.height()
+ , innerEl = this.innerEl
+
+ // minimum top is 0, maximum is the track height
+ var y = Math.min(Math.max(pos, 0), trackHeight - barHeight)
+
+ innerEl.scrollTop = (innerEl.scrollHeight - paneHeight)
+ * y / (trackHeight - barHeight)
+ };
+
+ /**
+ * Called upon container mousewheel.
+ *
+ * @api private
+ */
+
+ Scrollbar.Vertical.prototype.mousewheel = function (ev, delta, x, y) {
+ if ((y > 0 && 0 == this.innerEl.scrollTop) ||
+ (y < 0 && (this.innerEl.scrollTop + this.pane.el.height()
+ == this.innerEl.scrollHeight))) {
+ ev.preventDefault();
+ return false;
+ }
+ };
+
+ /**
+ * Cross-browser inheritance.
+ *
+ * @param {Function} constructor
+ * @param {Function} constructor we inherit from
+ * @api private
+ */
+
+ function inherits (ctorA, ctorB) {
+ function f() {};
+ f.prototype = ctorB.prototype;
+ ctorA.prototype = new f;
+ };
+
+ /**
+ * Scrollbar size detection.
+ */
+
+ var size;
+
+ function scrollbarSize () {
+ if (size === undefined) {
+ var div = $(
+ '
'
+ + '
'
+ );
+
+ $('body').append(div);
+
+ var w1 = $('div', div).innerWidth();
+ div.css('overflow-y', 'scroll');
+ var w2 = $('div', div).innerWidth();
+ $(div).remove();
+
+ size = w1 - w2;
+ }
+
+ return size;
+ };
+
+})(jQuery);
diff --git a/www/themes/profind/lib/antiscroll/deps/jquery-mousewheel.js b/www/themes/profind/lib/antiscroll/deps/jquery-mousewheel.js
new file mode 100644
index 0000000..dbf8f4b
--- /dev/null
+++ b/www/themes/profind/lib/antiscroll/deps/jquery-mousewheel.js
@@ -0,0 +1,78 @@
+/*! Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net)
+ * Licensed under the MIT License (LICENSE.txt).
+ *
+ * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
+ * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
+ * Thanks to: Seamus Leahy for adding deltaX and deltaY
+ *
+ * Version: 3.0.4
+ *
+ * Requires: 1.2.2+
+ */
+
+(function($) {
+
+var types = ['DOMMouseScroll', 'mousewheel'];
+
+$.event.special.mousewheel = {
+ setup: function() {
+ if ( this.addEventListener ) {
+ for ( var i=types.length; i; ) {
+ this.addEventListener( types[--i], handler, false );
+ }
+ } else {
+ this.onmousewheel = handler;
+ }
+ },
+
+ teardown: function() {
+ if ( this.removeEventListener ) {
+ for ( var i=types.length; i; ) {
+ this.removeEventListener( types[--i], handler, false );
+ }
+ } else {
+ this.onmousewheel = null;
+ }
+ }
+};
+
+$.fn.extend({
+ mousewheel: function(fn) {
+ return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
+ },
+
+ unmousewheel: function(fn) {
+ return this.unbind("mousewheel", fn);
+ }
+});
+
+
+function handler(event) {
+ var orgEvent = event || window.event, args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true, deltaX = 0, deltaY = 0;
+ event = $.event.fix(orgEvent);
+ event.type = "mousewheel";
+
+ // Old school scrollwheel delta
+ if ( event.wheelDelta ) { delta = event.wheelDelta/120; }
+ if ( event.detail ) { delta = -event.detail/3; }
+
+ // New school multidimensional scroll (touchpads) deltas
+ deltaY = delta;
+
+ // Gecko
+ if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
+ deltaY = 0;
+ deltaX = -1*delta;
+ }
+
+ // Webkit
+ if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY/120; }
+ if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = -1*orgEvent.wheelDeltaX/120; }
+
+ // Add event and delta to the front of the arguments
+ args.unshift(event, delta, deltaX, deltaY);
+
+ return $.event.handle.apply(this, args);
+}
+
+})(jQuery);
\ No newline at end of file
diff --git a/www/themes/profind/lib/antiscroll/index.html b/www/themes/profind/lib/antiscroll/index.html
new file mode 100644
index 0000000..0596ee1
--- /dev/null
+++ b/www/themes/profind/lib/antiscroll/index.html
@@ -0,0 +1,304 @@
+
+
+
+
Antiscroll - os x lion style cross-browser native scrolling on the web that gets out of the way
+
+
+
+
+
+
+
+
+
+
+
+
+
Antiscroll
+
os x lion style cross-browser native scrolling on the web that gets out of the way.
+
+ - supports mousewheels, trackpads, other input devices natively.
+ - total size is 1kb minified and gzipped.
+ - doesn't magically autowrap your elements with divs (manual wrapping is necessary, please see index.html demo).
+ - fade in/out controlled with CSS3 animations.
+ - shows scrollbars upon hovering.
+ - scrollbars are draggable.
+ - size of container can be dynamically adjusted and scrollbars will adapt.
+ - supports IE7+, Firefox 3+, Chrome, Safari, Opera
+
+
+
+
Download
+
+
+
+
X rows
+
+
+
X cols
+
+
Add col
+
Remove col
+
+
+
+
+
diff --git a/www/themes/profind/lib/cookie/CHANGELOG.md b/www/themes/profind/lib/cookie/CHANGELOG.md
new file mode 100644
index 0000000..e47d325
--- /dev/null
+++ b/www/themes/profind/lib/cookie/CHANGELOG.md
@@ -0,0 +1,17 @@
+1.3 (wip)
+---
+- Configuration options: `raw`, `json`. Replaces raw option, becomes config:
+
+```javascript
+$.cookie.raw = true; // bypass encoding/decoding the cookie value
+$.cookie.json = true; // automatically JSON stringify/parse value
+```
+Thus the default options now cleanly contain cookie attributes only.
+
+1.2
+---
+- Adding `$.removeCookie('foo')` for deleting a cookie, using `$.cookie('foo', null)` is now deprecated.
+
+1.1
+---
+- Default options.
diff --git a/www/themes/profind/lib/cookie/README.md b/www/themes/profind/lib/cookie/README.md
new file mode 100644
index 0000000..301e356
--- /dev/null
+++ b/www/themes/profind/lib/cookie/README.md
@@ -0,0 +1,92 @@
+# jquery.cookie
+
+A simple, lightweight jQuery plugin for reading, writing and deleting cookies.
+
+## Installation
+
+Include script *after* the jQuery library (unless you are packaging scripts somehow else):
+
+
+
+**Do not include the script directly from GitHub (http://raw.github.com/...).** The file is being served as text/plain and as such being blocked
+in Internet Explorer on Windows 7 for instance (because of the wrong MIME type). Bottom line: GitHub is not a CDN.
+
+## Usage
+
+Create session cookie:
+
+ $.cookie('the_cookie', 'the_value');
+
+Create expiring cookie, 7 days from then:
+
+ $.cookie('the_cookie', 'the_value', { expires: 7 });
+
+Create expiring cookie, valid across entire site:
+
+ $.cookie('the_cookie', 'the_value', { expires: 7, path: '/' });
+
+Read cookie:
+
+ $.cookie('the_cookie'); // => "the_value"
+ $.cookie('not_existing'); // => null
+
+Delete cookie:
+
+ // Returns true when cookie was found, false when no cookie was found...
+ $.removeCookie('the_cookie');
+
+ // Same path as when the cookie was written...
+ $.removeCookie('the_cookie', { path: '/' });
+
+*Note: when deleting a cookie, you must pass the exact same path, domain and secure options that were used to set the cookie, unless you're relying on the default options that is.*
+
+## Configuration
+
+By default the cookie value is encoded/decoded when writing/reading, using `encodeURIComponent`/`decodeURIComponent`. Bypass this by setting raw to true:
+
+ $.cookie.raw = true;
+
+Turn on automatic storage of JSON objects passed as the cookie value. Assumes `JSON.stringify` and `JSON.parse`:
+
+ $.cookie.json = true;
+
+## Cookie Options
+
+Cookie attributes can be set globally by setting properties of the `$.cookie.defaults` object or individually for each call to `$.cookie()` by passing a plain object to the options argument. Per-call options override the default options.
+
+ expires: 365
+
+Define lifetime of the cookie. Value can be a `Number` which will be interpreted as days from time of creation or a `Date` object. If omitted, the cookie becomes a session cookie.
+
+ path: '/'
+
+Define the path where the cookie is valid. *By default the path of the cookie is the path of the page where the cookie was created (standard browser behavior).* If you want to make it available for instance across the entire domain use `path: '/'`. Default: path of page where the cookie was created.
+
+ domain: 'example.com'
+
+Define the domain where the cookie is valid. Default: domain of page where the cookie was created.
+
+ secure: true
+
+If true, the cookie transmission requires a secure protocol (https). Default: `false`.
+
+## Tests
+
+Requires Node. Startup server:
+
+ $ node server.js
+
+Open in browser:
+
+ $ open http://0.0.0.0:8124/test.html
+
+## Development
+
+- Source hosted at [GitHub](https://github.com/carhartl/jquery-cookie)
+- Report issues, questions, feature requests on [GitHub Issues](https://github.com/carhartl/jquery-cookie/issues)
+
+Pull requests are very welcome! Make sure your patches are well tested. Please create a topic branch for every separate change you make.
+
+## Authors
+
+[Klaus Hartl](https://github.com/carhartl)
diff --git a/www/themes/profind/lib/cookie/jquery.cookie.js b/www/themes/profind/lib/cookie/jquery.cookie.js
new file mode 100644
index 0000000..2d4c05a
--- /dev/null
+++ b/www/themes/profind/lib/cookie/jquery.cookie.js
@@ -0,0 +1,72 @@
+/*!
+ * jQuery Cookie Plugin v1.3
+ * https://github.com/carhartl/jquery-cookie
+ *
+ * Copyright 2011, Klaus Hartl
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.opensource.org/licenses/GPL-2.0
+ */
+(function ($, document, undefined) {
+
+ var pluses = /\+/g;
+
+ function raw(s) {
+ return s;
+ }
+
+ function decoded(s) {
+ return decodeURIComponent(s.replace(pluses, ' '));
+ }
+
+ var config = $.cookie = function (key, value, options) {
+
+ // write
+ if (value !== undefined) {
+ options = $.extend({}, config.defaults, options);
+
+ if (value === null) {
+ options.expires = -1;
+ }
+
+ if (typeof options.expires === 'number') {
+ var days = options.expires, t = options.expires = new Date();
+ t.setDate(t.getDate() + days);
+ }
+
+ value = config.json ? JSON.stringify(value) : String(value);
+
+ return (document.cookie = [
+ encodeURIComponent(key), '=', config.raw ? value : encodeURIComponent(value),
+ options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
+ options.path ? '; path=' + options.path : '',
+ options.domain ? '; domain=' + options.domain : '',
+ options.secure ? '; secure' : ''
+ ].join(''));
+ }
+
+ // read
+ var decode = config.raw ? raw : decoded;
+ var cookies = document.cookie.split('; ');
+ for (var i = 0, l = cookies.length; i < l; i++) {
+ var parts = cookies[i].split('=');
+ if (decode(parts.shift()) === key) {
+ var cookie = decode(parts.join('='));
+ return config.json ? JSON.parse(cookie) : cookie;
+ }
+ }
+
+ return null;
+ };
+
+ config.defaults = {};
+
+ $.removeCookie = function (key, options) {
+ if ($.cookie(key) !== null) {
+ $.cookie(key, null, options);
+ return true;
+ }
+ return false;
+ };
+
+})(jQuery, document);
diff --git a/www/themes/profind/lib/qtip2/jquery.qtip.css b/www/themes/profind/lib/qtip2/jquery.qtip.css
new file mode 100644
index 0000000..f354308
--- /dev/null
+++ b/www/themes/profind/lib/qtip2/jquery.qtip.css
@@ -0,0 +1,557 @@
+/*
+* qTip2 - Pretty powerful tooltips
+* http://craigsworks.com/projects/qtip2/
+*
+* Version: nightly
+* 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: Mon Apr 2 13:46:17.0000000000 2012
+*/
+
+/* Core qTip styles */
+.ui-tooltip, .qtip{
+ position: absolute;
+ left: -28000px;
+ top: -28000px;
+ display: none;
+
+ max-width: 280px;
+ min-width: 50px;
+
+ font-size: 10.5px;
+ line-height: 12px;
+}
+
+ /* Fluid class for determining actual width in IE */
+ .ui-tooltip-fluid{
+ display: block;
+ visibility: hidden;
+ position: static !important;
+ float: left !important;
+ }
+
+ .ui-tooltip-content{
+ position: relative;
+ padding: 5px 9px;
+ overflow: hidden;
+
+ border: 1px solid #000001;
+
+ text-align: left;
+ word-wrap: break-word;
+ overflow: hidden;
+ }
+
+ .ui-tooltip-titlebar{
+ position: relative;
+ min-height: 14px;
+ padding: 5px 35px 5px 10px;
+ overflow: hidden;
+
+ border: 1px solid #000001;
+ border-width: 1px 1px 0;
+
+ font-weight: bold;
+ }
+
+ .ui-tooltip-titlebar + .ui-tooltip-content{ border-top-width: 0px !important; }
+
+ /*! Default close button class */
+ .ui-tooltip-titlebar .ui-state-default{
+ position: absolute;
+ right: 4px;
+ top: 50%;
+ margin-top: -9px;
+
+ cursor: pointer;
+ outline: medium none;
+
+ border-width: 1px;
+ border-style: solid;
+ }
+
+ * html .ui-tooltip-titlebar .ui-state-default{ top: 16px; } /* IE fix */
+
+ .ui-tooltip-titlebar .ui-icon,
+ .ui-tooltip-icon .ui-icon{
+ display: block;
+ text-indent: -1000em;
+ }
+
+ .ui-tooltip-icon, .ui-tooltip-icon .ui-icon{
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
+ }
+
+ .ui-tooltip-icon .ui-icon{
+ width: 18px;
+ height: 14px;
+
+ text-align: center;
+ text-indent: 0;
+ font: normal bold 10px/13px Tahoma,sans-serif;
+
+ color: inherit;
+ background: transparent none no-repeat -100em -100em;
+ }
+
+
+/* Applied to 'focused' tooltips e.g. most recently displayed/interacted with */
+.ui-tooltip-focus{
+
+}
+
+/* Applied on hover of tooltips i.e. added/removed on mouseenter/mouseleave respectively */
+.ui-tooltip-hover{
+
+}
+
+
+/*! Default tooltip style */
+.ui-tooltip-default .ui-tooltip-titlebar,
+.ui-tooltip-default .ui-tooltip-content{
+ border-color: #F1D031;
+ background-color: #FFFFA3;
+ color: #555;
+}
+
+ .ui-tooltip-default .ui-tooltip-titlebar{
+ background-color: #FFEF93;
+ }
+
+ .ui-tooltip-default .ui-tooltip-icon{
+ border-color: #CCC;
+ background: #F1F1F1;
+ color: #777;
+ }
+
+ .ui-tooltip-default .ui-tooltip-titlebar .ui-state-hover{
+ border-color: #AAA;
+ color: #111;
+ }
+
+/* Tips plugin */
+.ui-tooltip .ui-tooltip-tip{
+ margin: 0 auto;
+ overflow: hidden;
+ z-index: 10;
+}
+
+ .ui-tooltip .ui-tooltip-tip,
+ .ui-tooltip .ui-tooltip-tip *{
+ position: absolute;
+
+ line-height: 0.1px !important;
+ font-size: 0.1px !important;
+ color: #123456;
+
+ background: transparent;
+ border: 0px dashed transparent;
+ }
+
+ .ui-tooltip .ui-tooltip-tip canvas{ top: 0; left: 0; }
+
+
+/* Modal plugin */
+#qtip-overlay{
+ position: fixed;
+ left: -10000em;
+ top: -10000em;
+}
+
+ /* Applied to modals with show.modal.blur set to true */
+ #qtip-overlay.blurs{ cursor: pointer; }
+
+ /* Change opacity of overlay here */
+ #qtip-overlay div{
+ position: absolute;
+ left: 0; top: 0;
+ width: 100%; height: 100%;
+
+ background-color: black;
+
+ opacity: 0.7;
+ filter:alpha(opacity=70);
+ -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";
+ }
+
+/*! Light tooltip style */
+.ui-tooltip-light .ui-tooltip-titlebar,
+.ui-tooltip-light .ui-tooltip-content{
+ border-color: #E2E2E2;
+ color: #454545;
+}
+
+ .ui-tooltip-light .ui-tooltip-content{
+ background-color: white;
+ }
+
+ .ui-tooltip-light .ui-tooltip-titlebar{
+ background-color: #f1f1f1;
+ }
+
+
+/*! Dark tooltip style */
+.ui-tooltip-dark .ui-tooltip-titlebar,
+.ui-tooltip-dark .ui-tooltip-content{
+ border-color: #303030;
+ color: #f3f3f3;
+}
+
+ .ui-tooltip-dark .ui-tooltip-content{
+ background-color: #505050;
+ }
+
+ .ui-tooltip-dark .ui-tooltip-titlebar{
+ background-color: #404040;
+ }
+
+ .ui-tooltip-dark .ui-tooltip-icon{
+ border-color: #444;
+ }
+
+ .ui-tooltip-dark .ui-tooltip-titlebar .ui-state-hover{
+ border-color: #303030;
+ }
+
+
+/*! Cream tooltip style */
+.ui-tooltip-cream .ui-tooltip-titlebar,
+.ui-tooltip-cream .ui-tooltip-content{
+ border-color: #F9E98E;
+ color: #A27D35;
+}
+
+ .ui-tooltip-cream .ui-tooltip-content{
+ background-color: #FBF7AA;
+ }
+
+ .ui-tooltip-cream .ui-tooltip-titlebar{
+ background-color: #F0DE7D;
+ }
+
+ .ui-tooltip-cream .ui-state-default .ui-tooltip-icon{
+ background-position: -82px 0;
+ }
+
+
+/*! Red tooltip style */
+.ui-tooltip-red .ui-tooltip-titlebar,
+.ui-tooltip-red .ui-tooltip-content{
+ border-color: #D95252;
+ color: #912323;
+}
+
+ .ui-tooltip-red .ui-tooltip-content{
+ background-color: #F78B83;
+ }
+
+ .ui-tooltip-red .ui-tooltip-titlebar{
+ background-color: #F06D65;
+ }
+
+ .ui-tooltip-red .ui-state-default .ui-tooltip-icon{
+ background-position: -102px 0;
+ }
+
+ .ui-tooltip-red .ui-tooltip-icon{
+ border-color: #D95252;
+ }
+
+ .ui-tooltip-red .ui-tooltip-titlebar .ui-state-hover{
+ border-color: #D95252;
+ }
+
+
+/*! Green tooltip style */
+.ui-tooltip-green .ui-tooltip-titlebar,
+.ui-tooltip-green .ui-tooltip-content{
+ border-color: #90D93F;
+ color: #3F6219;
+}
+
+ .ui-tooltip-green .ui-tooltip-content{
+ background-color: #CAED9E;
+ }
+
+ .ui-tooltip-green .ui-tooltip-titlebar{
+ background-color: #B0DE78;
+ }
+
+ .ui-tooltip-green .ui-state-default .ui-tooltip-icon{
+ background-position: -42px 0;
+ }
+
+
+/*! Blue tooltip style */
+.ui-tooltip-blue .ui-tooltip-titlebar,
+.ui-tooltip-blue .ui-tooltip-content{
+ border-color: #ADD9ED;
+ color: #5E99BD;
+}
+
+ .ui-tooltip-blue .ui-tooltip-content{
+ background-color: #E5F6FE;
+ }
+
+ .ui-tooltip-blue .ui-tooltip-titlebar{
+ background-color: #D0E9F5;
+ }
+
+ .ui-tooltip-blue .ui-state-default .ui-tooltip-icon{
+ background-position: -2px 0;
+ }
+
+/*! Add shadows to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE6+, Safari 2+ */
+.ui-tooltip-shadow{
+ -webkit-box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15);
+ -moz-box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15);
+ box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15);
+}
+
+ .ui-tooltip-shadow .ui-tooltip-titlebar,
+ .ui-tooltip-shadow .ui-tooltip-content{
+ filter: progid:DXImageTransform.Microsoft.Shadow(Color='gray', Direction=135, Strength=3);
+ -ms-filter:"progid:DXImageTransform.Microsoft.Shadow(Color='gray', Direction=135, Strength=3)";
+
+ _margin-bottom: -3px; /* IE6 */
+ .margin-bottom: -3px; /* IE7 */
+ }
+
+
+/*! Add rounded corners to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+ */
+.ui-tooltip-rounded,
+.ui-tooltip-rounded .ui-tooltip-content,
+.ui-tooltip-tipsy,
+.ui-tooltip-tipsy .ui-tooltip-content,
+.ui-tooltip-youtube,
+.ui-tooltip-youtube .ui-tooltip-content{
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+}
+
+.ui-tooltip-rounded .ui-tooltip-titlebar,
+.ui-tooltip-tipsy .ui-tooltip-titlebar,
+.ui-tooltip-youtube .ui-tooltip-titlebar{
+ -moz-border-radius: 5px 5px 0 0;
+ -webkit-border-radius: 5px 5px 0 0;
+ border-radius: 5px 5px 0 0;
+}
+
+.ui-tooltip-rounded .ui-tooltip-titlebar + .ui-tooltip-content,
+.ui-tooltip-tipsy .ui-tooltip-titlebar + .ui-tooltip-content,
+.ui-tooltip-youtube .ui-tooltip-titlebar + .ui-tooltip-content{
+ -moz-border-radius: 0 0 5px 5px;
+ -webkit-border-radius: 0 0 5px 5px;
+ border-radius: 0 0 5px 5px;
+}
+
+
+/*! Youtube tooltip style */
+.ui-tooltip-youtube{
+ -webkit-box-shadow: 0 0 3px #333;
+ -moz-box-shadow: 0 0 3px #333;
+ box-shadow: 0 0 3px #333;
+}
+
+ .ui-tooltip-youtube .ui-tooltip-titlebar,
+ .ui-tooltip-youtube .ui-tooltip-content{
+ _margin-bottom: 0; /* IE6 */
+ .margin-bottom: 0; /* IE7 */
+
+ background: transparent;
+ background: rgba(0, 0, 0, 0.85);
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000)";
+
+ color: white;
+ border-color: #CCCCCC;
+ }
+
+ .ui-tooltip-youtube .ui-tooltip-icon{
+ border-color: #222;
+ }
+
+ .ui-tooltip-youtube .ui-tooltip-titlebar .ui-state-hover{
+ border-color: #303030;
+ }
+
+
+/* jQuery TOOLS Tooltip style */
+.ui-tooltip-jtools{
+ background: #232323;
+ background: rgba(0, 0, 0, 0.7);
+ background-image: -moz-linear-gradient(top, #717171, #232323);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#717171), to(#232323));
+
+ border: 2px solid #ddd;
+ border: 2px solid rgba(241,241,241,1);
+
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+
+ -webkit-box-shadow: 0 0 12px #333;
+ -moz-box-shadow: 0 0 12px #333;
+ box-shadow: 0 0 12px #333;
+}
+
+ /* IE Specific */
+ .ui-tooltip-jtools .ui-tooltip-titlebar{
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A)";
+ }
+ .ui-tooltip-jtools .ui-tooltip-content{
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323)";
+ }
+
+ .ui-tooltip-jtools .ui-tooltip-titlebar,
+ .ui-tooltip-jtools .ui-tooltip-content{
+ background: transparent;
+ color: white;
+ border: 0 dashed transparent;
+ }
+
+ .ui-tooltip-jtools .ui-tooltip-icon{
+ border-color: #555;
+ }
+
+ .ui-tooltip-jtools .ui-tooltip-titlebar .ui-state-hover{
+ border-color: #333;
+ }
+
+
+/* Cluetip style */
+.ui-tooltip-cluetip{
+ -webkit-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4);
+ -moz-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4);
+ box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4);
+}
+
+ .ui-tooltip-cluetip .ui-tooltip-titlebar{
+ background-color: #87876A;
+ color: white;
+ border: 0 dashed transparent;
+ }
+
+ .ui-tooltip-cluetip .ui-tooltip-content{
+ background-color: #D9D9C2;
+ color: #111;
+ border: 0 dashed transparent;
+ }
+
+ .ui-tooltip-cluetip .ui-tooltip-icon{
+ border-color: #808064;
+ }
+
+ .ui-tooltip-cluetip .ui-tooltip-titlebar .ui-state-hover{
+ border-color: #696952;
+ color: #696952;
+ }
+
+
+/* Tipsy style */
+.ui-tooltip-tipsy{
+ border: 0;
+}
+
+ .ui-tooltip-tipsy .ui-tooltip-titlebar,
+ .ui-tooltip-tipsy .ui-tooltip-content{
+ _margin-bottom: 0; /* IE6 */
+ .margin-bottom: 0; /* IE7 */
+
+ background: transparent;
+ background: rgba(0, 0, 0, .87);
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#D9000000,endColorstr=#D9000000)";
+
+ color: white;
+ border: 0px transparent;
+
+ font-size: 11px;
+ font-family: 'Lucida Grande', sans-serif;
+ font-weight: bold;
+ line-height: 16px;
+ text-shadow: 0 1px black;
+ }
+
+ .ui-tooltip-tipsy .ui-tooltip-titlebar{
+ padding: 6px 35px 0 10;
+ }
+
+ .ui-tooltip-tipsy .ui-tooltip-content{
+ padding: 6px 10;
+ }
+
+ .ui-tooltip-tipsy .ui-tooltip-icon{
+ border-color: #222;
+ text-shadow: none;
+ }
+
+ .ui-tooltip-tipsy .ui-tooltip-titlebar .ui-state-hover{
+ border-color: #303030;
+ }
+
+
+/* Tipped style */
+.ui-tooltip-tipped{
+
+}
+
+ .ui-tooltip-tipped .ui-tooltip-titlebar,
+ .ui-tooltip-tipped .ui-tooltip-content{
+ border: 3px solid #959FA9;
+
+ filter: none; -ms-filter: none;
+ }
+
+ .ui-tooltip-tipped .ui-tooltip-titlebar{
+ background: #3A79B8;
+ background-image: -moz-linear-gradient(top, #3A79B8, #2E629D);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#3A79B8), to(#2E629D));
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D)";
+
+ color: white;
+ font-weight: normal;
+ font-family: serif;
+
+ border-bottom-width: 0;
+ -moz-border-radius: 3px 3px 0 0;
+ -webkit-border-radius: 3px 3px 0 0;
+ border-radius: 3px 3px 0 0;
+ }
+
+ .ui-tooltip-tipped .ui-tooltip-content{
+ background-color: #F9F9F9;
+ color: #454545;
+
+ -moz-border-radius: 0 0 3px 3px;
+ -webkit-border-radius: 0 0 3px 3px;
+ border-radius: 0 0 3px 3px;
+ }
+
+ .ui-tooltip-tipped .ui-tooltip-icon{
+ border: 2px solid #285589;
+ background: #285589;
+ }
+
+ .ui-tooltip-tipped .ui-tooltip-icon .ui-icon{
+ background-color: #FBFBFB;
+ color: #555;
+ }
+
+/* IE9 fix - removes all filters */
+.ui-tooltip:not(.ie9haxors) div.ui-tooltip-content,
+.ui-tooltip:not(.ie9haxors) div.ui-tooltip-titlebar{
+ filter: none;
+ -ms-filter: none;
+}
+
diff --git a/www/themes/profind/lib/qtip2/jquery.qtip.js b/www/themes/profind/lib/qtip2/jquery.qtip.js
new file mode 100644
index 0000000..ed0d724
--- /dev/null
+++ b/www/themes/profind/lib/qtip2/jquery.qtip.js
@@ -0,0 +1,3270 @@
+/*
+* qTip2 - Pretty powerful tooltips
+* http://craigsworks.com/projects/qtip2/
+*
+* Version: nightly
+* 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: Mon Apr 2 13:46:17.0000000000 2012
+*/
+
+/*jslint browser: true, onevar: true, undef: true, nomen: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: true */
+/*global window: false, jQuery: false, console: false, define: false */
+
+// Uses AMD or browser globals to create a jQuery plugin.
+(function(factory) {
+ if(typeof define === 'function' && define.amd) {
+ define(['jquery'], factory);
+ }
+ else {
+ factory(jQuery);
+ }
+}
+(function($) {
+
+ "use strict"; // Enable ECMAScript "strict" operation for this function. See more: http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
+
+ // Munge the primitives - Paul Irish tip
+ var TRUE = true,
+ FALSE = false,
+ NULL = null,
+ undefined,
+
+ // Shortcut vars
+ QTIP, PLUGINS, MOUSE,
+ usedIDs = {},
+ uitooltip = 'ui-tooltip',
+ widget = 'ui-widget',
+ disabled = 'ui-state-disabled',
+ selector = 'div.qtip.'+uitooltip,
+ defaultClass = uitooltip + '-default',
+ focusClass = uitooltip + '-focus',
+ hoverClass = uitooltip + '-hover',
+ fluidClass = uitooltip + '-fluid',
+ hideOffset = '-31000px',
+ replaceSuffix = '_replacedByqTip',
+ oldtitle = 'oldtitle',
+ trackingBound;
+
+ /* Thanks to Paul Irish for this one: http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/ */
+ function log() {
+ log.history = log.history || [];
+ log.history.push(arguments);
+
+ // Make sure console is present
+ if('object' === typeof console) {
+
+ // Setup console and arguments
+ var c = console[ console.warn ? 'warn' : 'log' ],
+ args = Array.prototype.slice.call(arguments), a;
+
+ // Add qTip2 marker to first argument if it's a string
+ if(typeof arguments[0] === 'string') { args[0] = 'qTip2: ' + args[0]; }
+
+ // Apply console.warn or .log if not supported
+ a = c.apply ? c.apply(console, args) : c(args);
+ }
+ }
+
+// Option object sanitizer
+function sanitizeOptions(opts)
+{
+ var content;
+
+ if(!opts || 'object' !== typeof opts) { return FALSE; }
+
+ if(opts.metadata === NULL || 'object' !== typeof opts.metadata) {
+ opts.metadata = {
+ type: opts.metadata
+ };
+ }
+
+ if('content' in opts) {
+ if(opts.content === NULL || '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(opts.content.title === NULL || '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(opts.position === NULL || 'object' !== typeof opts.position) {
+ opts.position = {
+ my: opts.position,
+ at: opts.position
+ };
+ }
+ }
+
+ if('show' in opts) {
+ if(opts.show === NULL || 'object' !== typeof opts.show) {
+ if(opts.show.jquery) {
+ opts.show = { target: opts.show };
+ }
+ else {
+ opts.show = { event: opts.show };
+ }
+ }
+ }
+
+ if('hide' in opts) {
+ if(opts.hide === NULL || 'object' !== typeof opts.hide) {
+ if(opts.hide.jquery) {
+ opts.hide = { target: opts.hide };
+ }
+ else {
+ opts.hide = { event: opts.hide };
+ }
+ }
+ }
+
+ if('style' in opts) {
+ if(opts.style === NULL || '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 = $(),
+ namespace = '.qtip-' + id,
+ 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: $(),
+ disabled: FALSE,
+ attr: attr,
+ onTarget: FALSE
+ };
+
+ /*
+ * 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).toggleClass(defaultClass, options.style.def && !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(reposition)
+ {
+ if(elements.title) {
+ elements.titlebar.remove();
+ elements.titlebar = elements.title = elements.button = NULL;
+
+ // Reposition if enabled
+ if(reposition !== FALSE) { 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 ui-tooltip-close ' + (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')
+ .click(function(event) {
+ if(!tooltip.hasClass(disabled)) { self.hide(event); }
+ return FALSE;
+ });
+
+ // 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)
+
+ // Button-specific events
+ .delegate('.ui-tooltip-close', 'mousedown keydown mouseup keyup mouseout', function(event) {
+ $(this).toggleClass('ui-state-active ui-state-focus', event.type.substr(-4) === 'down');
+ })
+ .delegate('.ui-tooltip-close', 'mouseover mouseout', function(event){
+ $(this).toggleClass('ui-state-hover', event.type === 'mouseover');
+ });
+
+ // 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, reposition)
+ {
+ 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, cache.event, self);
+ }
+
+ // Remove title if callback returns false or null/undefined (but not '')
+ if(content === FALSE || (!content && content !== '')) { return removeTitle(FALSE); }
+
+ // Append new content if its a DOM array and show it if hidden
+ else 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(reposition !== FALSE && 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, cache.event, 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, srcs = {};
+
+ function imageLoad(image) {
+ // Clear src from object and any timers and events associated with the image
+ if(image) {
+ delete srcs[image.src];
+ clearTimeout(self.timers.img[image.src]);
+ $(image).unbind(namespace);
+ }
+
+ // If queue is empty after image removal, update tooltip and continue the queue
+ if($.isEmptyObject(srcs)) {
+ self.redraw();
+ if(reposition !== FALSE) {
+ self.reposition(cache.event);
+ }
+
+ next();
+ }
+ }
+
+ // Find all content images without dimensions, and if no images were found, continue
+ if((images = elem.find('img[src]:not([height]):not([width])')).length === 0) { return imageLoad(); }
+
+ // Apply timer to each image to poll for dimensions
+ images.each(function(i, elem) {
+ // Skip if the src is already present
+ if(srcs[elem.src] !== undefined) { return; }
+
+ // Keep track of how many times we poll for image dimensions.
+ // If it doesn't return in a reasonable amount of time, it's better
+ // to display the tooltip, rather than hold up the queue.
+ var iterations = 0, maxIterations = 3;
+
+ (function timer(){
+ // When the dimensions are found, remove the image from the queue
+ if(elem.height || elem.width || (iterations > maxIterations)) { return imageLoad(elem); }
+
+ // Increase iterations and restart timer
+ iterations += 1;
+ self.timers.img[elem.src] = setTimeout(timer, 700);
+ }());
+
+ // Also apply regular load/error event handlers
+ $(elem).bind('error'+namespace+' load'+namespace, function(){ imageLoad(this); });
+
+ // Store the src and element in our object
+ srcs[elem.src] = elem;
+ });
+ }
+
+ /*
+ * 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()
+ {
+ var posOptions = options.position,
+ targets = {
+ show: options.show.target,
+ hide: options.hide.target,
+ viewport: $(posOptions.viewport),
+ document: $(document),
+ body: $(document.body),
+ window: $(window)
+ },
+ 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; }
+
+ // Clear hide timers
+ clearTimeout(self.timers.show);
+ clearTimeout(self.timers.hide);
+
+ // Start show timer
+ var callback = function(){ self.toggle(TRUE, 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) || isPositioning || isDrawing) { 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)))) {
+ try { event.preventDefault(); event.stopImmediatePropagation(); } catch(e) {} return;
+ }
+
+ // 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); }
+ }
+
+ // On mouseenter/mouseleave...
+ tooltip.bind('mouseenter'+namespace+' mouseleave'+namespace, function(event) {
+ var state = event.type === 'mouseenter';
+
+ // Focus the tooltip on mouseenter (z-index stacking)
+ if(state) { self.focus(event); }
+
+ // Add hover class
+ tooltip.toggleClass(hoverClass, state);
+ });
+
+ // 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 using mouseout/mouseleave as a hide event...
+ if(/mouse(out|leave)/i.test(options.hide.event)) {
+ // Hide tooltips when leaving current window/frame (but not select/option elements)
+ if(options.hide.leave === 'window') {
+ targets.window.bind('mouseout'+namespace+' blur'+namespace, function(event) {
+ if(/select|option/.test(event.target) && !event.relatedTarget) { self.hide(event); }
+ });
+ }
+ }
+
+ /*
+ * Make sure hoverIntent functions properly by using mouseleave to clear show timer if
+ * mouseenter/mouseout is used for show.event, even if it isn't in the users options.
+ */
+ else if(/mouse(over|enter)/i.test(options.show.event)) {
+ targets.hide.bind('mouseleave'+namespace, function(event) {
+ clearTimeout(self.timers.show);
+ });
+ }
+
+ // Hide tooltip on document mousedown if unfocus events are enabled
+ if(('' + options.hide.event).indexOf('unfocus') > -1) {
+ posOptions.container.closest('html').bind('mousedown'+namespace, function(event) {
+ var elem = $(event.target),
+ enabled = !tooltip.hasClass(disabled) && tooltip.is(':visible'),
+ isAncestor = elem.parents(selector).filter(tooltip[0]).length > 0;
+
+ if(elem[0] !== target[0] && elem[0] !== tooltip[0] && !isAncestor &&
+ !target.has(elem[0]).length && !elem.attr('disabled')
+ ) {
+ self.hide(event);
+ }
+ });
+ }
+
+ // 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
+ $.each(events.show, function(index, type) {
+ targets.show.bind(type+namespace, showMethod);
+ });
+
+ // Check if the tooltip hides when mouse is moved a certain distance
+ if('number' === typeof options.hide.distance) {
+ // Bind mousemove to target to detect distance difference
+ targets.show.add(tooltip).bind('mousemove'+namespace, function(event) {
+ var origin = cache.origin || {},
+ limit = options.hide.distance,
+ abs = Math.abs;
+
+ // Check if the movement has gone beyond the limit, and hide it if so
+ if(abs(event.pageX - origin.pageX) >= limit || abs(event.pageY - origin.pageY) >= limit) {
+ self.hide(event);
+ }
+ });
+ }
+
+ // Mouse positioning events
+ if(posOptions.target === 'mouse') {
+ // Cache mousemove coords on show targets
+ targets.show.bind('mousemove'+namespace, function(event) {
+ MOUSE = { pageX: event.pageX, pageY: event.pageY, type: 'mousemove' };
+ });
+
+ // If mouse adjustment is on...
+ if(posOptions.adjust.mouse) {
+ // Apply a mouseleave event so we don't get problems with overlapping
+ if(options.hide.event) {
+ // Hide when we leave the tooltip and not onto the show target
+ tooltip.bind('mouseleave'+namespace, function(event) {
+ if((event.relatedTarget || event.target) !== targets.show[0]) { self.hide(event); }
+ });
+
+ // Track if we're on the target or not
+ elements.target.bind('mouseenter'+namespace+' mouseleave'+namespace, function(event) {
+ cache.onTarget = event.type === 'mouseenter';
+ });
+ }
+
+ // Update tooltip position on mousemove
+ targets.document.bind('mousemove'+namespace, function(event) {
+ // Update the tooltip position only if the tooltip is visible and adjustment is enabled
+ if(cache.onTarget && !tooltip.hasClass(disabled) && tooltip.is(':visible')) {
+ self.reposition(event || MOUSE);
+ }
+ });
+ }
+ }
+
+ // Adjust positions of the tooltip on window resize if enabled
+ if(posOptions.adjust.resize || targets.viewport.length) {
+ ($.event.special.resize ? targets.viewport : targets.window).bind('resize'+namespace, repositionMethod);
+ }
+
+ // Adjust tooltip position on scroll if screen adjustment is enabled
+ if(targets.viewport.length || (IE6 && tooltip.css('position') === 'fixed')) {
+ targets.viewport.bind('scroll'+namespace, repositionMethod);
+ }
+ }
+
+ function unassignEvents()
+ {
+ var targets = [
+ options.show.target[0],
+ options.hide.target[0],
+ self.rendered && elements.tooltip[0],
+ options.position.container[0],
+ options.position.viewport[0],
+ window,
+ document
+ ];
+
+ // Check if tooltip is rendered
+ if(self.rendered) {
+ $([]).pushStack( $.grep(targets, function(i){ return typeof i === 'object'; }) ).unbind(namespace);
+ }
+
+ // Tooltip isn't yet rendered, remove render event
+ else { 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 checks
+ '^show.ready$': function() {
+ if(!self.rendered) { self.render(1); }
+ else { self.toggle(TRUE); }
+ },
+
+ // Style checks
+ '^style.classes$': function(obj, o, v) {
+ tooltip.attr('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);
+ },
+
+ // Properties which require event reassignment
+ '^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)': function() {
+ var posOptions = options.position;
+
+ // Set tracking flag
+ tooltip.attr('tracking', posOptions.target === 'mouse' && posOptions.adjust.mouse);
+
+ // Reassign events
+ unassignEvents(); assignEvents();
+ }
+ };
+
+ /*
+ * Public API methods
+ */
+ $.extend(self, {
+ render: function(show)
+ {
+ if(self.rendered) { return self; } // If tooltip has already been rendered, exit
+
+ var text = options.content.text,
+ title = options.content.title.text,
+ posOptions = options.position,
+ callback = $.Event('tooltiprender');
+
+ // Add ARIA attributes to target
+ $.attr(target[0], 'aria-describedby', tooltipID);
+
+ // Create tooltip element
+ tooltip = elements.tooltip = $('
', {
+ 'id': tooltipID,
+ 'class': uitooltip + ' qtip ui-helper-reset ' + defaultClass + ' ' + options.style.classes + ' '+ uitooltip + '-pos-' + options.position.my.abbrev(),
+ 'width': options.style.width || '',
+ 'height': options.style.height || '',
+ 'tracking': posOptions.target === 'mouse' && posOptions.adjust.mouse,
+
+ /* 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/reposition calls for now
+ self.rendered = -1;
+ isDrawing = 1; isPositioning = 1;
+
+ // Create title...
+ if(title) {
+ createTitle();
+
+ // Update title only if its not a callback (called in toggle if so)
+ if(!$.isFunction(title)) { updateTitle(title, FALSE); }
+ }
+
+ // Set proper rendered flag and update content if not a callback function (called in toggle)
+ if(!$.isFunction(text)) { updateContent(text, FALSE); }
+ 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();
+
+ /* 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]);
+
+ // Reset flags
+ isDrawing = 0; isPositioning = 0;
+
+ // Redraw the tooltip manually now we're fully rendered
+ self.redraw();
+
+ // Show tooltip if needed
+ if(options.show.ready || show) {
+ self.toggle(TRUE, cache.event, FALSE);
+ }
+
+ 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,
+ rdraw = /^content\.(title|attr)|style/i,
+ reposition = FALSE,
+ redraw = 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
+ option[notation] = [obj[0], obj[1], value, previous];
+
+ // Also check if we need to reposition / redraw
+ reposition = rmove.test(notation) || reposition;
+ redraw = rdraw.test(notation) || redraw;
+ });
+
+ // 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 / redraw if needed
+ if(tooltip.is(':visible') && self.rendered) {
+ if(reposition) {
+ self.reposition( options.position.target === 'mouse' ? NULL : cache.event );
+ }
+ if(redraw) { self.redraw(); }
+ }
+
+ return self;
+ },
+
+ toggle: function(state, event)
+ {
+ // Render the tooltip if showing and it isn't already
+ if(!self.rendered) { return state ? self.render(1) : self; }
+
+ var type = state ? 'show' : 'hide',
+ opts = options[type],
+ visible = tooltip.is(':visible'),
+ sameTarget = !event || opts.target.length < 2 || cache.target[0] === event.target,
+ eventAsTarget = event && opts.target.add(event.target).length !== opts.target.length,
+ posOptions = options.position,
+ contentOptions = options.content,
+ delay,
+ 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(!tooltip.is(':animated') && visible === state && sameTarget) { 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) &&
+ options.show.target.add(event.target).length === options.show.target.length &&
+ 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) {
+ // Store show origin coordinates
+ cache.origin = $.extend({}, MOUSE);
+
+ // Focus the tooltip
+ self.focus(event);
+
+ // Update tooltip content & title if it's a dynamic function
+ if($.isFunction(contentOptions.text)) { updateContent(contentOptions.text, FALSE); }
+ if($.isFunction(contentOptions.title.text)) { updateTitle(contentOptions.title.text, FALSE); }
+
+ // Cache mousemove events for positioning purposes (if not already tracking)
+ if(!trackingBound && posOptions.target === 'mouse' && posOptions.adjust.mouse) {
+ $(document).bind('mousemove.qtip', function(event) {
+ MOUSE = { pageX: event.pageX, pageY: event.pageY, type: 'mousemove' };
+ });
+ trackingBound = TRUE;
+ }
+
+ // Update the tooltip position
+ self.reposition(event, arguments[2]);
+
+ // Hide other tooltips if tooltip is solo, using it as the context
+ if((callback.solo = !!opts.solo)) { $(selector, opts.solo).not(tooltip).qtip('hide', callback); }
+ }
+ else {
+ // Clear show timer if we're hiding
+ clearTimeout(self.timers.show);
+
+ // Remove cached origin on hide
+ delete cache.origin;
+
+ // Remove mouse tracking event if not needed (all tracking qTips are hidden)
+ if(trackingBound && !$(selector+'[tracking="true"]:visible', opts.solo).not(tooltip).length) {
+ $(document).unbind('mousemove.qtip');
+ trackingBound = FALSE;
+ }
+
+ // Blur the tooltip
+ self.blur(event);
+ }
+
+ // Define post-animation, state specific properties
+ function after() {
+ if(state) {
+ // 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', '');
+
+ // Autofocus elements if enabled
+ if('string' === typeof opts.autofocus) {
+ $(opts.autofocus, tooltip).focus();
+ }
+
+ // If set, hide tooltip when inactive for delay period
+ opts.target.trigger('qtip-'+id+'-inactive');
+ }
+ else {
+ // Reset CSS states
+ tooltip.css({
+ display: '',
+ visibility: '',
+ opacity: '',
+ left: '',
+ top: ''
+ });
+ }
+
+ // Call API method
+ callback = $.Event('tooltip'+(state ? 'visible' : 'hidden'));
+ callback.originalEvent = event ? cache.event : NULL;
+ tooltip.trigger(callback, [self]);
+ }
+
+ // Clear/stop animation
+ tooltip.stop(eventAsTarget, !eventAsTarget);
+
+ // If no effect type is supplied, use a simple toggle
+ if(opts.effect === FALSE) {
+ tooltip[ type ]();
+ after.call(tooltip);
+ }
+
+ // Use custom function if provided
+ else if($.isFunction(opts.effect)) {
+ opts.effect.call(tooltip, self);
+ tooltip.queue('fx', function(n){ after(); n(); });
+ }
+
+ // 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))
+ {
+ // Call API method
+ callback = $.Event('tooltipfocus');
+ callback.originalEvent = cachedEvent;
+ tooltip.trigger(callback, [self, newIndex]);
+
+ // If default action wasn't prevented...
+ if(!callback.isDefaultPrevented()) {
+ // 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);
+ }
+
+ // 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,
+ method = adjust.method.split(' '),
+ elemWidth = tooltip.outerWidth(),
+ elemHeight = tooltip.outerHeight(),
+ targetWidth = 0,
+ targetHeight = 0,
+ callback = $.Event('tooltipmove'),
+ fixed = tooltip.css('position') === 'fixed',
+ viewport = posOptions.viewport,
+ position = { left: 0, top: 0 },
+ container = posOptions.container,
+ flipoffset = FALSE,
+ tip = self.plugins.tip,
+ readjust = {
+ // Axis detection and readjustment indicator
+ horizontal: method[0],
+ vertical: (method[1] = method[1] || method[0]),
+ enabled: viewport.jquery && target[0] !== window && target[0] !== docBody && adjust.method !== 'none',
+
+ // Reposition methods
+ left: function(posLeft) {
+ var isShift = readjust.horizontal === 'shift',
+ viewportScroll = -container.offset.left + viewport.offset.left + viewport.scrollLeft,
+ myWidth = my.x === 'left' ? elemWidth : my.x === 'right' ? -elemWidth : -elemWidth / 2,
+ atWidth = at.x === 'left' ? targetWidth : at.x === 'right' ? -targetWidth : -targetWidth / 2,
+ tipWidth = tip && tip.size ? tip.size.width || 0 : 0,
+ tipAdjust = tip && tip.corner && tip.corner.precedance === 'x' && !isShift ? tipWidth : 0,
+ overflowLeft = viewportScroll - posLeft + tipAdjust,
+ overflowRight = posLeft + elemWidth - viewport.width - viewportScroll + tipAdjust,
+ offset = myWidth - (my.precedance === 'x' || my.x === my.y ? atWidth : 0) - (at.x === 'center' ? targetWidth / 2 : 0),
+ isCenter = my.x === 'center';
+
+ // Optional 'shift' style repositioning
+ if(isShift) {
+ tipAdjust = tip && tip.corner && tip.corner.precedance === 'y' ? tipWidth : 0;
+ offset = (my.x === 'left' ? 1 : -1) * myWidth - tipAdjust;
+
+ // Adjust position but keep it within viewport dimensions
+ position.left += overflowLeft > 0 ? overflowLeft : overflowRight > 0 ? -overflowRight : 0;
+ position.left = Math.max(
+ -container.offset.left + viewport.offset.left + (tipAdjust && tip.corner.x === 'center' ? tip.offset : 0),
+ posLeft - offset,
+ Math.min(
+ Math.max(-container.offset.left + viewport.offset.left + viewport.width, posLeft + offset),
+ position.left
+ )
+ );
+ }
+
+ // Default 'flip' repositioning
+ else {
+ if(overflowLeft > 0 && (my.x !== 'left' || overflowRight > 0)) {
+ position.left -= offset;
+ }
+ else if(overflowRight > 0 && (my.x !== 'right' || overflowLeft > 0) ) {
+ position.left -= isCenter ? -offset : offset;
+ }
+ 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 < viewportScroll && -position.left > overflowRight) { position.left = posLeft; }
+ }
+
+ return position.left - posLeft;
+ },
+ top: function(posTop) {
+ var isShift = readjust.vertical === 'shift',
+ viewportScroll = -container.offset.top + viewport.offset.top + viewport.scrollTop,
+ myHeight = my.y === 'top' ? elemHeight : my.y === 'bottom' ? -elemHeight : -elemHeight / 2,
+ atHeight = at.y === 'top' ? targetHeight : at.y === 'bottom' ? -targetHeight : -targetHeight / 2,
+ tipHeight = tip && tip.size ? tip.size.height || 0 : 0,
+ tipAdjust = tip && tip.corner && tip.corner.precedance === 'y' && !isShift ? tipHeight : 0,
+ overflowTop = viewportScroll - posTop + tipAdjust,
+ overflowBottom = posTop + elemHeight - viewport.height - viewportScroll + tipAdjust,
+ offset = myHeight - (my.precedance === 'y' || my.x === my.y ? atHeight : 0) - (at.y === 'center' ? targetHeight / 2 : 0),
+ isCenter = my.y === 'center';
+
+ // Optional 'shift' style repositioning
+ if(isShift) {
+ tipAdjust = tip && tip.corner && tip.corner.precedance === 'x' ? tipHeight : 0;
+ offset = (my.y === 'top' ? 1 : -1) * myHeight - tipAdjust;
+
+ // Adjust position but keep it within viewport dimensions
+ position.top += overflowTop > 0 ? overflowTop : overflowBottom > 0 ? -overflowBottom : 0;
+ position.top = Math.max(
+ -container.offset.top + viewport.offset.top + (tipAdjust && tip.corner.x === 'center' ? tip.offset : 0),
+ posTop - offset,
+ Math.min(
+ Math.max(-container.offset.top + viewport.offset.top + viewport.height, posTop + offset),
+ position.top
+ )
+ );
+ }
+
+ // Default 'flip' repositioning
+ else {
+ if(overflowTop > 0 && (my.y !== 'top' || overflowBottom > 0)) {
+ position.top -= offset;
+ }
+ else if(overflowBottom > 0 && (my.y !== 'bottom' || overflowTop > 0) ) {
+ position.top -= isCenter ? -offset : offset;
+ }
+ 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;
+ }
+ },
+ win;
+
+ // Check if absolute position was passed
+ if($.isArray(target) && target.length === 2) {
+ // Force left top and set position
+ at = { x: 'left', y: 'top' };
+ position = { left: target[0], top: target[1] };
+ }
+
+ // Check if mouse was the target
+ else if(target === 'mouse' && ((event && event.pageX) || cache.event.pageX)) {
+ // 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 :
+ event && event.pageX && event.type === 'mousemove' ? event :
+ MOUSE && MOUSE.pageX && (adjust.mouse || !event || !event.pageX) ? { pageX: MOUSE.pageX, pageY: MOUSE.pageY } :
+ !adjust.mouse && cache.origin && cache.origin.pageX && options.show.distance ? cache.origin :
+ event) || event || cache.event || MOUSE || {};
+
+ // Use event coordinates for position
+ position = { top: event.pageY, left: event.pageX };
+ }
+
+ // Target wasn't mouse or absolute...
+ 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;
+ }
+ }
+ else {
+ target = cache.target = $(target.jquery ? target : elements.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 = PLUGINS.iOS ? window.innerWidth : target.width();
+ targetHeight = PLUGINS.iOS ? window.innerHeight : target.height();
+
+ if(target[0] === window) {
+ position = {
+ top: (viewport || target).scrollTop(),
+ left: (viewport || target).scrollLeft()
+ };
+ }
+ }
+
+ // Use Imagemap/SVG plugins if needed
+ else if(target.is('area') && PLUGINS.imagemap) {
+ position = PLUGINS.imagemap(target, at, readjust.enabled ? method : FALSE);
+ }
+ 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, container);
+ }
+
+ // Parse returned plugin values into proper variables
+ if(position.offset) {
+ targetWidth = position.width;
+ targetHeight = position.height;
+ flipoffset = position.flipoffset;
+ position = position.offset;
+ }
+
+ // Adjust for position.fixed tooltips (and also iOS scroll bug in v3.2 - v4.0)
+ if((PLUGINS.iOS < 4.1 && PLUGINS.iOS > 3.1) || PLUGINS.iOS == 4.3 || (!PLUGINS.iOS && fixed)) {
+ win = $(window);
+ position.left -= win.scrollLeft();
+ position.top -= win.scrollTop();
+ }
+
+ // 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 viewport positioning is enabled
+ if(readjust.enabled) {
+ // Cache our viewport details
+ viewport = {
+ elem: viewport,
+ height: viewport[ (viewport[0] === window ? 'h' : 'outerH') + 'eight' ](),
+ width: viewport[ (viewport[0] === window ? 'w' : 'outerW') + 'idth' ](),
+ scrollLeft: fixed ? 0 : viewport.scrollLeft(),
+ scrollTop: fixed ? 0 : viewport.scrollTop(),
+ offset: viewport.offset() || { left: 0, top: 0 }
+ };
+ container = {
+ elem: container,
+ scrollLeft: container.scrollLeft(),
+ scrollTop: container.scrollTop(),
+ offset: container.offset() || { left: 0, top: 0 }
+ };
+
+ // Adjust position based onviewport and adjustment options
+ position.adjusted = {
+ left: readjust.horizontal !== 'none' ? readjust.left(position.left) : 0,
+ top: readjust.vertical !== 'none' ? readjust.top(position.top) : 0
+ };
+
+ // Set tooltip position class
+ if(position.adjusted.left + position.adjusted.top) {
+ tooltip.attr('class', tooltip[0].className.replace(/ui-tooltip-pos-\w+/i, uitooltip + '-pos-' + my.abbrev()));
+ }
+
+ // Apply flip offsets supplied by positioning plugins
+ if(flipoffset && position.adjusted.left) { position.left += flipoffset.left; }
+ if(flipoffset && position.adjusted.top) { position.top += flipoffset.top; }
+ }
+
+ //Viewport adjustment is disabled, set values to zero
+ else { position.adjusted = { left: 0, top: 0 }; }
+
+ // Call API method
+ callback.originalEvent = $.extend({}, event);
+ tooltip.trigger(callback, [self, position, viewport.elem || viewport]);
+ if(callback.isDefaultPrevented()){ return self; }
+ delete position.adjusted;
+
+ // If effect is disabled, target it mouse, no animation is defined or positioning gives NaN out, set CSS directly
+ if(effect === FALSE || isNaN(position.left) || isNaN(position.top) || target === 'mouse' || !$.isFunction(posOptions.effect)) {
+ 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;
+ },
+
+ // Max/min width simulator function for all browsers.. yeaaah!
+ redraw: function()
+ {
+ if(self.rendered < 1 || isDrawing) { return self; }
+
+ var container = options.position.container,
+ perc, width, max, min;
+
+ // Set drawing flag
+ isDrawing = 1;
+
+ // If tooltip has a set height, just set it... like a boss!
+ if(options.style.height) { tooltip.css('height', options.style.height); }
+
+ // If tooltip has a set width, just set it... like a boss!
+ if(options.style.width) { tooltip.css('width', options.style.width); }
+
+ // Otherwise simualte max/min width...
+ else {
+ // Reset width and add fluid class
+ tooltip.css('width', '').addClass(fluidClass);
+
+ // Grab our tooltip width (add 1 so we don't get wrapping problems.. huzzah!)
+ width = tooltip.width() + 1;
+
+ // Grab our max/min properties
+ max = tooltip.css('max-width') || '';
+ min = tooltip.css('min-width') || '';
+
+ // Parse into proper pixel values
+ perc = (max + min).indexOf('%') > -1 ? container.width() / 100 : 0;
+ max = ((max.indexOf('%') > -1 ? perc : 1) * parseInt(max, 10)) || width;
+ min = ((min.indexOf('%') > -1 ? perc : 1) * parseInt(min, 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', Math.round(width)).removeClass(fluidClass);
+ }
+
+ // Set drawing flag
+ isDrawing = 0;
+
+ return self;
+ },
+
+ disable: function(state)
+ {
+ if('boolean' !== typeof state) {
+ state = !(tooltip.hasClass(disabled) || cache.disabled);
+ }
+
+ if(self.rendered) {
+ tooltip.toggleClass(disabled, 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),
+ elemAPI = target.data('qtip');
+
+ // Destroy tooltip and any associated plugins if rendered
+ if(self.rendered) {
+ tooltip.stop(1,0).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();
+
+ // If the API if actually this qTip API...
+ if(!elemAPI || self === elemAPI) {
+ // Remove api object
+ $.removeData(t, 'qtip');
+
+ // Reset old title attribute if removed
+ if(options.suppress && title) {
+ $.attr(t, 'title', title);
+ target.removeAttr(oldtitle);
+ }
+
+ // Remove ARIA attributes
+ target.removeAttr('aria-describedby');
+ }
+
+ // Remove qTip events associated with this API
+ target.unbind('.qtip-'+id);
+
+ // Remove ID from sued id object
+ delete usedIDs[self.id];
+
+ return target;
+ }
+ });
+}
+
+// Initialization method
+function init(id, opts)
+{
+ var obj, posOptions, attr, config, title,
+
+ // 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) { log('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));
+
+ // 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 {
+ log('Unable to locate content for tooltip! Aborting render of tooltip on element: ', elem);
+ return FALSE;
+ }
+ }
+
+ // Setup target options
+ if(!posOptions.container.length) { posOptions.container = docBody; }
+ if(posOptions.target === FALSE) { posOptions.target = newTarget; }
+ if(config.show.target === FALSE) { config.show.target = newTarget; }
+ if(config.show.solo === TRUE) { config.show.solo = posOptions.container.closest('body'); }
+ if(config.hide.target === FALSE) { config.hide.target = newTarget; }
+ if(config.position.viewport === TRUE) { config.position.viewport = posOptions.container; }
+
+ // Ensure we only use a single container
+ posOptions.container = posOptions.container.eq(0);
+
+ // Convert position corner values into x and y strings
+ posOptions.at = new 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(config.suppress && (title = $.attr(this, 'title'))) {
+ $(this).removeAttr('title').attr(oldtitle, title);
+ }
+
+ // Initialize the tooltip and add API reference
+ obj = new QTip(elem, config, id, !!attr);
+ $.data(this, 'qtip', obj);
+
+ // Catch remove/removeqtip events on target element to destroy redundant tooltip
+ elem.bind('remove.qtip-'+id+' removeqtip.qtip-'+id, 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 = $.makeArray(arguments).slice(1),
+ 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, namespace, api, id;
+
+ // Find next available ID, or use custom ID if provided
+ id = $.isArray(opts.id) ? opts.id[i] : opts.id;
+ id = !id || id === FALSE || id.length < 1 || usedIDs[id] ? QTIP.nextid++ : (usedIDs[id] = 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
+ };
+
+ /*
+ * Make sure hoverIntent functions properly by using mouseleave as a hide event if
+ * mouseenter/mouseout is used for show.event, even if it isn't in the users options.
+ */
+ if(/mouse(over|enter)/i.test(events.show) && !/mouse(out|leave)/i.test(events.hide)) {
+ events.hide += ' mouseleave' + namespace;
+ }
+
+ /*
+ * Also make sure initial mouse targetting works correctly by caching mousemove coords
+ * on show targets before the tooltip has rendered.
+ *
+ * Also set onTarget when triggered to keep mouse tracking working
+ */
+ targets.show.bind('mousemove'+namespace, function(event) {
+ MOUSE = { pageX: event.pageX, pageY: event.pageY, type: 'mousemove' };
+ api.cache.onTarget = TRUE;
+ });
+
+ // 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 events
+ targets.show.add(targets.hide).unbind(namespace);
+ }
+
+ // Only continue if tooltip isn't disabled
+ if(api.cache.disabled) { return FALSE; }
+
+ // Cache the event data
+ api.cache.event = $.extend({}, event);
+ api.cache.target = event ? $(event.target) : [undefined];
+
+ // 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();
+
+ var f = corner.charAt(0); this.precedance = (f === 't' || f === 'b' ? 'y' : 'x');
+
+ this.string = function() { return this.precedance === 'y' ? this.y+this.x : this.x+this.y; };
+ this.abbrev = 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;
+ };
+
+ this.clone = function() {
+ return { x: this.x, y: this.y, precedance: this.precedance, string: this.string, abbrev: this.abbrev, clone: this.clone };
+ };
+ },
+
+ // Custom (more correct for qTip!) offset calculator
+ offset: function(elem, container) {
+ var pos = elem.offset(),
+ docBody = elem.closest('body')[0],
+ parent = container, scrolled,
+ coffset, overflow;
+
+ 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.css('position') !== 'static') {
+ coffset = parent.position();
+
+ // Account for element positioning, borders and margins
+ pos.left -= coffset.left + (parseInt(parent.css('borderLeftWidth'), 10) || 0) + (parseInt(parent.css('marginLeft'), 10) || 0);
+ pos.top -= coffset.top + (parseInt(parent.css('borderTopWidth'), 10) || 0) + (parseInt(parent.css('marginTop'), 10) || 0);
+
+ // If this is the first parent element with an overflow of "scroll" or "auto", store it
+ if(!scrolled && (overflow = parent.css('overflow')) !== 'hidden' && overflow !== 'visible') { scrolled = parent; }
+ }
+ }
+ while((parent = $(parent[0].offsetParent)).length);
+
+ // Compensate for containers scroll if it also has an offsetParent
+ if(scrolled && scrolled[0] !== docBody) { scroll( scrolled, 1 ); }
+ }
+
+ return pos;
+ },
+
+ /*
+ * iOS 3.2 - 4.0 scroll fix detection used in offset() function.
+ */
+ iOS: parseFloat(
+ ('' + (/CPU.*OS ([0-9_]{1,3})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0,''])[1])
+ .replace('undefined', '3_2').replace('_','.')
+ ) || FALSE,
+
+ /*
+ * jQuery-specific $.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) {
+ var self = this[0],
+ title = 'title',
+ api = $.data(self, 'qtip');
+
+ if(attr === title && api && 'object' === typeof api && api.options.suppress) {
+ if(arguments.length < 2) {
+ return $.attr(self, oldtitle);
+ }
+ else {
+ // If qTip is rendered and title was originally used as content, update it
+ if(api && api.options.content.attr === title && api.cache.attr) {
+ api.set('content.text', val);
+ }
+
+ // Use the regular attr method to set, then cache the result
+ return this.attr(oldtitle, val);
+ }
+ }
+ }
+
+ return $.fn['attr'+replaceSuffix].apply(this, arguments);
+ },
+
+ /* Allow clone to correctly retrieve cached title attributes */
+ clone: function(keepData) {
+ var titles = $([]), title = 'title',
+
+ // Clone our element using the real clone method
+ elems = $.fn['clone'+replaceSuffix].apply(this, arguments);
+
+ // Grab all elements with an oldtitle set, and change it to regular title attribute, if keepData is false
+ if(!keepData) {
+ elems.filter('['+oldtitle+']').attr('title', function() {
+ return $.attr(this, oldtitle);
+ })
+ .removeAttr(oldtitle);
+ }
+
+ return elems;
+ }
+ }
+};
+
+// Apply the fn overrides above
+$.each(PLUGINS.fn, function(name, func) {
+ if(!func || $.fn[name+replaceSuffix]) { return TRUE; }
+
+ var old = $.fn[name+replaceSuffix] = $.fn[name];
+ $.fn[name] = function() {
+ return func.apply(this, arguments) || old.apply(this, arguments);
+ };
+});
+
+/* Fire off 'removeqtip' handler in $.cleanData if jQuery UI not present (it already does similar).
+ * This snippet is taken directly from jQuery UI source code found here:
+ * http://code.jquery.com/ui/jquery-ui-git.js
+ */
+if(!$.ui) {
+ $['cleanData'+replaceSuffix] = $.cleanData;
+ $.cleanData = function( elems ) {
+ for(var i = 0, elem; (elem = elems[i]) !== undefined; i++) {
+ try { $( elem ).triggerHandler('removeqtip'); }
+ catch( e ) {}
+ }
+ $['cleanData'+replaceSuffix]( elems );
+ };
+}
+
+// Set global qTip properties
+QTIP.version = 'nightly';
+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,
+ suppress: 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 flip'
+ },
+ effect: function(api, pos, viewport) {
+ $(this).animate(pos, {
+ duration: 200,
+ queue: FALSE
+ });
+ }
+ },
+ show: {
+ target: FALSE,
+ event: 'mouseenter',
+ effect: TRUE,
+ delay: 90,
+ solo: FALSE,
+ ready: FALSE,
+ autofocus: FALSE
+ },
+ hide: {
+ target: FALSE,
+ event: 'mouseleave',
+ effect: TRUE,
+ delay: 0,
+ fixed: FALSE,
+ inactive: FALSE,
+ leave: 'window',
+ distance: FALSE
+ },
+ style: {
+ classes: '',
+ widget: FALSE,
+ width: FALSE,
+ height: FALSE,
+ def: TRUE
+ },
+ events: {
+ render: NULL,
+ move: NULL,
+ show: NULL,
+ hide: NULL,
+ toggle: NULL,
+ visible: NULL,
+ hidden: NULL,
+ focus: NULL,
+ blur: NULL
+ }
+};
+
+function Ajax(api)
+{
+ var self = this,
+ tooltip = api.elements.tooltip,
+ opts = api.options.content.ajax,
+ namespace = '.qtip-ajax',
+ rscript = /
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+