This week only. Pastebin PRO Accounts Christmas Special! Don't miss out!Want more features on Pastebin? Sign Up, it's FREE!
Guest

Untitled

By: a guest on Feb 16th, 2012  |  syntax: None  |  size: 83.29 KB  |  views: 58  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /*!
  2.  * jquery.qtip. The jQuery tooltip plugin
  3.  *
  4.  * Copyright (c) 2009 Craig Thompson
  5.  * http://craigsworks.com
  6.  *
  7.  * Licensed under MIT
  8.  * http://www.opensource.org/licenses/mit-license.php
  9.  *
  10.  * Launch  : February 2009
  11.  * Version : 1.0.0-rc3
  12.  * Released: Tuesday 12th May, 2009 - 00:00
  13.  * Debug: jquery.qtip.debug.js
  14.  */
  15. (function($)
  16. {
  17.    // Implementation
  18.    $.fn.qtip = function(options, blanket)
  19.    {
  20.       var i, id, interfaces, opts, obj, command, config, api;
  21.  
  22.       // Return API / Interfaces if requested
  23.       if(typeof options == 'string')
  24.       {
  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);
  28.  
  29.          // Return requested object
  30.          if(options == 'api')
  31.             return $(this).data('qtip').interfaces[ $(this).data('qtip').current ];
  32.          else if(options == 'interfaces')
  33.             return $(this).data('qtip').interfaces;
  34.       }
  35.  
  36.       // Validate provided options
  37.       else
  38.       {
  39.          // Set null options object if no options are provided
  40.          if(!options) options = {};
  41.  
  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);
  55.  
  56.          // Build main options object
  57.          opts = $.extend(true, {}, $.fn.qtip.defaults, options);
  58.  
  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);
  62.       };
  63.  
  64.       // Iterate each matched element
  65.       return $(this).each(function() // Return original elements as per jQuery guidelines
  66.       {
  67.          // Check for API commands
  68.          if(typeof options == 'string')
  69.          {
  70.             command = options.toLowerCase();
  71.             interfaces = $(this).qtip('interfaces');
  72.  
  73.             // Make sure API data exists$('.qtip').qtip('destroy')
  74.             if(typeof interfaces == 'object')
  75.             {
  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();
  79.  
  80.                // API call is not a BLANKET DESTROY command
  81.                else
  82.                {
  83.                   // Check if supplied command effects this tooltip only (NOT BLANKET)
  84.                   if(blanket !== true) interfaces = [ $(this).qtip('api') ];
  85.  
  86.                   // Execute command on chosen qTips
  87.                   for(i = 0; i < interfaces.length; i++)
  88.                   {
  89.                      // Destroy command doesn't require tooltip to be rendered
  90.                      if(command == 'destroy') interfaces[i].destroy();
  91.  
  92.                      // Only call API if tooltip is rendered and it wasn't a destroy call
  93.                      else if(interfaces[i].status.rendered === true)
  94.                      {
  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);
  100.                      };
  101.                   };
  102.                };
  103.             };
  104.          }
  105.  
  106.          // No API commands, continue with qTip creation
  107.          else
  108.          {
  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;
  113.  
  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);
  119.  
  120.             // Determine tooltip ID (Reuse array slots if possible)
  121.             id = $.fn.qtip.interfaces.length;
  122.             for(i = 0; i < id; i++)
  123.             {
  124.                if(typeof $.fn.qtip.interfaces[i] == 'undefined'){ id = i; break; };
  125.             };
  126.  
  127.             // Instantiate the tooltip
  128.             obj = new qTip($(this), config, id);
  129.  
  130.             // Add API references
  131.             $.fn.qtip.interfaces[id] = obj;
  132.  
  133.             // Check if element already has qTip data assigned
  134.             if(typeof $(this).data('qtip') == 'object')
  135.             {
  136.                // Set new current interface id
  137.                if(typeof $(this).attr('qtip') === 'undefined')
  138.                   $(this).data('qtip').current = $(this).data('qtip').interfaces.length;
  139.  
  140.                // Push new API interface onto interfaces array
  141.                $(this).data('qtip').interfaces.push(obj);
  142.             }
  143.  
  144.             // No qTip data is present, create now
  145.             else $(this).data('qtip', { current: 0, interfaces: [obj] });
  146.  
  147.             // If prerendering is disabled, create tooltip on showEvent
  148.             if(config.content.prerender === false && config.show.when.event !== false && config.show.ready !== true)
  149.             {
  150.                config.show.when.target.bind(config.show.when.event+'.qtip-'+id+'-create', { qtip: id }, function(event)
  151.                {
  152.                   // Retrieve API interface via passed qTip Id
  153.                   api = $.fn.qtip.interfaces[ event.data.qtip ];
  154.  
  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 };
  158.  
  159.                   // Render tooltip and start the event sequence
  160.                   construct.call( api );
  161.                   api.options.show.when.target.trigger(api.options.show.when.event);
  162.                });
  163.             }
  164.  
  165.             // Prerendering is enabled, create tooltip now
  166.             else
  167.             {
  168.                // Set mouse position cache to top left of the element
  169.                obj.cache.mouse = {
  170.                   x: config.show.when.target.offset().left,
  171.                   y: config.show.when.target.offset().top
  172.                };
  173.  
  174.                // Construct the tooltip
  175.                construct.call(obj);
  176.             }
  177.          };
  178.       });
  179.    };
  180.  
  181.    // Instantiator
  182.    function qTip(target, options, id)
  183.    {
  184.       // Declare this reference
  185.       var self = this;
  186.  
  187.       // Setup class attributes
  188.       self.id = id;
  189.       self.options = options;
  190.       self.status = {
  191.          animated: false,
  192.          rendered: false,
  193.          disabled: false,
  194.          focused: false
  195.       };
  196.       self.elements = {
  197.          target: target.addClass(self.options.style.classes.target),
  198.          tooltip: null,
  199.          wrapper: null,
  200.          content: null,
  201.          contentWrapper: null,
  202.          title: null,
  203.          button: null,
  204.          tip: null,
  205.          bgiframe: null
  206.       };
  207.       self.cache = {
  208.          mouse: {},
  209.          position: {},
  210.          toggle: 0
  211.       };
  212.       self.timers = {};
  213.  
  214.       // Define exposed API methods
  215.       $.extend(self, self.options.api,
  216.       {
  217.          show: function(event)
  218.          {
  219.             var returned, solo;
  220.  
  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');
  224.  
  225.             // Only continue if element is visible
  226.             if(self.elements.tooltip.css('display') !== 'none') return self;
  227.  
  228.             // Clear animation queue
  229.             self.elements.tooltip.stop(true, false);
  230.  
  231.             // Call API method and if return value is false, halt
  232.             returned = self.beforeShow.call(self, event);
  233.             if(returned === false) return self;
  234.  
  235.             // Define afterShow callback method
  236.             function afterShow()
  237.             {
  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);
  241.  
  242.                // Prevent antialias from disappearing in IE7 by removing filter attribute
  243.                if($.browser.msie) self.elements.tooltip.get(0).style.removeAttribute('filter');
  244.             };
  245.  
  246.             // Maintain toggle functionality if enabled
  247.             self.cache.toggle = 1;
  248.  
  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));
  252.  
  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(); });
  257.  
  258.             // Show tooltip
  259.             if(typeof self.options.show.effect.type == 'function')
  260.             {
  261.                self.options.show.effect.type.call(self.elements.tooltip, self.options.show.effect.length);
  262.                self.elements.tooltip.queue(function(){ afterShow(); $(this).dequeue(); });
  263.             }
  264.             else
  265.             {
  266.                switch(self.options.show.effect.type.toLowerCase())
  267.                {
  268.                   case 'fade':
  269.                      self.elements.tooltip.fadeIn(self.options.show.effect.length, afterShow);
  270.                      break;
  271.                   case 'slide':
  272.                      self.elements.tooltip.slideDown(self.options.show.effect.length, function()
  273.                      {
  274.                         afterShow();
  275.                         if(self.options.position.type !== 'static') self.updatePosition(event, true);
  276.                      });
  277.                      break;
  278.                   case 'grow':
  279.                      self.elements.tooltip.show(self.options.show.effect.length, afterShow);
  280.                      break;
  281.                   default:
  282.                      self.elements.tooltip.show(null, afterShow);
  283.                      break;
  284.                };
  285.  
  286.                // Add active class to tooltip
  287.                self.elements.tooltip.addClass(self.options.style.classes.active);
  288.             };
  289.  
  290.             // Log event and return
  291.             return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_SHOWN, 'show');
  292.          },
  293.  
  294.          hide: function(event)
  295.          {
  296.             var returned;
  297.  
  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');
  301.  
  302.             // Only continue if element is visible
  303.             else if(self.elements.tooltip.css('display') === 'none') return self;
  304.  
  305.             // Stop show timer and animation queue
  306.             clearTimeout(self.timers.show);
  307.             self.elements.tooltip.stop(true, false);
  308.  
  309.             // Call API method and if return value is false, halt
  310.             returned = self.beforeHide.call(self, event);
  311.             if(returned === false) return self;
  312.  
  313.             // Define afterHide callback method
  314.             function afterHide(){ self.onHide.call(self, event); };
  315.  
  316.             // Maintain toggle functionality if enabled
  317.             self.cache.toggle = 0;
  318.  
  319.             // Hide tooltip
  320.             if(typeof self.options.hide.effect.type == 'function')
  321.             {
  322.                self.options.hide.effect.type.call(self.elements.tooltip, self.options.hide.effect.length);
  323.                self.elements.tooltip.queue(function(){ afterHide(); $(this).dequeue(); });
  324.             }
  325.             else
  326.             {
  327.                switch(self.options.hide.effect.type.toLowerCase())
  328.                {
  329.                   case 'fade':
  330.                      self.elements.tooltip.fadeOut(self.options.hide.effect.length, afterHide);
  331.                      break;
  332.                   case 'slide':
  333.                      self.elements.tooltip.slideUp(self.options.hide.effect.length, afterHide);
  334.                      break;
  335.                   case 'grow':
  336.                      self.elements.tooltip.hide(self.options.hide.effect.length, afterHide);
  337.                      break;
  338.                   default:
  339.                      self.elements.tooltip.hide(null, afterHide);
  340.                      break;
  341.                };
  342.  
  343.                // Remove active class to tooltip
  344.                self.elements.tooltip.removeClass(self.options.style.classes.active);
  345.             };
  346.  
  347.             // Log event and return
  348.             return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_HIDDEN, 'hide');
  349.          },
  350.  
  351.          updatePosition: function(event, animate)
  352.          {
  353.             var i, target, tooltip, coords, mapName, imagePos, newPosition, ieAdjust, ie6Adjust, borderAdjust, mouseAdjust, offset, curPosition, returned
  354.  
  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');
  358.  
  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');
  362.  
  363.             // Define property objects
  364.             target = {
  365.                position: { left: 0, top: 0 },
  366.                dimensions: { height: 0, width: 0 },
  367.                corner: self.options.position.corner.target
  368.             };
  369.             tooltip = {
  370.                position: self.getPosition(),
  371.                dimensions: self.getDimensions(),
  372.                corner: self.options.position.corner.tooltip
  373.             };
  374.  
  375.             // Target is an HTML element
  376.             if(self.options.position.target !== 'mouse')
  377.             {
  378.                // If the HTML element is AREA, calculate position manually
  379.                if(self.options.position.target.get(0).nodeName.toLowerCase() == 'area')
  380.                {
  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]);
  384.  
  385.                   // Setup target position object
  386.                   mapName = self.options.position.target.parent('map').attr('name');
  387.                   imagePos = $('img[usemap="#'+mapName+'"]:first').offset();
  388.                   target.position = {
  389.                      left: Math.floor(imagePos.left + coords[0]),
  390.                      top: Math.floor(imagePos.top + coords[1])
  391.                   };
  392.  
  393.                   // Determine width and height of the area
  394.                   switch(self.options.position.target.attr('shape').toLowerCase())
  395.                   {
  396.                      case 'rect':
  397.                         target.dimensions = {
  398.                            width: Math.ceil(Math.abs(coords[2] - coords[0])),
  399.                            height: Math.ceil(Math.abs(coords[3] - coords[1]))
  400.                         };
  401.                         break;
  402.  
  403.                      case 'circle':
  404.                         target.dimensions = {
  405.                            width: coords[2] + 1,
  406.                            height: coords[2] + 1
  407.                         };
  408.                         break;
  409.  
  410.                      case 'poly':
  411.                         target.dimensions = {
  412.                            width: coords[0],
  413.                            height: coords[1]
  414.                         };
  415.  
  416.                         for(i = 0; i < coords.length; i++)
  417.                         {
  418.                            if(i % 2 == 0)
  419.                            {
  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]);
  424.                            }
  425.                            else
  426.                            {
  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]);
  431.                            };
  432.                         };
  433.  
  434.                         target.dimensions.width = target.dimensions.width - (target.position.left - imagePos.left);
  435.                         target.dimensions.height = target.dimensions.height - (target.position.top - imagePos.top);
  436.                         break;
  437.  
  438.                      default:
  439.                         return $.fn.qtip.log.error.call(self, 4, $.fn.qtip.constants.INVALID_AREA_SHAPE, 'updatePosition');
  440.                         break;
  441.                   };
  442.  
  443.                   // Adjust position by 2 pixels (Positioning bug?)
  444.                   target.dimensions.width -= 2; target.dimensions.height -= 2;
  445.                }
  446.  
  447.                // Target is the document
  448.                else if(self.options.position.target.add(document.body).length === 1)
  449.                {
  450.                   target.position = { left: $(document).scrollLeft(), top: $(document).scrollTop() };
  451.                   target.dimensions = { height: $(window).height(), width: $(window).width() };
  452.                }
  453.  
  454.                // Target is a regular HTML element, find position normally
  455.                else
  456.                {
  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;
  460.                   else
  461.                      target.position = self.options.position.target.offset();
  462.  
  463.                   // Setup dimensions objects
  464.                   target.dimensions = {
  465.                      height: self.options.position.target.outerHeight(),
  466.                      width: self.options.position.target.outerWidth()
  467.                   };
  468.                };
  469.  
  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;
  474.  
  475.                if(target.corner.search(/bottom/i) !== -1)
  476.                   newPosition.top += target.dimensions.height;
  477.  
  478.                if(target.corner.search(/((top|bottom)Middle)|center/) !== -1)
  479.                   newPosition.left += (target.dimensions.width / 2);
  480.  
  481.                if(target.corner.search(/((left|right)Middle)|center/) !== -1)
  482.                   newPosition.top += (target.dimensions.height / 2);
  483.             }
  484.  
  485.             // Mouse is the target, set position to current mouse coordinates
  486.             else
  487.             {
  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 };
  491.             };
  492.  
  493.             // Calculate correct target corner position
  494.             if(tooltip.corner.search(/right/i) !== -1)
  495.                newPosition.left -= tooltip.dimensions.width;
  496.  
  497.             if(tooltip.corner.search(/bottom/i) !== -1)
  498.                newPosition.top -= tooltip.dimensions.height;
  499.  
  500.             if(tooltip.corner.search(/((top|bottom)Middle)|center/) !== -1)
  501.                newPosition.left -= (tooltip.dimensions.width / 2);
  502.  
  503.             if(tooltip.corner.search(/((left|right)Middle)|center/) !== -1)
  504.                newPosition.top -= (tooltip.dimensions.height / 2);
  505.  
  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!
  509.  
  510.             // Adjust for border radius
  511.             if(self.options.style.border.radius > 0)
  512.             {
  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;
  517.  
  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;
  522.             };
  523.  
  524.             // IE only adjustments (Pixel perfect!)
  525.             if(ieAdjust)
  526.             {
  527.                if(tooltip.corner.search(/top/) !== -1)
  528.                   newPosition.top -= ieAdjust
  529.                else if(tooltip.corner.search(/bottom/) !== -1)
  530.                   newPosition.top += ieAdjust
  531.  
  532.                if(tooltip.corner.search(/left/) !== -1)
  533.                   newPosition.left -= ieAdjust
  534.                else if(tooltip.corner.search(/right/) !== -1)
  535.                   newPosition.left += ieAdjust
  536.  
  537.                if(tooltip.corner.search(/leftMiddle|rightMiddle/) !== -1)
  538.                   newPosition.top -= 1
  539.             };
  540.  
  541.             // If screen adjustment is enabled, apply adjustments
  542.             if(self.options.position.adjust.screen === true)
  543.                newPosition = screenAdjust.call(self, newPosition, target, tooltip);
  544.  
  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)
  547.             {
  548.                if(self.options.position.adjust.screen === true && self.elements.tip)
  549.                   mouseAdjust = self.elements.tip.attr('rel');
  550.                else
  551.                   mouseAdjust = self.options.position.corner.tooltip;
  552.  
  553.                newPosition.left += (mouseAdjust.search(/right/i) !== -1) ? -6 : 6;
  554.                newPosition.top += (mouseAdjust.search(/bottom/i) !== -1) ? -6 : 6;
  555.             }
  556.  
  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)
  559.             {
  560.                $('select, object').each(function()
  561.                {
  562.                   offset = $(this).offset();
  563.                   offset.bottom = offset.top + $(this).height();
  564.                   offset.right = offset.left + $(this).width();
  565.  
  566.                   if(newPosition.top + tooltip.dimensions.height >= offset.top
  567.                   && newPosition.left + tooltip.dimensions.width >= offset.left)
  568.                      bgiframe.call(self);
  569.                });
  570.             };
  571.  
  572.             // Add user xy adjustments
  573.             newPosition.left += self.options.position.adjust.x;
  574.             newPosition.top += self.options.position.adjust.y;
  575.  
  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)
  579.             {
  580.                // Call API method and if return value is false, halt
  581.                returned = self.beforePositionUpdate.call(self, event);
  582.                if(returned === false) return self;
  583.  
  584.                // Cache new position
  585.                self.cache.position = newPosition;
  586.  
  587.                // Check if animation is enabled
  588.                if(animate === true)
  589.                {
  590.                   // Set animated status
  591.                   self.status.animated = true;
  592.  
  593.                   // Animate and reset animated status on animation end
  594.                   self.elements.tooltip.animate(newPosition, 200, 'swing', function(){ self.status.animated = false });
  595.                }
  596.  
  597.                // Set new position via CSS
  598.                else self.elements.tooltip.css(newPosition);
  599.  
  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');
  604.             };
  605.  
  606.             return self;
  607.          },
  608.  
  609.          updateWidth: function(newWidth)
  610.          {
  611.             var hidden;
  612.  
  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');
  616.  
  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');
  620.  
  621.             // Setup elements which must be hidden during width update
  622.             hidden = self.elements.contentWrapper.siblings().add(self.elements.tip).add(self.elements.button);
  623.  
  624.             // Calculate the new width if one is not supplied
  625.             if(!newWidth)
  626.             {
  627.                // Explicit width is set
  628.                if(typeof self.options.style.width.value == 'number')
  629.                   newWidth = self.options.style.width.value;
  630.  
  631.                // No width is set, proceed with auto detection
  632.                else
  633.                {
  634.                   // Set width to auto initally to determine new width and hide other elements
  635.                   self.elements.tooltip.css({ width: 'auto' });
  636.                   hidden.hide();
  637.  
  638.                   // Set position and zoom to defaults to prevent IE hasLayout bug
  639.                   if($.browser.msie)
  640.                      self.elements.wrapper.add(self.elements.contentWrapper.children()).css({ zoom: 'normal' });
  641.  
  642.                   // Set the new width
  643.                   newWidth = self.getDimensions().width + 1;
  644.  
  645.                   // Make sure its within the maximum and minimum width boundries
  646.                   if(!self.options.style.width.value)
  647.                   {
  648.                      if(newWidth > self.options.style.width.max) newWidth = self.options.style.width.max
  649.                      if(newWidth < self.options.style.width.min) newWidth = self.options.style.width.min
  650.                   };
  651.                };
  652.             };
  653.  
  654.             // Adjust newWidth by 1px if width is odd (IE6 rounding bug fix)
  655.             if(newWidth % 2 !== 0) newWidth -= 1;
  656.  
  657.             // Set the new calculated width and unhide other elements
  658.             self.elements.tooltip.width(newWidth);
  659.             hidden.show();
  660.  
  661.             // Set the border width, if enabled
  662.             if(self.options.style.border.radius)
  663.             {
  664.                self.elements.tooltip.find('.qtip-betweenCorners').each(function(i)
  665.                {
  666.                   $(this).width(newWidth - (self.options.style.border.radius * 2));
  667.                })
  668.             };
  669.  
  670.             // IE only adjustments
  671.             if($.browser.msie)
  672.             {
  673.                // Reset position and zoom to give the wrapper layout (IE hasLayout bug)
  674.                self.elements.wrapper.add(self.elements.contentWrapper.children()).css({ zoom: '1' });
  675.  
  676.                // Set the new width
  677.                self.elements.wrapper.width(newWidth);
  678.  
  679.                // Adjust BGIframe height and width if enabled
  680.                if(self.elements.bgiframe) self.elements.bgiframe.width(newWidth).height(self.getDimensions.height);
  681.             };
  682.  
  683.             // Log event and return
  684.             return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_WIDTH_UPDATED, 'updateWidth');
  685.          },
  686.  
  687.          updateStyle: function(name)
  688.          {
  689.             var tip, borders, context, corner, coordinates;
  690.  
  691.             // Make sure tooltip is rendered and if not, return
  692.             if(!self.status.rendered)
  693.                return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'updateStyle');
  694.  
  695.             // Return if style is not defined or name is not a string
  696.             else if(typeof name !== 'string' || !$.fn.qtip.styles[name])
  697.                return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.STYLE_NOT_DEFINED, 'updateStyle');
  698.  
  699.             // Set the new style object
  700.             self.options.style = buildStyle.call(self, $.fn.qtip.styles[name], self.options.user.style);
  701.  
  702.             // Update initial styles of content and title elements
  703.             self.elements.content.css( jQueryStyle(self.options.style) );
  704.             if(self.options.content.title.text !== false)
  705.                self.elements.title.css( jQueryStyle(self.options.style.title, true) );
  706.  
  707.             // Update CSS border colour
  708.             self.elements.contentWrapper.css({ borderColor: self.options.style.border.color });
  709.  
  710.             // Update tip color if enabled
  711.             if(self.options.style.tip.corner !== false)
  712.             {
  713.                if($('<canvas>').get(0).getContext)
  714.                {
  715.                   // Retrieve canvas context and clear
  716.                   tip = self.elements.tooltip.find('.qtip-tip canvas:first');
  717.                   context = tip.get(0).getContext('2d');
  718.                   context.clearRect(0,0,300,300);
  719.  
  720.                   // Draw new tip
  721.                   corner = tip.parent('div[rel]:first').attr('rel');
  722.                   coordinates = calculateTip(corner, self.options.style.tip.size.width, self.options.style.tip.size.height);
  723.                   drawTip.call(self, tip, coordinates, self.options.style.tip.color || self.options.style.border.color);
  724.                }
  725.                else if($.browser.msie)
  726.                {
  727.                   // Set new fillcolor attribute
  728.                   tip = self.elements.tooltip.find('.qtip-tip [nodeName="shape"]');
  729.                   tip.attr('fillcolor', self.options.style.tip.color || self.options.style.border.color);
  730.                };
  731.             };
  732.  
  733.             // Update border colors if enabled
  734.             if(self.options.style.border.radius > 0)
  735.             {
  736.                self.elements.tooltip.find('.qtip-betweenCorners').css({ backgroundColor: self.options.style.border.color });
  737.  
  738.                if($('<canvas>').get(0).getContext)
  739.                {
  740.                   borders = calculateBorders(self.options.style.border.radius)
  741.                   self.elements.tooltip.find('.qtip-wrapper canvas').each(function()
  742.                   {
  743.                      // Retrieve canvas context and clear
  744.                      context = $(this).get(0).getContext('2d');
  745.                      context.clearRect(0,0,300,300);
  746.  
  747.                      // Draw new border
  748.                      corner = $(this).parent('div[rel]:first').attr('rel')
  749.                      drawBorder.call(self, $(this), borders[corner],
  750.                         self.options.style.border.radius, self.options.style.border.color);
  751.                   });
  752.                }
  753.                else if($.browser.msie)
  754.                {
  755.                   // Set new fillcolor attribute on each border corner
  756.                   self.elements.tooltip.find('.qtip-wrapper [nodeName="arc"]').each(function()
  757.                   {
  758.                      $(this).attr('fillcolor', self.options.style.border.color)
  759.                   });
  760.                };
  761.             };
  762.  
  763.             // Log event and return
  764.             return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_STYLE_UPDATED, 'updateStyle');
  765.          },
  766.  
  767.          updateContent: function(content, reposition)
  768.          {
  769.             var parsedContent, images, loadedImages;
  770.  
  771.             // Make sure tooltip is rendered and if not, return
  772.             if(!self.status.rendered)
  773.                return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'updateContent');
  774.  
  775.             // Make sure content is defined before update
  776.             else if(!content)
  777.                return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.NO_CONTENT_PROVIDED, 'updateContent');
  778.  
  779.             // Call API method and set new content if a string is returned
  780.             parsedContent = self.beforeContentUpdate.call(self, content);
  781.             if(typeof parsedContent == 'string') content = parsedContent;
  782.             else if(parsedContent === false) return;
  783.  
  784.             // Set position and zoom to defaults to prevent IE hasLayout bug
  785.             if($.browser.msie) self.elements.contentWrapper.children().css({ zoom: 'normal' });
  786.  
  787.             // Append new content if its a DOM array and show it if hidden
  788.             if(content.jquery && content.length > 0)
  789.                content.clone(true).appendTo(self.elements.content).show();
  790.  
  791.             // Content is a regular string, insert the new content
  792.             else self.elements.content.html(content);
  793.  
  794.             // Check if images need to be loaded before position is updated to prevent mis-positioning
  795.             images = self.elements.content.find('img[complete=false]');
  796.             if(images.length > 0)
  797.             {
  798.                loadedImages = 0;
  799.                images.each(function(i)
  800.                {
  801.                   $('<img src="'+ $(this).attr('src') +'" />')
  802.                      .load(function(){ if(++loadedImages == images.length) afterLoad(); });
  803.                });
  804.             }
  805.             else afterLoad();
  806.  
  807.             function afterLoad()
  808.             {
  809.                // Update the tooltip width
  810.                self.updateWidth();
  811.  
  812.                // If repositioning is enabled, update positions
  813.                if(reposition !== false)
  814.                {
  815.                   // Update position if tooltip isn't static
  816.                   if(self.options.position.type !== 'static')
  817.                      self.updatePosition(self.elements.tooltip.is(':visible'), true);
  818.  
  819.                   // Reposition the tip if enabled
  820.                   if(self.options.style.tip.corner !== false)
  821.                      positionTip.call(self);
  822.                };
  823.             };
  824.  
  825.             // Call API method and log event
  826.             self.onContentUpdate.call(self);
  827.             return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_CONTENT_UPDATED, 'loadContent');
  828.          },
  829.  
  830.          loadContent: function(url, data, method)
  831.          {
  832.             var returned;
  833.  
  834.             // Make sure tooltip is rendered and if not, return
  835.             if(!self.status.rendered)
  836.                return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'loadContent');
  837.  
  838.             // Call API method and if return value is false, halt
  839.             returned = self.beforeContentLoad.call(self);
  840.             if(returned === false) return self;
  841.  
  842.             // Load content using specified request type
  843.             if(method == 'post')
  844.                $.post(url, data, setupContent);
  845.             else
  846.                $.get(url, data, setupContent);
  847.  
  848.             function setupContent(content)
  849.             {
  850.                // Call API method and log event
  851.                self.onContentLoad.call(self);
  852.                $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_CONTENT_LOADED, 'loadContent');
  853.  
  854.                // Update the content
  855.                self.updateContent(content);
  856.             };
  857.  
  858.             return self;
  859.          },
  860.  
  861.          updateTitle: function(content)
  862.          {
  863.             // Make sure tooltip is rendered and if not, return
  864.             if(!self.status.rendered)
  865.                return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'updateTitle');
  866.  
  867.             // Make sure content is defined before update
  868.             else if(!content)
  869.                return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.NO_CONTENT_PROVIDED, 'updateTitle');
  870.  
  871.             // Call API method and if return value is false, halt
  872.             returned = self.beforeTitleUpdate.call(self);
  873.             if(returned === false) return self;
  874.  
  875.             // Set the new content and reappend the button if enabled
  876.             if(self.elements.button) self.elements.button = self.elements.button.clone(true);
  877.             self.elements.title.html(content)
  878.             if(self.elements.button) self.elements.title.prepend(self.elements.button);
  879.  
  880.             // Call API method and log event
  881.             self.onTitleUpdate.call(self);
  882.             return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_TITLE_UPDATED, 'updateTitle');
  883.          },
  884.  
  885.          focus: function(event)
  886.          {
  887.             var curIndex, newIndex, elemIndex, returned;
  888.  
  889.             // Make sure tooltip is rendered and if not, return
  890.             if(!self.status.rendered)
  891.                return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'focus');
  892.  
  893.             else if(self.options.position.type == 'static')
  894.                return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.CANNOT_FOCUS_STATIC, 'focus');
  895.  
  896.             // Set z-index variables
  897.             curIndex = parseInt( self.elements.tooltip.css('z-index') );
  898.             newIndex = 6000 + $('div.qtip[qtip]').length - 1;
  899.  
  900.             // Only update the z-index if it has changed and tooltip is not already focused
  901.             if(!self.status.focused && curIndex !== newIndex)
  902.             {
  903.                // Call API method and if return value is false, halt
  904.                returned = self.beforeFocus.call(self, event);
  905.                if(returned === false) return self;
  906.  
  907.                // Loop through all other tooltips
  908.                $('div.qtip[qtip]').not(self.elements.tooltip).each(function()
  909.                {
  910.                   if($(this).qtip('api').status.rendered === true)
  911.                   {
  912.                      elemIndex = parseInt($(this).css('z-index'));
  913.  
  914.                      // Reduce all other tooltip z-index by 1
  915.                      if(typeof elemIndex == 'number' && elemIndex > -1)
  916.                         $(this).css({ zIndex: parseInt( $(this).css('z-index') ) - 1 });
  917.  
  918.                      // Set focused status to false
  919.                      $(this).qtip('api').status.focused = false;
  920.                   }
  921.                })
  922.  
  923.                // Set the new z-index and set focus status to true
  924.                self.elements.tooltip.css({ zIndex: newIndex });
  925.                self.status.focused = true;
  926.  
  927.                // Call API method and log event
  928.                self.onFocus.call(self, event);
  929.                $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_FOCUSED, 'focus');
  930.             };
  931.  
  932.             return self;
  933.          },
  934.  
  935.          disable: function(state)
  936.          {
  937.             // Make sure tooltip is rendered and if not, return
  938.             if(!self.status.rendered)
  939.                return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'disable');
  940.  
  941.             if(state)
  942.             {
  943.                // Tooltip is not already disabled, proceed
  944.                if(!self.status.disabled)
  945.                {
  946.                   // Set the disabled flag and log event
  947.                   self.status.disabled = true;
  948.                   $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_DISABLED, 'disable');
  949.                }
  950.  
  951.                // Tooltip is already disabled, inform user via log
  952.                else  $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.TOOLTIP_ALREADY_DISABLED, 'disable');
  953.             }
  954.             else
  955.             {
  956.                // Tooltip is not already enabled, proceed
  957.                if(self.status.disabled)
  958.                {
  959.                   // Reassign events, set disable status and log
  960.                   self.status.disabled = false;
  961.                   $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_ENABLED, 'disable');
  962.                }
  963.  
  964.                // Tooltip is already enabled, inform the user via log
  965.                else $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.TOOLTIP_ALREADY_ENABLED, 'disable');
  966.             };
  967.  
  968.             return self;
  969.          },
  970.  
  971.          destroy: function()
  972.          {
  973.             var i, returned, interfaces;
  974.  
  975.             // Call API method and if return value is false, halt
  976.             returned = self.beforeDestroy.call(self);
  977.             if(returned === false) return self;
  978.  
  979.             // Check if tooltip is rendered
  980.             if(self.status.rendered)
  981.             {
  982.                // Remove event handlers and remove element
  983.                self.options.show.when.target.unbind('mousemove.qtip', self.updatePosition);
  984.                self.options.show.when.target.unbind('mouseout.qtip', self.hide);
  985.                self.options.show.when.target.unbind(self.options.show.when.event + '.qtip');
  986.                self.options.hide.when.target.unbind(self.options.hide.when.event + '.qtip');
  987.                self.elements.tooltip.unbind(self.options.hide.when.event + '.qtip');
  988.                self.elements.tooltip.unbind('mouseover.qtip', self.focus);
  989.                self.elements.tooltip.remove();
  990.             }
  991.  
  992.             // Tooltip isn't yet rendered, remove render event
  993.             else self.options.show.when.target.unbind(self.options.show.when.event+'.qtip-create');
  994.  
  995.             // Check to make sure qTip data is present on target element
  996.             if(typeof self.elements.target.data('qtip') == 'object')
  997.             {
  998.                // Remove API references from interfaces object
  999.                interfaces = self.elements.target.data('qtip').interfaces;
  1000.                if(typeof interfaces == 'object' && interfaces.length > 0)
  1001.                {
  1002.                   // Remove API from interfaces array
  1003.                   for(i = 0; i < interfaces.length - 1; i++)
  1004.                      if(interfaces[i].id == self.id) interfaces.splice(i, 1)
  1005.                }
  1006.             }
  1007.             delete $.fn.qtip.interfaces[self.id];
  1008.  
  1009.             // Set qTip current id to previous tooltips API if available
  1010.             if(typeof interfaces == 'object' && interfaces.length > 0)
  1011.                self.elements.target.data('qtip').current = interfaces.length -1;
  1012.             else
  1013.                self.elements.target.removeData('qtip');
  1014.  
  1015.             // Call API method and log destroy
  1016.             self.onDestroy.call(self);
  1017.             $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_DESTROYED, 'destroy');
  1018.  
  1019.             return self.elements.target
  1020.          },
  1021.  
  1022.          getPosition: function()
  1023.          {
  1024.             var show, offset;
  1025.  
  1026.             // Make sure tooltip is rendered and if not, return
  1027.             if(!self.status.rendered)
  1028.                return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'getPosition');
  1029.  
  1030.             show = (self.elements.tooltip.css('display') !== 'none') ? false : true;
  1031.  
  1032.             // Show and hide tooltip to make sure coordinates are returned
  1033.             if(show) self.elements.tooltip.css({ visiblity: 'hidden' }).show();
  1034.             offset = self.elements.tooltip.offset();
  1035.             if(show) self.elements.tooltip.css({ visiblity: 'visible' }).hide();
  1036.  
  1037.             return offset;
  1038.          },
  1039.  
  1040.          getDimensions: function()
  1041.          {
  1042.             var show, dimensions;
  1043.  
  1044.             // Make sure tooltip is rendered and if not, return
  1045.             if(!self.status.rendered)
  1046.                return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'getDimensions');
  1047.  
  1048.             show = (!self.elements.tooltip.is(':visible')) ? true : false;
  1049.  
  1050.             // Show and hide tooltip to make sure dimensions are returned
  1051.             if(show) self.elements.tooltip.css({ visiblity: 'hidden' }).show();
  1052.             dimensions = {
  1053.                height: self.elements.tooltip.outerHeight(),
  1054.                width: self.elements.tooltip.outerWidth()
  1055.             };
  1056.             if(show) self.elements.tooltip.css({ visiblity: 'visible' }).hide();
  1057.  
  1058.             return dimensions;
  1059.          }
  1060.       });
  1061.    };
  1062.  
  1063.    // Define priamry construct function
  1064.    function construct()
  1065.    {
  1066.       var self, adjust, content, url, data, method, tempLength;
  1067.       self = this;
  1068.  
  1069.       // Call API method
  1070.       self.beforeRender.call(self);
  1071.  
  1072.       // Set rendered status to true
  1073.       self.status.rendered = true;
  1074.  
  1075.       // Create initial tooltip elements
  1076.       self.elements.tooltip =  '<div qtip="'+self.id+'" ' +
  1077.          'class="qtip '+(self.options.style.classes.tooltip || self.options.style)+'"' +
  1078.          'style="display:none; -moz-border-radius:0; -webkit-border-radius:0; border-radius:0;' +
  1079.          'position:'+self.options.position.type+';">' +
  1080.          '  <div class="qtip-wrapper" style="position:relative; overflow:hidden; text-align:left;">' +
  1081.          '    <div class="qtip-contentWrapper" style="overflow:hidden;">' +
  1082.          '       <div class="qtip-content '+self.options.style.classes.content+'"></div>' +
  1083.          '</div></div></div>';
  1084.  
  1085.       // Append to container element
  1086.       self.elements.tooltip = $(self.elements.tooltip);
  1087.       self.elements.tooltip.appendTo(self.options.position.container)
  1088.  
  1089.       // Setup tooltip qTip data
  1090.       self.elements.tooltip.data('qtip', { current: 0, interfaces: [self] });
  1091.  
  1092.       // Setup element references
  1093.       self.elements.wrapper = self.elements.tooltip.children('div:first');
  1094.       self.elements.contentWrapper = self.elements.wrapper.children('div:first').css({ background: self.options.style.background });
  1095.       self.elements.content = self.elements.contentWrapper.children('div:first').css( jQueryStyle(self.options.style) );
  1096.  
  1097.       // Apply IE hasLayout fix to wrapper and content elements
  1098.       if($.browser.msie) self.elements.wrapper.add(self.elements.content).css({ zoom: 1 });
  1099.  
  1100.       // Setup tooltip attributes
  1101.       if(self.options.hide.when.event == 'unfocus') self.elements.tooltip.attr('unfocus', true);
  1102.  
  1103.       // If an explicit width is set, updateWidth prior to setting content to prevent dirty rendering
  1104.       if(typeof self.options.style.width.value == 'number') self.updateWidth();
  1105.  
  1106.       // Create borders and tips if supported by the browser
  1107.       if($('<canvas>').get(0).getContext || $.browser.msie)
  1108.       {
  1109.          // Create border
  1110.          if(self.options.style.border.radius > 0)
  1111.             createBorder.call(self);
  1112.          else
  1113.             self.elements.contentWrapper.css({ border: self.options.style.border.width+'px solid '+self.options.style.border.color  });
  1114.  
  1115.          // Create tip if enabled
  1116.          if(self.options.style.tip.corner !== false)
  1117.             createTip.call(self);
  1118.       }
  1119.  
  1120.       // Neither canvas or VML is supported, tips and borders cannot be drawn!
  1121.       else
  1122.       {
  1123.          // Set defined border width
  1124.          self.elements.contentWrapper.css({ border: self.options.style.border.width+'px solid '+self.options.style.border.color  });
  1125.  
  1126.          // Reset border radius and tip
  1127.          self.options.style.border.radius = 0;
  1128.          self.options.style.tip.corner = false;
  1129.  
  1130.          // Inform via log
  1131.          $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.CANVAS_VML_NOT_SUPPORTED, 'render');
  1132.       };
  1133.  
  1134.       // Use the provided content string or DOM array
  1135.       if((typeof self.options.content.text == 'string' && self.options.content.text.length > 0)
  1136.       || (self.options.content.text.jquery && self.options.content.text.length > 0))
  1137.          content = self.options.content.text;
  1138.  
  1139.       // Use title string for content if present
  1140.       else if(typeof self.elements.target.attr('title') == 'string' && self.elements.target.attr('title').length > 0)
  1141.       {
  1142.          content = self.elements.target.attr('title').replace("\\n", '<br />');
  1143.          self.elements.target.attr('title', ''); // Remove title attribute to prevent default tooltip showing
  1144.       }
  1145.  
  1146.       // No title is present, use alt attribute instead
  1147.       else if(typeof self.elements.target.attr('alt') == 'string' && self.elements.target.attr('alt').length > 0)
  1148.       {
  1149.          content = self.elements.target.attr('alt').replace("\\n", '<br />');
  1150.          self.elements.target.attr('alt', ''); // Remove alt attribute to prevent default tooltip showing
  1151.       }
  1152.  
  1153.       // No valid content was provided, inform via log
  1154.       else
  1155.       {
  1156.          content = ' ';
  1157.          $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.NO_VALID_CONTENT, 'render');
  1158.       };
  1159.  
  1160.       // Set the tooltips content and create title if enabled
  1161.       if(self.options.content.title.text !== false) createTitle.call(self);
  1162.       self.updateContent(content);
  1163.  
  1164.       // Assign events and toggle tooltip with focus
  1165.       assignEvents.call(self);
  1166.       if(self.options.show.ready === true) self.show();
  1167.  
  1168.       // Retrieve ajax content if provided
  1169.       if(self.options.content.url !== false)
  1170.       {
  1171.          url = self.options.content.url;
  1172.          data = self.options.content.data;
  1173.          method = self.options.content.method || 'get';
  1174.          self.loadContent(url, data, method);
  1175.       };
  1176.  
  1177.       // Call API method and log event
  1178.       self.onRender.call(self);
  1179.       $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_RENDERED, 'render');
  1180.    };
  1181.  
  1182.    // Create borders using canvas and VML
  1183.    function createBorder()
  1184.    {
  1185.       var self, i, width, radius, color, coordinates, containers, size, betweenWidth, betweenCorners, borderTop, borderBottom, borderCoord, sideWidth, vertWidth;
  1186.       self = this;
  1187.  
  1188.       // Destroy previous border elements, if present
  1189.       self.elements.wrapper.find('.qtip-borderBottom, .qtip-borderTop').remove();
  1190.  
  1191.       // Setup local variables
  1192.       width = self.options.style.border.width;
  1193.       radius = self.options.style.border.radius;
  1194.       color = self.options.style.border.color || self.options.style.tip.color;
  1195.  
  1196.       // Calculate border coordinates
  1197.       coordinates = calculateBorders(radius);
  1198.  
  1199.       // Create containers for the border shapes
  1200.       containers = {};
  1201.       for(i in coordinates)
  1202.       {
  1203.          // Create shape container
  1204.          containers[i] = '<div rel="'+i+'" style="'+((i.search(/Left/) !== -1) ? 'left' : 'right') + ':0; ' +
  1205.             'position:absolute; height:'+radius+'px; width:'+radius+'px; overflow:hidden; line-height:0.1px; font-size:1px">';
  1206.  
  1207.          // Canvas is supported
  1208.          if($('<canvas>').get(0).getContext)
  1209.             containers[i] += '<canvas height="'+radius+'" width="'+radius+'" style="vertical-align: top"></canvas>';
  1210.  
  1211.          // No canvas, but if it's IE use VML
  1212.          else if($.browser.msie)
  1213.          {
  1214.             size = radius * 2 + 3;
  1215.             containers[i] += '<v:arc stroked="false" fillcolor="'+color+'" startangle="'+coordinates[i][0]+'" endangle="'+coordinates[i][1]+'" ' +
  1216.                'style="width:'+size+'px; height:'+size+'px; margin-top:'+((i.search(/bottom/) !== -1) ? -2 : -1)+'px; ' +
  1217.                'margin-left:'+((i.search(/Right/) !== -1) ? coordinates[i][2] - 3.5 : -1)+'px; ' +
  1218.                'vertical-align:top; display:inline-block; behavior:url(#default#VML)"></v:arc>';
  1219.  
  1220.          };
  1221.  
  1222.          containers[i] += '</div>';
  1223.       };
  1224.  
  1225.       // Create between corners elements
  1226.       betweenWidth = self.getDimensions().width - (Math.max(width, radius) * 2);
  1227.       betweenCorners = '<div class="qtip-betweenCorners" style="height:'+radius+'px; width:'+betweenWidth+'px; ' +
  1228.          'overflow:hidden; background-color:'+color+'; line-height:0.1px; font-size:1px;">';
  1229.  
  1230.       // Create top border container
  1231.       borderTop = '<div class="qtip-borderTop" dir="ltr" style="height:'+radius+'px; ' +
  1232.          'margin-left:'+radius+'px; line-height:0.1px; font-size:1px; padding:0;">' +
  1233.          containers['topLeft'] + containers['topRight'] + betweenCorners;
  1234.       self.elements.wrapper.prepend(borderTop);
  1235.  
  1236.       // Create bottom border container
  1237.       borderBottom = '<div class="qtip-borderBottom" dir="ltr" style="height:'+radius+'px; ' +
  1238.          'margin-left:'+radius+'px; line-height:0.1px; font-size:1px; padding:0;">' +
  1239.          containers['bottomLeft'] + containers['bottomRight'] + betweenCorners;
  1240.       self.elements.wrapper.append(borderBottom);
  1241.  
  1242.       // Draw the borders if canvas were used (Delayed til after DOM creation)
  1243.       if($('<canvas>').get(0).getContext)
  1244.       {
  1245.          self.elements.wrapper.find('canvas').each(function()
  1246.          {
  1247.             borderCoord = coordinates[ $(this).parent('[rel]:first').attr('rel') ];
  1248.             drawBorder.call(self, $(this), borderCoord, radius, color);
  1249.          })
  1250.       }
  1251.  
  1252.       // Create a phantom VML element (IE won't show the last created VML element otherwise)
  1253.       else if($.browser.msie) self.elements.tooltip.append('<v:image style="behavior:url(#default#VML);"></v:image>');
  1254.  
  1255.       // Setup contentWrapper border
  1256.       sideWidth = Math.max(radius, (radius + (width - radius)) )
  1257.       vertWidth = Math.max(width - radius, 0);
  1258.       self.elements.contentWrapper.css({
  1259.          border: '0px solid ' + color,
  1260.          borderWidth: vertWidth + 'px ' + sideWidth + 'px'
  1261.       })
  1262.    };
  1263.  
  1264.    // Border canvas draw method
  1265.    function drawBorder(canvas, coordinates, radius, color)
  1266.    {
  1267.       // Create corner
  1268.       var context = canvas.get(0).getContext('2d');
  1269.       context.fillStyle = color;
  1270.       context.beginPath();
  1271.       context.arc(coordinates[0], coordinates[1], radius, 0, Math.PI * 2, false);
  1272.       context.fill();
  1273.    };
  1274.  
  1275.    // Create tip using canvas and VML
  1276.    function createTip(corner)
  1277.    {
  1278.       var self, color, coordinates, coordsize, path;
  1279.       self = this;
  1280.  
  1281.       // Destroy previous tip, if there is one
  1282.       if(self.elements.tip !== null) self.elements.tip.remove();
  1283.  
  1284.       // Setup color and corner values
  1285.       color = self.options.style.tip.color || self.options.style.border.color;
  1286.       if(self.options.style.tip.corner === false) return;
  1287.       else if(!corner) corner = self.options.style.tip.corner;
  1288.  
  1289.       // Calculate tip coordinates
  1290.       coordinates = calculateTip(corner, self.options.style.tip.size.width, self.options.style.tip.size.height);
  1291.  
  1292.       // Create tip element
  1293.       self.elements.tip =  '<div class="'+self.options.style.classes.tip+'" dir="ltr" rel="'+corner+'" style="position:absolute; ' +
  1294.          'height:'+self.options.style.tip.size.height+'px; width:'+self.options.style.tip.size.width+'px; ' +
  1295.          'margin:0 auto; line-height:0.1px; font-size:1px;">';
  1296.  
  1297.       // Use canvas element if supported
  1298.       if($('<canvas>').get(0).getContext)
  1299.           self.elements.tip += '<canvas height="'+self.options.style.tip.size.height+'" width="'+self.options.style.tip.size.width+'"></canvas>';
  1300.  
  1301.       // Canvas not supported - Use VML (IE)
  1302.       else if($.browser.msie)
  1303.       {
  1304.          // Create coordize and tip path using tip coordinates
  1305.          coordsize = self.options.style.tip.size.width + ',' + self.options.style.tip.size.height;
  1306.          path = 'm' + coordinates[0][0] + ',' + coordinates[0][1];
  1307.          path += ' l' + coordinates[1][0] + ',' + coordinates[1][1];
  1308.          path += ' ' + coordinates[2][0] + ',' + coordinates[2][1];
  1309.          path += ' xe';
  1310.  
  1311.          // Create VML element
  1312.          self.elements.tip += '<v:shape fillcolor="'+color+'" stroked="false" filled="true" path="'+path+'" coordsize="'+coordsize+'" ' +
  1313.             'style="width:'+self.options.style.tip.size.width+'px; height:'+self.options.style.tip.size.height+'px; ' +
  1314.             'line-height:0.1px; display:inline-block; behavior:url(#default#VML); ' +
  1315.             'vertical-align:'+((corner.search(/top/) !== -1) ? 'bottom' : 'top')+'"></v:shape>';
  1316.  
  1317.          // Create a phantom VML element (IE won't show the last created VML element otherwise)
  1318.          self.elements.tip += '<v:image style="behavior:url(#default#VML);"></v:image>';
  1319.  
  1320.          // Prevent tooltip appearing above the content (IE z-index bug)
  1321.          self.elements.contentWrapper.css('position', 'relative');
  1322.       };
  1323.  
  1324.       // Attach new tip to tooltip element
  1325.       self.elements.tooltip.prepend(self.elements.tip + '</div>');
  1326.  
  1327.       // Create element reference and draw the canvas tip (Delayed til after DOM creation)
  1328.       self.elements.tip = self.elements.tooltip.find('.'+self.options.style.classes.tip).eq(0);
  1329.       if($('<canvas>').get(0).getContext)
  1330.          drawTip.call(self, self.elements.tip.find('canvas:first'), coordinates, color);
  1331.  
  1332.       // Fix IE small tip bug
  1333.       if(corner.search(/top/) !== -1 && $.browser.msie && parseInt($.browser.version.charAt(0)) === 6)
  1334.          self.elements.tip.css({ marginTop: -4 });
  1335.  
  1336.       // Set the tip position
  1337.       positionTip.call(self, corner);
  1338.    };
  1339.  
  1340.    // Canvas tip drawing method
  1341.    function drawTip(canvas, coordinates, color)
  1342.    {
  1343.       // Setup properties
  1344.       var context = canvas.get(0).getContext('2d');
  1345.       context.fillStyle = color;
  1346.  
  1347.       // Create tip
  1348.       context.beginPath();
  1349.       context.moveTo(coordinates[0][0], coordinates[0][1]);
  1350.       context.lineTo(coordinates[1][0], coordinates[1][1]);
  1351.       context.lineTo(coordinates[2][0], coordinates[2][1]);
  1352.       context.fill();
  1353.    };
  1354.  
  1355.    function positionTip(corner)
  1356.    {
  1357.       var self, ieAdjust, paddingCorner, paddingSize, newMargin;
  1358.       self = this;
  1359.  
  1360.       // Return if tips are disabled or tip is not yet rendered
  1361.       if(self.options.style.tip.corner === false || !self.elements.tip) return;
  1362.       if(!corner) corner = self.elements.tip.attr('rel');
  1363.  
  1364.       // Setup adjustment variables
  1365.       ieAdjust = positionAdjust = ($.browser.msie) ? 1 : 0;
  1366.  
  1367.       // Set initial position
  1368.       self.elements.tip.css(corner.match(/left|right|top|bottom/)[0], 0);
  1369.  
  1370.       // Set position of tip to correct side
  1371.       if(corner.search(/top|bottom/) !== -1)
  1372.       {
  1373.          // Adjustments for IE6 - 0.5px border gap bug
  1374.          if($.browser.msie)
  1375.          {
  1376.             if(parseInt($.browser.version.charAt(0)) === 6)
  1377.                positionAdjust = (corner.search(/top/) !== -1) ? -3 : 1;
  1378.             else
  1379.                positionAdjust = (corner.search(/top/) !== -1) ? 1 : 2;
  1380.          };
  1381.  
  1382.          if(corner.search(/Middle/) !== -1)
  1383.             self.elements.tip.css({ left: '50%', marginLeft: -(self.options.style.tip.size.width / 2) });
  1384.  
  1385.          else if(corner.search(/Left/) !== -1)
  1386.             self.elements.tip.css({ left: self.options.style.border.radius - ieAdjust });
  1387.  
  1388.          else if(corner.search(/Right/) !== -1)
  1389.             self.elements.tip.css({ right: self.options.style.border.radius + ieAdjust });
  1390.  
  1391.          if(corner.search(/top/) !== -1)
  1392.             self.elements.tip.css({ top: -positionAdjust });
  1393.          else
  1394.             self.elements.tip.css({ bottom: positionAdjust });
  1395.  
  1396.       }
  1397.       else if(corner.search(/left|right/) !== -1)
  1398.       {
  1399.          // Adjustments for IE6 - 0.5px border gap bug
  1400.          if($.browser.msie)
  1401.             positionAdjust = (parseInt($.browser.version.charAt(0)) === 6) ? 1 : ((corner.search(/left/) !== -1) ? 1 : 2);
  1402.  
  1403.          if(corner.search(/Middle/) !== -1)
  1404.             self.elements.tip.css({ top: '50%', marginTop: -(self.options.style.tip.size.height / 2) });
  1405.  
  1406.          else if(corner.search(/Top/) !== -1)
  1407.             self.elements.tip.css({ top: self.options.style.border.radius - ieAdjust });
  1408.  
  1409.          else if(corner.search(/Bottom/) !== -1)
  1410.             self.elements.tip.css({ bottom: self.options.style.border.radius + ieAdjust });
  1411.  
  1412.          if(corner.search(/left/) !== -1)
  1413.             self.elements.tip.css({ left: -positionAdjust });
  1414.          else
  1415.             self.elements.tip.css({ right: positionAdjust });
  1416.       };
  1417.  
  1418.       // Adjust tooltip padding to compensate for tip
  1419.       paddingCorner = 'padding-' + corner.match(/left|right|top|bottom/)[0];
  1420.       paddingSize = self.options.style.tip.size[ (paddingCorner.search(/left|right/) !== -1) ? 'width' : 'height' ];
  1421.       self.elements.tooltip.css('padding', 0);
  1422.       self.elements.tooltip.css(paddingCorner, paddingSize);
  1423.  
  1424.       // Match content margin to prevent gap bug in IE6 ONLY
  1425.       if($.browser.msie && parseInt($.browser.version.charAt(0)) == 6)
  1426.       {
  1427.          newMargin = parseInt(self.elements.tip.css('margin-top')) || 0;
  1428.          newMargin += parseInt(self.elements.content.css('margin-top')) || 0;
  1429.  
  1430.          self.elements.tip.css({ marginTop: newMargin });
  1431.       };
  1432.    };
  1433.  
  1434.    // Create title bar for content
  1435.    function createTitle()
  1436.    {
  1437.       var self = this;
  1438.  
  1439.       // Destroy previous title element, if present
  1440.       if(self.elements.title !== null) self.elements.title.remove();
  1441.  
  1442.       // Create title element
  1443.       self.elements.title = $('<div class="'+self.options.style.classes.title+'">')
  1444.          .css( jQueryStyle(self.options.style.title, true) )
  1445.          .css({ zoom: ($.browser.msie) ? 1 : 0 })
  1446.          .prependTo(self.elements.contentWrapper);
  1447.  
  1448.       // Update title with contents if enabled
  1449.       if(self.options.content.title.text) self.updateTitle.call(self, self.options.content.title.text);
  1450.  
  1451.       // Create title close buttons if enabled
  1452.       if(self.options.content.title.button !== false
  1453.       && typeof self.options.content.title.button == 'string')
  1454.       {
  1455.          self.elements.button = $('<a class="'+self.options.style.classes.button+'" style="float:right; position: relative"></a>')
  1456.             .css( jQueryStyle(self.options.style.button, true) )
  1457.             .html(self.options.content.title.button)
  1458.             .prependTo(self.elements.title)
  1459.             .click(function(event){ if(!self.status.disabled) self.hide(event) });
  1460.       };
  1461.    };
  1462.  
  1463.    // Assign hide and show events
  1464.    function assignEvents()
  1465.    {
  1466.       var self, showTarget, hideTarget, inactiveEvents;
  1467.       self = this;
  1468.  
  1469.       // Setup event target variables
  1470.       showTarget = self.options.show.when.target;
  1471.       hideTarget = self.options.hide.when.target;
  1472.  
  1473.       // Add tooltip as a hideTarget is its fixed
  1474.       if(self.options.hide.fixed) hideTarget = hideTarget.add(self.elements.tooltip);
  1475.  
  1476.       // Check if the hide event is special 'inactive' type
  1477.       if(self.options.hide.when.event == 'inactive')
  1478.       {
  1479.          // Define events which reset the 'inactive' event handler
  1480.          inactiveEvents = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove',
  1481.          'mouseout', 'mouseenter', 'mouseleave', 'mouseover' ];
  1482.  
  1483.          // Define 'inactive' event timer method
  1484.          function inactiveMethod(event)
  1485.          {
  1486.             if(self.status.disabled === true) return;
  1487.  
  1488.             //Clear and reset the timer
  1489.             clearTimeout(self.timers.inactive);
  1490.             self.timers.inactive = setTimeout(function()
  1491.             {
  1492.                // Unassign 'inactive' events
  1493.                $(inactiveEvents).each(function()
  1494.                {
  1495.                   hideTarget.unbind(this+'.qtip-inactive');
  1496.                   self.elements.content.unbind(this+'.qtip-inactive');
  1497.                });
  1498.  
  1499.                // Hide the tooltip
  1500.                self.hide(event);
  1501.             }
  1502.             , self.options.hide.delay);
  1503.          };
  1504.       }
  1505.  
  1506.       // Check if the tooltip is 'fixed'
  1507.       else if(self.options.hide.fixed === true)
  1508.       {
  1509.          self.elements.tooltip.bind('mouseover.qtip', function()
  1510.          {
  1511.             if(self.status.disabled === true) return;
  1512.  
  1513.             // Reset the hide timer
  1514.             clearTimeout(self.timers.hide);
  1515.          });
  1516.       };
  1517.  
  1518.       // Define show event method
  1519.       function showMethod(event)
  1520.       {
  1521.          if(self.status.disabled === true) return;
  1522.  
  1523.          // If set, hide tooltip when inactive for delay period
  1524.          if(self.options.hide.when.event == 'inactive')
  1525.          {
  1526.             // Assign each reset event
  1527.             $(inactiveEvents).each(function()
  1528.             {
  1529.                hideTarget.bind(this+'.qtip-inactive', inactiveMethod);
  1530.                self.elements.content.bind(this+'.qtip-inactive', inactiveMethod);
  1531.             });
  1532.  
  1533.             // Start the inactive timer
  1534.             inactiveMethod();
  1535.          };
  1536.  
  1537.          // Clear hide timers
  1538.          clearTimeout(self.timers.show);
  1539.          clearTimeout(self.timers.hide);
  1540.  
  1541.          // Start show timer
  1542.          self.timers.show = setTimeout(function(){ self.show(event); }, self.options.show.delay);
  1543.       };
  1544.  
  1545.       // Define hide event method
  1546.       function hideMethod(event)
  1547.       {
  1548.          if(self.status.disabled === true) return;
  1549.  
  1550.          // Prevent hiding if tooltip is fixed and event target is the tooltip
  1551.          if(self.options.hide.fixed === true
  1552.          && self.options.hide.when.event.search(/mouse(out|leave)/i) !== -1
  1553.          && $(event.relatedTarget).parents('div.qtip[qtip]').length > 0)
  1554.          {
  1555.             // Prevent default and popagation
  1556.             event.stopPropagation();
  1557.             event.preventDefault();
  1558.  
  1559.             // Reset the hide timer
  1560.             clearTimeout(self.timers.hide);
  1561.             return false;
  1562.          };
  1563.  
  1564.          // Clear timers and stop animation queue
  1565.          clearTimeout(self.timers.show);
  1566.          clearTimeout(self.timers.hide);
  1567.          self.elements.tooltip.stop(true, true);
  1568.  
  1569.          // If tooltip has displayed, start hide timer
  1570.          self.timers.hide = setTimeout(function(){ self.hide(event); }, self.options.hide.delay);
  1571.       };
  1572.  
  1573.       // Both events and targets are identical, apply events using a toggle
  1574.       if((self.options.show.when.target.add(self.options.hide.when.target).length === 1
  1575.       && self.options.show.when.event == self.options.hide.when.event
  1576.       && self.options.hide.when.event !== 'inactive')
  1577.       || self.options.hide.when.event == 'unfocus')
  1578.       {
  1579.          self.cache.toggle = 0;
  1580.          // Use a toggle to prevent hide/show conflicts
  1581.          showTarget.bind(self.options.show.when.event + '.qtip', function(event)
  1582.          {
  1583.             if(self.cache.toggle == 0) showMethod(event);
  1584.             else hideMethod(event);
  1585.          });
  1586.       }
  1587.  
  1588.       // Events are not identical, bind normally
  1589.       else
  1590.       {
  1591.          showTarget.bind(self.options.show.when.event + '.qtip', showMethod);
  1592.  
  1593.          // If the hide event is not 'inactive', bind the hide method
  1594.          if(self.options.hide.when.event !== 'inactive')
  1595.             hideTarget.bind(self.options.hide.when.event + '.qtip', hideMethod);
  1596.       };
  1597.  
  1598.       // Focus the tooltip on mouseover
  1599.       if(self.options.position.type.search(/(fixed|absolute)/) !== -1)
  1600.          self.elements.tooltip.bind('mouseover.qtip', self.focus);
  1601.  
  1602.       // If mouse is the target, update tooltip position on mousemove
  1603.       if(self.options.position.target === 'mouse' && self.options.position.type !== 'static')
  1604.       {
  1605.          showTarget.bind('mousemove.qtip', function(event)
  1606.          {
  1607.             // Set the new mouse positions if adjustment is enabled
  1608.             self.cache.mouse = { x: event.pageX, y: event.pageY };
  1609.  
  1610.             // Update the tooltip position only if the tooltip is visible and adjustment is enabled
  1611.             if(self.status.disabled === false
  1612.             && self.options.position.adjust.mouse === true
  1613.             && self.options.position.type !== 'static'
  1614.             && self.elements.tooltip.css('display') !== 'none')
  1615.                self.updatePosition(event);
  1616.          });
  1617.       };
  1618.    };
  1619.  
  1620.    // Screen position adjustment
  1621.    function screenAdjust(position, target, tooltip)
  1622.    {
  1623.       var self, adjustedPosition, adjust, newCorner, overflow, corner;
  1624.       self = this;
  1625.  
  1626.       // Setup corner and adjustment variable
  1627.       if(tooltip.corner == 'center') return target.position // TODO: 'center' corner adjustment
  1628.       adjustedPosition = $.extend({}, position);
  1629.       newCorner = { x: false, y: false };
  1630.  
  1631.       // Define overflow properties
  1632.       overflow = {
  1633.          left: (adjustedPosition.left < $.fn.qtip.cache.screen.scroll.left),
  1634.          right: (adjustedPosition.left + tooltip.dimensions.width + 2 >= $.fn.qtip.cache.screen.width + $.fn.qtip.cache.screen.scroll.left),
  1635.          top: (adjustedPosition.top < $.fn.qtip.cache.screen.scroll.top),
  1636.          bottom: (adjustedPosition.top + tooltip.dimensions.height + 2 >= $.fn.qtip.cache.screen.height + $.fn.qtip.cache.screen.scroll.top)
  1637.       };
  1638.  
  1639.       // Determine new positioning properties
  1640.       adjust = {
  1641.          left: (overflow.left && (tooltip.corner.search(/right/i) != -1 || (tooltip.corner.search(/right/i) == -1 && !overflow.right))),
  1642.          right: (overflow.right && (tooltip.corner.search(/left/i) != -1 || (tooltip.corner.search(/left/i) == -1 && !overflow.left))),
  1643.          top: (overflow.top && tooltip.corner.search(/top/i) == -1),
  1644.          bottom: (overflow.bottom && tooltip.corner.search(/bottom/i) == -1)
  1645.       };
  1646.  
  1647.       // Tooltip overflows off the left side of the screen
  1648.       if(adjust.left)
  1649.       {
  1650.          if(self.options.position.target !== 'mouse')
  1651.             adjustedPosition.left = target.position.left + target.dimensions.width;
  1652.          else
  1653.             adjustedPosition.left = self.cache.mouse.x
  1654.  
  1655.          newCorner.x = 'Left';
  1656.       }
  1657.  
  1658.       // Tooltip overflows off the right side of the screen
  1659.       else if(adjust.right)
  1660.       {
  1661.          if(self.options.position.target !== 'mouse')
  1662.             adjustedPosition.left = target.position.left - tooltip.dimensions.width;
  1663.          else
  1664.             adjustedPosition.left = self.cache.mouse.x - tooltip.dimensions.width;
  1665.  
  1666.          newCorner.x = 'Right';
  1667.       };
  1668.  
  1669.       // Tooltip overflows off the top of the screen
  1670.       if(adjust.top)
  1671.       {
  1672.          if(self.options.position.target !== 'mouse')
  1673.             adjustedPosition.top = target.position.top + target.dimensions.height;
  1674.          else
  1675.             adjustedPosition.top = self.cache.mouse.y
  1676.  
  1677.          newCorner.y = 'top';
  1678.       }
  1679.  
  1680.       // Tooltip overflows off the bottom of the screen
  1681.       else if(adjust.bottom)
  1682.       {
  1683.          if(self.options.position.target !== 'mouse')
  1684.             adjustedPosition.top = target.position.top - tooltip.dimensions.height;
  1685.          else
  1686.             adjustedPosition.top = self.cache.mouse.y - tooltip.dimensions.height;
  1687.  
  1688.          newCorner.y = 'bottom';
  1689.       };
  1690.  
  1691.       // Don't adjust if resulting position is negative
  1692.       if(adjustedPosition.left < 0)
  1693.       {
  1694.          adjustedPosition.left = position.left;
  1695.          newCorner.x = false;
  1696.       };
  1697.       if(adjustedPosition.top < 0)
  1698.       {
  1699.          adjustedPosition.top = position.top;
  1700.          newCorner.y = false;
  1701.       };
  1702.  
  1703.       // Change tip corner if positioning has changed and tips are enabled
  1704.       if(self.options.style.tip.corner !== false)
  1705.       {
  1706.          // Determine new corner properties
  1707.          adjustedPosition.corner = new String(tooltip.corner);
  1708.          if(newCorner.x !== false) adjustedPosition.corner = adjustedPosition.corner.replace(/Left|Right|Middle/, newCorner.x);
  1709.          if(newCorner.y !== false) adjustedPosition.corner = adjustedPosition.corner.replace(/top|bottom/, newCorner.y);
  1710.  
  1711.          // Adjust tip if position has changed and tips are enabled
  1712.          if(adjustedPosition.corner !== self.elements.tip.attr('rel'))
  1713.             createTip.call(self, adjustedPosition.corner);
  1714.       };
  1715.  
  1716.       return adjustedPosition;
  1717.    };
  1718.  
  1719.    // Build a jQuery style object from supplied style object
  1720.    function jQueryStyle(style, sub)
  1721.    {
  1722.       var styleObj, i;
  1723.  
  1724.       styleObj = $.extend(true, {}, style);
  1725.       for(i in styleObj)
  1726.       {
  1727.          if(sub === true && i.search(/(tip|classes)/i) !== -1)
  1728.             delete styleObj[i];
  1729.          else if(!sub && i.search(/(width|border|tip|title|classes|user)/i) !== -1)
  1730.             delete styleObj[i];
  1731.       };
  1732.  
  1733.       return styleObj;
  1734.    };
  1735.  
  1736.    // Sanitize styles
  1737.    function sanitizeStyle(style)
  1738.    {
  1739.       if(typeof style.tip !== 'object') style.tip = { corner: style.tip };
  1740.       if(typeof style.tip.size !== 'object') style.tip.size = { width: style.tip.size, height: style.tip.size };
  1741.       if(typeof style.border !== 'object') style.border = { width: style.border };
  1742.       if(typeof style.width !== 'object') style.width = { value: style.width };
  1743.       if(typeof style.width.max == 'string') style.width.max = parseInt(style.width.max.replace(/([0-9]+)/i, "$1"));
  1744.       if(typeof style.width.min == 'string') style.width.min = parseInt(style.width.min.replace(/([0-9]+)/i, "$1"));
  1745.  
  1746.       // Convert deprecated x and y tip values to width/height
  1747.       if(typeof style.tip.size.x == 'number')
  1748.       {
  1749.          style.tip.size.width = style.tip.size.x;
  1750.          delete style.tip.size.x;
  1751.       };
  1752.       if(typeof style.tip.size.y == 'number')
  1753.       {
  1754.          style.tip.size.height = style.tip.size.y;
  1755.          delete style.tip.size.y;
  1756.       };
  1757.  
  1758.       return style;
  1759.    };
  1760.  
  1761.    // Build styles recursively with inheritance
  1762.    function buildStyle()
  1763.    {
  1764.       var self, i, styleArray, styleExtend, finalStyle, ieAdjust;
  1765.       self = this;
  1766.  
  1767.       // Build style options from supplied arguments
  1768.       styleArray = [true, {}];
  1769.       for(i = 0; i < arguments.length; i++)
  1770.          styleArray.push(arguments[i]);
  1771.       styleExtend = [ $.extend.apply($, styleArray) ];
  1772.  
  1773.       // Loop through each named style inheritance
  1774.       while(typeof styleExtend[0].name == 'string')
  1775.       {
  1776.          // Sanitize style data and append to extend array
  1777.          styleExtend.unshift( sanitizeStyle($.fn.qtip.styles[ styleExtend[0].name ]) );
  1778.       };
  1779.  
  1780.       // Make sure resulting tooltip className represents final style
  1781.       styleExtend.unshift(true, {classes:{ tooltip: 'qtip-' + (arguments[0].name || 'defaults') }}, $.fn.qtip.styles.defaults);
  1782.  
  1783.       // Extend into a single style object
  1784.       finalStyle = $.extend.apply($, styleExtend);
  1785.  
  1786.       // Adjust tip size if needed (IE 1px adjustment bug fix)
  1787.       ieAdjust = ($.browser.msie) ? 1 : 0;
  1788.       finalStyle.tip.size.width += ieAdjust;
  1789.       finalStyle.tip.size.height += ieAdjust;
  1790.  
  1791.       // Force even numbers for pixel precision
  1792.       if(finalStyle.tip.size.width % 2 > 0) finalStyle.tip.size.width += 1;
  1793.       if(finalStyle.tip.size.height % 2 > 0) finalStyle.tip.size.height += 1;
  1794.  
  1795.       // Sanitize final styles tip corner value
  1796.       if(finalStyle.tip.corner === true)
  1797.          finalStyle.tip.corner = (self.options.position.corner.tooltip === 'center') ? false : self.options.position.corner.tooltip;
  1798.  
  1799.       return finalStyle;
  1800.    };
  1801.  
  1802.    // Tip coordinates calculator
  1803.    function calculateTip(corner, width, height)
  1804.    {
  1805.       // Define tip coordinates in terms of height and width values
  1806.       var tips = {
  1807.          bottomRight:   [[0,0],              [width,height],      [width,0]],
  1808.          bottomLeft:    [[0,0],              [width,0],           [0,height]],
  1809.          topRight:      [[0,height],         [width,0],           [width,height]],
  1810.          topLeft:       [[0,0],              [0,height],          [width,height]],
  1811.          topMiddle:     [[0,height],         [width / 2,0],       [width,height]],
  1812.          bottomMiddle:  [[0,0],              [width,0],           [width / 2,height]],
  1813.          rightMiddle:   [[0,0],              [width,height / 2],  [0,height]],
  1814.          leftMiddle:    [[width,0],          [width,height],      [0,height / 2]]
  1815.       };
  1816.       tips.leftTop = tips.bottomRight;
  1817.       tips.rightTop = tips.bottomLeft;
  1818.       tips.leftBottom = tips.topRight;
  1819.       tips.rightBottom = tips.topLeft;
  1820.  
  1821.       return tips[corner];
  1822.    };
  1823.  
  1824.    // Border coordinates calculator
  1825.    function calculateBorders(radius)
  1826.    {
  1827.       var borders;
  1828.  
  1829.       // Use canvas element if supported
  1830.       if($('<canvas>').get(0).getContext)
  1831.       {
  1832.          borders = {
  1833.             topLeft: [radius,radius], topRight: [0,radius],
  1834.             bottomLeft: [radius,0], bottomRight: [0,0]
  1835.          };
  1836.       }
  1837.  
  1838.       // Canvas not supported - Use VML (IE)
  1839.       else if($.browser.msie)
  1840.       {
  1841.          borders = {
  1842.             topLeft: [-90,90,0], topRight: [-90,90,-radius],
  1843.             bottomLeft: [90,270,0], bottomRight: [90, 270,-radius]
  1844.          };
  1845.       };
  1846.  
  1847.       return borders;
  1848.    };
  1849.  
  1850.    // BGIFRAME JQUERY PLUGIN ADAPTION
  1851.    //   Special thanks to Brandon Aaron for this plugin
  1852.    //   http://plugins.jquery.com/project/bgiframe
  1853.    function bgiframe()
  1854.    {
  1855.       var self, html, dimensions;
  1856.       self = this;
  1857.       dimensions = self.getDimensions();
  1858.  
  1859.       // Setup iframe HTML string
  1860.       html = '<iframe class="qtip-bgiframe" frameborder="0" tabindex="-1" src="javascript:false" '+
  1861.          'style="display:block; position:absolute; z-index:-1; filter:alpha(opacity=\'0\'); border: 1px solid red; ' +
  1862.          'height:'+dimensions.height+'px; width:'+dimensions.width+'px" />';
  1863.  
  1864.       // Append the new HTML and setup element reference
  1865.       self.elements.bgiframe = self.elements.wrapper.prepend(html).children('.qtip-bgiframe:first');
  1866.    };
  1867.  
  1868.    // Assign cache and event initialisation on document load
  1869.    $(document).ready(function()
  1870.    {
  1871.       // Setup library cache with window scroll and dimensions of document
  1872.       $.fn.qtip.cache = {
  1873.          screen: {
  1874.             scroll: { left: $(window).scrollLeft(), top: $(window).scrollTop() },
  1875.             width: $(window).width(),
  1876.             height: $(window).height()
  1877.          }
  1878.       };
  1879.  
  1880.       // Adjust positions of the tooltips on window resize or scroll if enabled
  1881.       var adjustTimer;
  1882.       $(window).bind('resize scroll', function(event)
  1883.       {
  1884.          clearTimeout(adjustTimer);
  1885.          adjustTimer = setTimeout(function()
  1886.          {
  1887.             // Readjust cached screen values
  1888.             if(event.type === 'scroll')
  1889.                $.fn.qtip.cache.screen.scroll = { left: $(window).scrollLeft(), top: $(window).scrollTop() };
  1890.             else
  1891.             {
  1892.                $.fn.qtip.cache.screen.width = $(window).width();
  1893.                $.fn.qtip.cache.screen.height = $(window).height();
  1894.             };
  1895.  
  1896.             for(i = 0; i < $.fn.qtip.interfaces.length; i++)
  1897.             {
  1898.                // Access current elements API
  1899.                var api = $.fn.qtip.interfaces[i];
  1900.  
  1901.                // Update position if resize or scroll adjustments are enabled
  1902.                if(api !== undefined)
  1903.                {
  1904.                    if(api.status.rendered === true
  1905.                    && (api.options.position.type !== 'static'
  1906.                    || api.options.position.adjust.scroll && event.type === 'scroll'
  1907.                    || api.options.position.adjust.resize && event.type === 'resize'))
  1908.                    {
  1909.                       // Queue the animation so positions are updated correctly
  1910.                       api.updatePosition(event, true);
  1911.                    }
  1912.                }
  1913.             };
  1914.          }
  1915.          , 100);
  1916.       })
  1917.  
  1918.       // Hide unfocus toolipts on document mousedown
  1919.       $(document).bind('mousedown.qtip', function(event)
  1920.       {
  1921.          if($(event.target).parents('div.qtip').length === 0)
  1922.          {
  1923.             $('.qtip[unfocus]').each(function()
  1924.             {
  1925.                var api = $(this).qtip("api");
  1926.  
  1927.                // Only hide if its visible and not the tooltips target
  1928.                if($(this).is(':visible') && !api.status.disabled
  1929.                && $(event.target).add(api.elements.target).length > 1)
  1930.                   api.hide(event);
  1931.             })
  1932.          };
  1933.       })
  1934.    });
  1935.  
  1936.    // Define qTip API interfaces array
  1937.    $.fn.qtip.interfaces = []
  1938.  
  1939.    // Define log and constant place holders
  1940.    $.fn.qtip.log = { error: function(){ return this; } };
  1941.    $.fn.qtip.constants = {};
  1942.  
  1943.    // Define configuration defaults
  1944.    $.fn.qtip.defaults = {
  1945.       // Content
  1946.       content: {
  1947.          prerender: false,
  1948.          text: false,
  1949.          url: false,
  1950.          data: null,
  1951.          title: {
  1952.             text: false,
  1953.             button: false
  1954.          }
  1955.       },
  1956.       // Position
  1957.       position: {
  1958.          target: false,
  1959.          corner: {
  1960.             target: 'bottomRight',
  1961.             tooltip: 'topLeft'
  1962.          },
  1963.          adjust: {
  1964.             x: 0, y: 0,
  1965.             mouse: true,
  1966.             screen: false,
  1967.             scroll: true,
  1968.             resize: true
  1969.          },
  1970.          type: 'absolute',
  1971.          container: false
  1972.       },
  1973.       // Effects
  1974.       show: {
  1975.          when: {
  1976.             target: false,
  1977.             event: 'mouseover'
  1978.          },
  1979.          effect: {
  1980.             type: 'fade',
  1981.             length: 100
  1982.          },
  1983.          delay: 140,
  1984.          solo: false,
  1985.          ready: false
  1986.       },
  1987.       hide: {
  1988.          when: {
  1989.             target: false,
  1990.             event: 'mouseout'
  1991.          },
  1992.          effect: {
  1993.             type: 'fade',
  1994.             length: 100
  1995.          },
  1996.          delay: 0,
  1997.          fixed: false
  1998.       },
  1999.       // Callbacks
  2000.       api: {
  2001.          beforeRender: function(){},
  2002.          onRender: function(){},
  2003.          beforePositionUpdate: function(){},
  2004.          onPositionUpdate: function(){},
  2005.          beforeShow: function(){},
  2006.          onShow: function(){},
  2007.          beforeHide: function(){},
  2008.          onHide: function(){},
  2009.          beforeContentUpdate: function(){},
  2010.          onContentUpdate: function(){},
  2011.          beforeContentLoad: function(){},
  2012.          onContentLoad: function(){},
  2013.          beforeTitleUpdate: function(){},
  2014.          onTitleUpdate: function(){},
  2015.          beforeDestroy: function(){},
  2016.          onDestroy: function(){},
  2017.          beforeFocus: function(){},
  2018.          onFocus: function(){}
  2019.       }
  2020.    };
  2021.  
  2022.    $.fn.qtip.styles = {
  2023.       defaults: {
  2024.          background: 'white',
  2025.          color: '#111',
  2026.          overflow: 'hidden',
  2027.          textAlign: 'left',
  2028.          width: {
  2029.             min: 0,
  2030.             max: 250
  2031.          },
  2032.          padding: '5px 9px',
  2033.          border: {
  2034.             width: 1,
  2035.             radius: 0,
  2036.             color: '#d3d3d3'
  2037.          },
  2038.          tip: {
  2039.             corner: false,
  2040.             color: false,
  2041.             size: { width: 13, height: 13 },
  2042.             opacity: 1
  2043.          },
  2044.          title: {
  2045.             background: '#e1e1e1',
  2046.             fontWeight: 'bold',
  2047.             padding: '7px 12px'
  2048.          },
  2049.          button: {
  2050.             cursor: 'pointer'
  2051.          },
  2052.          classes: {
  2053.             target: '',
  2054.             tip: 'qtip-tip',
  2055.             title: 'qtip-title',
  2056.             button: 'qtip-button',
  2057.             content: 'qtip-content',
  2058.             active: 'qtip-active'
  2059.          }
  2060.       },
  2061.       cream: {
  2062.          border: {
  2063.             width: 3,
  2064.             radius: 0,
  2065.             color: '#F9E98E'
  2066.          },
  2067.          title: {
  2068.             background: '#F0DE7D',
  2069.             color: '#A27D35'
  2070.          },
  2071.          background: '#FBF7AA',
  2072.          color: '#A27D35',
  2073.  
  2074.          classes: { tooltip: 'qtip-cream' }
  2075.       },
  2076.       light: {
  2077.          border: {
  2078.             width: 3,
  2079.             radius: 0,
  2080.             color: '#E2E2E2'
  2081.          },
  2082.          title: {
  2083.             background: '#f1f1f1',
  2084.             color: '#454545'
  2085.          },
  2086.          background: 'white',
  2087.          color: '#454545',
  2088.  
  2089.          classes: { tooltip: 'qtip-light' }
  2090.       },
  2091.       dark: {
  2092.          border: {
  2093.             width: 3,
  2094.             radius: 0,
  2095.             color: '#303030'
  2096.          },
  2097.          title: {
  2098.             background: '#404040',
  2099.             color: '#f3f3f3'
  2100.          },
  2101.          background: '#505050',
  2102.          color: '#f3f3f3',
  2103.  
  2104.          classes: { tooltip: 'qtip-dark' }
  2105.       },
  2106.       red: {
  2107.          border: {
  2108.             width: 3,
  2109.             radius: 0,
  2110.             color: '#CE6F6F'
  2111.          },
  2112.          title: {
  2113.             background: '#f28279',
  2114.             color: '#9C2F2F'
  2115.          },
  2116.          background: '#F79992',
  2117.          color: '#9C2F2F',
  2118.  
  2119.          classes: { tooltip: 'qtip-red' }
  2120.       },
  2121.       green: {
  2122.          border: {
  2123.             width: 3,
  2124.             radius: 0,
  2125.             color: '#A9DB66'
  2126.          },
  2127.          title: {
  2128.             background: '#b9db8c',
  2129.             color: '#58792E'
  2130.          },
  2131.          background: '#CDE6AC',
  2132.          color: '#58792E',
  2133.  
  2134.          classes: { tooltip: 'qtip-green' }
  2135.       },
  2136.       blue: {
  2137.          border: {
  2138.             width: 3,
  2139.             radius: 0,
  2140.             color: '#ADD9ED'
  2141.          },
  2142.          title: {
  2143.             background: '#D0E9F5',
  2144.             color: '#5E99BD'
  2145.          },
  2146.          background: '#E5F6FE',
  2147.          color: '#4D9FBF',
  2148.  
  2149.          classes: { tooltip: 'qtip-blue' }
  2150.       }
  2151.    };
  2152. })(jQuery);
clone this paste RAW Paste Data