jquery-qtip2-rails 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +13 -0
- data/jquery-qtip2-rails.gemspec +1 -0
- data/lib/jquery-qtip2-rails/version.rb +1 -1
- data/test/dummy/config/environments/production.rb +1 -1
- data/vendor/assets/jquery-qtip/jquery-qtip/src/ajax/ajax.js +10 -9
- data/vendor/assets/jquery-qtip/jquery-qtip/src/core.js +197 -144
- data/vendor/assets/jquery-qtip/jquery-qtip/src/ie6/ie6.js +8 -10
- data/vendor/assets/jquery-qtip/jquery-qtip/src/intro.js +9 -1
- data/vendor/assets/jquery-qtip/jquery-qtip/src/modal/modal.js +226 -195
- data/vendor/assets/jquery-qtip/jquery-qtip/src/tips/tips.css +9 -1
- data/vendor/assets/jquery-qtip/jquery-qtip/src/tips/tips.js +43 -23
- metadata +18 -2
data/README.md
CHANGED
@@ -98,6 +98,19 @@ $('.selector').qtip({
|
|
98
98
|
})
|
99
99
|
```
|
100
100
|
|
101
|
+
## Rails test/dummy
|
102
|
+
|
103
|
+
jquery-qtip2-rails comes with a dummy Rails application that you can run:
|
104
|
+
|
105
|
+
Development mode:
|
106
|
+
- `bundle`
|
107
|
+
- `cd test/dummy && rails s`
|
108
|
+
|
109
|
+
Production mode:
|
110
|
+
- `bundle`
|
111
|
+
- `cd test/dummy && rake assets:precompile`: generates .js and .css files inside test/dummy/public/assets/ + test/dummy/tmp/
|
112
|
+
- `cd test/dummy && rails s -e production`
|
113
|
+
|
101
114
|
## License
|
102
115
|
|
103
116
|
qTip2 is being developed by [Craig Thompson](http://craigsworks.com/) and is dual-licensed
|
data/jquery-qtip2-rails.gemspec
CHANGED
@@ -9,7 +9,7 @@ Dummy::Application.configure do
|
|
9
9
|
config.action_controller.perform_caching = true
|
10
10
|
|
11
11
|
# Disable Rails's static asset server (Apache or nginx will already do this)
|
12
|
-
config.serve_static_assets =
|
12
|
+
config.serve_static_assets = true
|
13
13
|
|
14
14
|
# Compress JavaScripts and CSS
|
15
15
|
config.assets.compress = true
|
@@ -1,11 +1,13 @@
|
|
1
|
+
var AJAX,
|
2
|
+
AJAXNS = '.qtip-ajax',
|
3
|
+
RSCRIPT = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi;
|
4
|
+
|
1
5
|
function Ajax(api)
|
2
6
|
{
|
3
7
|
var self = this,
|
4
8
|
tooltip = api.elements.tooltip,
|
5
9
|
opts = api.options.content.ajax,
|
6
10
|
defaults = QTIP.defaults.content.ajax,
|
7
|
-
namespace = '.qtip-ajax',
|
8
|
-
rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
|
9
11
|
first = TRUE,
|
10
12
|
stop = FALSE,
|
11
13
|
xhr;
|
@@ -22,7 +24,7 @@ function Ajax(api)
|
|
22
24
|
self.load();
|
23
25
|
}
|
24
26
|
else {
|
25
|
-
tooltip.unbind(
|
27
|
+
tooltip.unbind(AJAXNS);
|
26
28
|
}
|
27
29
|
}
|
28
30
|
};
|
@@ -31,7 +33,7 @@ function Ajax(api)
|
|
31
33
|
init: function() {
|
32
34
|
// Make sure ajax options are enabled and bind event
|
33
35
|
if(opts && opts.url) {
|
34
|
-
tooltip.unbind(
|
36
|
+
tooltip.unbind(AJAXNS)[ opts.once ? 'one' : 'bind' ]('tooltipshow'+AJAXNS, self.load);
|
35
37
|
}
|
36
38
|
|
37
39
|
return self;
|
@@ -92,7 +94,7 @@ function Ajax(api)
|
|
92
94
|
content = $('<div/>')
|
93
95
|
// inject the contents of the document in, removing the scripts
|
94
96
|
// to avoid any 'Permission Denied' errors in IE
|
95
|
-
.append(content.replace(
|
97
|
+
.append(content.replace(RSCRIPT, ""))
|
96
98
|
|
97
99
|
// Locate the specified elements
|
98
100
|
.find(selector);
|
@@ -135,18 +137,17 @@ function Ajax(api)
|
|
135
137
|
self.init();
|
136
138
|
}
|
137
139
|
|
138
|
-
|
139
|
-
PLUGINS.ajax = function(api)
|
140
|
+
AJAX = PLUGINS.ajax = function(api)
|
140
141
|
{
|
141
142
|
var self = api.plugins.ajax;
|
142
143
|
|
143
144
|
return 'object' === typeof self ? self : (api.plugins.ajax = new Ajax(api));
|
144
145
|
};
|
145
146
|
|
146
|
-
|
147
|
+
AJAX.initialize = 'render';
|
147
148
|
|
148
149
|
// Setup plugin sanitization
|
149
|
-
|
150
|
+
AJAX.sanitize = function(options)
|
150
151
|
{
|
151
152
|
var content = options.content, opts;
|
152
153
|
if(content && 'ajax' in content) {
|
@@ -35,7 +35,8 @@ function sanitizeOptions(opts)
|
|
35
35
|
}
|
36
36
|
|
37
37
|
if('show' in opts && invalid(opts.show)) {
|
38
|
-
opts.show = opts.show.jquery ? { target: opts.show } :
|
38
|
+
opts.show = opts.show.jquery ? { target: opts.show } :
|
39
|
+
opts.show === TRUE ? { ready: TRUE } : { event: opts.show };
|
39
40
|
}
|
40
41
|
|
41
42
|
if('hide' in opts && invalid(opts.hide)) {
|
@@ -286,67 +287,72 @@ function QTip(target, options, id, attr)
|
|
286
287
|
// Content is a regular string, insert the new content
|
287
288
|
else { elem.html(content); }
|
288
289
|
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
290
|
+
/*
|
291
|
+
* New images loaded detection method slimmed down from David DeSandro's plugin
|
292
|
+
* GitHub: https://github.com/desandro/imagesloaded/
|
293
|
+
*/
|
294
|
+
function imagesLoaded(next) {
|
295
|
+
var elem = $(this),
|
296
|
+
images = elem.find('img').add( elem.filter('img') ),
|
297
|
+
loaded = [];
|
298
|
+
|
299
|
+
function imgLoaded( img ) {
|
300
|
+
// don't proceed if BLANKIMG image, or image is already loaded
|
301
|
+
if(img.src === BLANKIMG || $.inArray(img, loaded) !== -1) { return; }
|
302
|
+
|
303
|
+
// store element in loaded images array
|
304
|
+
loaded.push(img);
|
305
|
+
|
306
|
+
// cache image and its state for future calls
|
307
|
+
$.data(img, 'imagesLoaded', { src: img.src });
|
308
|
+
|
309
|
+
// call doneLoading and clean listeners if all images are loaded
|
310
|
+
if(images.length === loaded.length) {
|
311
|
+
setTimeout(next);
|
312
|
+
images.unbind('.imagesLoaded');
|
308
313
|
}
|
309
314
|
}
|
310
315
|
|
311
|
-
//
|
312
|
-
if(
|
313
|
-
|
314
|
-
// Apply timer to each image to poll for dimensions
|
315
|
-
images.each(function(i, elem) {
|
316
|
-
// Skip if the src is already present
|
317
|
-
if(srcs[elem.src] !== undefined) { return; }
|
318
|
-
|
319
|
-
// Keep track of how many times we poll for image dimensions.
|
320
|
-
// If it doesn't return in a reasonable amount of time, it's better
|
321
|
-
// to display the tooltip, rather than hold up the queue.
|
322
|
-
var iterations = 0, maxIterations = 3;
|
323
|
-
|
324
|
-
(function timer(){
|
325
|
-
// When the dimensions are found, remove the image from the queue
|
326
|
-
if(elem.height || elem.width || (iterations > maxIterations)) { return imageLoad(elem); }
|
316
|
+
// No images? Proceed with next
|
317
|
+
if(!images.length) { return next(); }
|
327
318
|
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
319
|
+
images.bind('load.imagesLoaded error.imagesLoaded', function() {
|
320
|
+
imgLoaded(event.target);
|
321
|
+
})
|
322
|
+
.each(function(i, el) {
|
323
|
+
var src = el.src, cached = $.data(el, 'imagesLoaded');
|
324
|
+
|
325
|
+
/*
|
326
|
+
* Find out if this image has been already checked for status, and
|
327
|
+
* if it was and src has not changed, call imgLoaded on it. Also,
|
328
|
+
* if complete is true and browser supports natural sizes, try to
|
329
|
+
* check for image status manually
|
330
|
+
*/
|
331
|
+
if((cached && cached.src === src) || (el.complete && el.naturalWidth)) {
|
332
|
+
imgLoaded(el);
|
333
|
+
}
|
335
334
|
|
336
|
-
|
337
|
-
|
335
|
+
/*
|
336
|
+
* Cached images don't fire load sometimes, so we reset src, but only when
|
337
|
+
* dealing with IE, or image is complete (loaded) and failed manual check
|
338
|
+
*
|
339
|
+
* Webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
|
340
|
+
*/
|
341
|
+
else if(el.readyState || el.complete) {
|
342
|
+
el.src = BLANKIMG; el.src = src;
|
343
|
+
}
|
338
344
|
});
|
339
345
|
}
|
340
346
|
|
341
347
|
/*
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
if(self.rendered < 0) { tooltip.queue('fx',
|
348
|
+
* If we're still rendering... insert into 'fx' queue our image dimension
|
349
|
+
* checker which will halt the showing of the tooltip until image dimensions
|
350
|
+
* can be detected properly.
|
351
|
+
*/
|
352
|
+
if(self.rendered < 0) { tooltip.queue('fx', imagesLoaded); }
|
347
353
|
|
348
354
|
// We're fully rendered, so reset isDrawing flag and proceed without queue delay
|
349
|
-
else { isDrawing = 0;
|
355
|
+
else { isDrawing = 0; imagesLoaded.call(tooltip[0], $.noop); }
|
350
356
|
|
351
357
|
return self;
|
352
358
|
}
|
@@ -366,7 +372,7 @@ function QTip(target, options, id, attr)
|
|
366
372
|
show: $.trim('' + options.show.event).split(' '),
|
367
373
|
hide: $.trim('' + options.hide.event).split(' ')
|
368
374
|
},
|
369
|
-
IE6 =
|
375
|
+
IE6 = PLUGINS.ie === 6;
|
370
376
|
|
371
377
|
// Define show event method
|
372
378
|
function showMethod(event)
|
@@ -391,7 +397,7 @@ function QTip(target, options, id, attr)
|
|
391
397
|
if(tooltip.hasClass(disabledClass) || isPositioning || isDrawing) { return FALSE; }
|
392
398
|
|
393
399
|
// Check if new target was actually the tooltip element
|
394
|
-
var relatedTarget = $(event.relatedTarget
|
400
|
+
var relatedTarget = $(event.relatedTarget),
|
395
401
|
ontoTooltip = relatedTarget.closest(selector)[0] === tooltip[0],
|
396
402
|
ontoTarget = relatedTarget[0] === targets.show[0];
|
397
403
|
|
@@ -400,7 +406,11 @@ function QTip(target, options, id, attr)
|
|
400
406
|
clearTimeout(self.timers.hide);
|
401
407
|
|
402
408
|
// Prevent hiding if tooltip is fixed and event target is the tooltip. Or if mouse positioning is enabled and cursor momentarily overlaps
|
403
|
-
if(
|
409
|
+
if(this !== relatedTarget[0] &&
|
410
|
+
(posOptions.target === 'mouse' && ontoTooltip) ||
|
411
|
+
(options.hide.fixed && (
|
412
|
+
(/mouse(out|leave|move)/).test(event.type) && (ontoTooltip || ontoTarget))
|
413
|
+
)) {
|
404
414
|
try { event.preventDefault(); event.stopImmediatePropagation(); } catch(e) {} return;
|
405
415
|
}
|
406
416
|
|
@@ -440,8 +450,10 @@ function QTip(target, options, id, attr)
|
|
440
450
|
if(/mouse(out|leave)/i.test(options.hide.event)) {
|
441
451
|
// Hide tooltips when leaving current window/frame (but not select/option elements)
|
442
452
|
if(options.hide.leave === 'window') {
|
443
|
-
targets.
|
444
|
-
if(!/select|option/.test(event.target.nodeName) && !event.relatedTarget) {
|
453
|
+
targets.document.bind('mouseout'+namespace+' blur'+namespace, function(event) {
|
454
|
+
if(!/select|option/.test(event.target.nodeName) && !event.relatedTarget) {
|
455
|
+
self.hide(event);
|
456
|
+
}
|
445
457
|
});
|
446
458
|
}
|
447
459
|
}
|
@@ -458,9 +470,9 @@ function QTip(target, options, id, attr)
|
|
458
470
|
}
|
459
471
|
|
460
472
|
/*
|
461
|
-
|
462
|
-
|
463
|
-
|
473
|
+
* Make sure hoverIntent functions properly by using mouseleave to clear show timer if
|
474
|
+
* mouseenter/mouseout is used for show.event, even if it isn't in the users options.
|
475
|
+
*/
|
464
476
|
else if(/mouse(over|enter)/i.test(options.show.event)) {
|
465
477
|
targets.hide.bind('mouseleave'+namespace, function(event) {
|
466
478
|
clearTimeout(self.timers.show);
|
@@ -475,7 +487,7 @@ function QTip(target, options, id, attr)
|
|
475
487
|
isAncestor = elem.parents(selector).filter(tooltip[0]).length > 0;
|
476
488
|
|
477
489
|
if(elem[0] !== target[0] && elem[0] !== tooltip[0] && !isAncestor &&
|
478
|
-
!target.has(elem[0]).length &&
|
490
|
+
!target.has(elem[0]).length && enabled
|
479
491
|
) {
|
480
492
|
self.hide(event);
|
481
493
|
}
|
@@ -570,21 +582,23 @@ function QTip(target, options, id, attr)
|
|
570
582
|
}
|
571
583
|
|
572
584
|
// Adjust tooltip position on scroll of the window or viewport element if present
|
573
|
-
|
585
|
+
if(posOptions.adjust.scroll) {
|
586
|
+
targets.window.add(posOptions.container).bind('scroll'+namespace, repositionMethod);
|
587
|
+
}
|
574
588
|
}
|
575
589
|
|
576
590
|
function unassignEvents()
|
577
591
|
{
|
578
592
|
var targets = [
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
593
|
+
options.show.target[0],
|
594
|
+
options.hide.target[0],
|
595
|
+
self.rendered && elements.tooltip[0],
|
596
|
+
options.position.container[0],
|
597
|
+
options.position.viewport[0],
|
598
|
+
options.position.container.closest('html')[0], // unfocus
|
599
|
+
window,
|
600
|
+
document
|
601
|
+
];
|
588
602
|
|
589
603
|
// Check if tooltip is rendered
|
590
604
|
if(self.rendered) {
|
@@ -667,8 +681,8 @@ function QTip(target, options, id, attr)
|
|
667
681
|
|
668
682
|
$.extend(self, {
|
669
683
|
/*
|
670
|
-
|
671
|
-
|
684
|
+
* Psuedo-private API methods
|
685
|
+
*/
|
672
686
|
_triggerEvent: function(type, args, event)
|
673
687
|
{
|
674
688
|
var callback = $.Event('tooltip'+type);
|
@@ -679,8 +693,8 @@ function QTip(target, options, id, attr)
|
|
679
693
|
},
|
680
694
|
|
681
695
|
/*
|
682
|
-
|
683
|
-
|
696
|
+
* Public API methods
|
697
|
+
*/
|
684
698
|
render: function(show)
|
685
699
|
{
|
686
700
|
if(self.rendered) { return self; } // If tooltip has already been rendered, exit
|
@@ -757,10 +771,10 @@ function QTip(target, options, id, attr)
|
|
757
771
|
assignEvents();
|
758
772
|
|
759
773
|
/* Queue this part of the render process in our fx queue so we can
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
774
|
+
* load images before the tooltip renders fully.
|
775
|
+
*
|
776
|
+
* See: updateContent method
|
777
|
+
*/
|
764
778
|
tooltip.queue('fx', function(next) {
|
765
779
|
// tooltiprender event
|
766
780
|
self._triggerEvent('render');
|
@@ -852,9 +866,9 @@ function QTip(target, options, id, attr)
|
|
852
866
|
sanitizeOptions(options);
|
853
867
|
|
854
868
|
/*
|
855
|
-
|
856
|
-
|
857
|
-
|
869
|
+
* Execute any valid callbacks for the set options
|
870
|
+
* Also set isPositioning/isDrawing so we don't get loads of redundant repositioning calls.
|
871
|
+
*/
|
858
872
|
isPositioning = 1; $.each(option, callback); isPositioning = 0;
|
859
873
|
|
860
874
|
// Update position if needed
|
@@ -887,6 +901,7 @@ function QTip(target, options, id, attr)
|
|
887
901
|
otherOpts = options[ !state ? 'show' : 'hide' ],
|
888
902
|
posOptions = options.position,
|
889
903
|
contentOptions = options.content,
|
904
|
+
width = tooltip.css('width'),
|
890
905
|
visible = tooltip[0].offsetWidth > 0,
|
891
906
|
animate = state || opts.target.length === 1,
|
892
907
|
sameTarget = !event || opts.target.length < 2 || cache.target[0] === event.target,
|
@@ -922,8 +937,10 @@ function QTip(target, options, id, attr)
|
|
922
937
|
trackingBound = TRUE;
|
923
938
|
}
|
924
939
|
|
925
|
-
// Update the tooltip position
|
940
|
+
// Update the tooltip position (set width first to prevent viewport/max-width issues)
|
941
|
+
if(!width) { tooltip.css('width', tooltip.outerWidth()); }
|
926
942
|
self.reposition(event, arguments[2]);
|
943
|
+
if(!width) { tooltip.css('width', ''); }
|
927
944
|
|
928
945
|
// Hide other tooltips if tooltip is solo
|
929
946
|
if(!!opts.solo) {
|
@@ -952,7 +969,7 @@ function QTip(target, options, id, attr)
|
|
952
969
|
function after() {
|
953
970
|
if(state) {
|
954
971
|
// Prevent antialias from disappearing in IE by removing filter
|
955
|
-
if(
|
972
|
+
if(PLUGINS.ie) { tooltip[0].style.removeAttribute('filter'); }
|
956
973
|
|
957
974
|
// Remove overflow setting to prevent tip bugs
|
958
975
|
tooltip.css('overflow', '');
|
@@ -1206,7 +1223,7 @@ function QTip(target, options, id, attr)
|
|
1206
1223
|
tooltip.queue(function(next) {
|
1207
1224
|
// Reset attributes to avoid cross-browser rendering bugs
|
1208
1225
|
$(this).css({ opacity: '', height: '' });
|
1209
|
-
if(
|
1226
|
+
if(PLUGINS.ie) { this.style.removeAttribute('filter'); }
|
1210
1227
|
|
1211
1228
|
next();
|
1212
1229
|
});
|
@@ -1237,49 +1254,67 @@ function QTip(target, options, id, attr)
|
|
1237
1254
|
|
1238
1255
|
enable: function() { return self.disable(FALSE); },
|
1239
1256
|
|
1240
|
-
destroy: function()
|
1257
|
+
destroy: function(immediate)
|
1241
1258
|
{
|
1242
|
-
var t = target[0],
|
1243
|
-
title = $.attr(t, oldtitle),
|
1244
|
-
elemAPI = target.data('qtip');
|
1245
|
-
|
1246
1259
|
// Set flag the signify destroy is taking place to plugins
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1260
|
+
// and ensure it only gets destroyed once!
|
1261
|
+
if(self.destroyed) { return; }
|
1262
|
+
self.destroyed = !(self.rendered = FALSE);
|
1263
|
+
|
1264
|
+
function process() {
|
1265
|
+
var t = target[0],
|
1266
|
+
title = $.attr(t, oldtitle),
|
1267
|
+
elemAPI = target.data('qtip');
|
1268
|
+
|
1269
|
+
// Destroy tooltip and any associated plugins if rendered
|
1270
|
+
if(self.rendered) {
|
1271
|
+
// Destroy all plugins
|
1272
|
+
$.each(self.plugins, function(name) {
|
1273
|
+
if(this.destroy) { this.destroy(); }
|
1274
|
+
delete self.plugins[name];
|
1275
|
+
});
|
1257
1276
|
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
unassignEvents();
|
1277
|
+
// Remove all descendants and tooltip element
|
1278
|
+
tooltip.stop(1,0).find('*').remove().end().remove();
|
1279
|
+
}
|
1262
1280
|
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1281
|
+
// Clear timers and remove bound events
|
1282
|
+
clearTimeout(self.timers.show);
|
1283
|
+
clearTimeout(self.timers.hide);
|
1284
|
+
unassignEvents();
|
1285
|
+
|
1286
|
+
// If the API if actually this qTip API...
|
1287
|
+
if(!elemAPI || self === elemAPI) {
|
1288
|
+
// Remove api object
|
1289
|
+
target.removeData('qtip').removeAttr(HASATTR);
|
1290
|
+
|
1291
|
+
// Reset old title attribute if removed
|
1292
|
+
if(options.suppress && title) {
|
1293
|
+
target.attr('title', title);
|
1294
|
+
target.removeAttr(oldtitle);
|
1295
|
+
}
|
1267
1296
|
|
1268
|
-
|
1269
|
-
|
1270
|
-
$.attr(t, 'title', title);
|
1271
|
-
target.removeAttr(oldtitle);
|
1297
|
+
// Remove ARIA attributes
|
1298
|
+
target.removeAttr('aria-describedby');
|
1272
1299
|
}
|
1273
1300
|
|
1274
|
-
// Remove
|
1275
|
-
target.
|
1276
|
-
}
|
1301
|
+
// Remove qTip events associated with this API
|
1302
|
+
target.unbind('.qtip-'+id);
|
1277
1303
|
|
1278
|
-
|
1279
|
-
|
1304
|
+
// Remove ID from used id objects, and delete object references
|
1305
|
+
// for better garbage collection and leak protection
|
1306
|
+
delete usedIDs[self.id];
|
1307
|
+
delete self.options; delete self.elements;
|
1308
|
+
delete self.cache; delete self.timers;
|
1309
|
+
delete self.checks;
|
1310
|
+
}
|
1280
1311
|
|
1281
|
-
//
|
1282
|
-
|
1312
|
+
// Destroy after hide if no immediate
|
1313
|
+
if(immediate === TRUE) { process(); }
|
1314
|
+
else {
|
1315
|
+
tooltip.bind('tooltiphidden', process);
|
1316
|
+
self.hide();
|
1317
|
+
}
|
1283
1318
|
|
1284
1319
|
return target;
|
1285
1320
|
}
|
@@ -1287,16 +1322,15 @@ function QTip(target, options, id, attr)
|
|
1287
1322
|
}
|
1288
1323
|
|
1289
1324
|
// Initialization method
|
1290
|
-
function init(id, opts)
|
1325
|
+
function init(elem, id, opts)
|
1291
1326
|
{
|
1292
1327
|
var obj, posOptions, attr, config, title,
|
1293
1328
|
|
1294
1329
|
// Setup element references
|
1295
|
-
elem = $(this),
|
1296
1330
|
docBody = $(document.body),
|
1297
1331
|
|
1298
1332
|
// Use document body instead of document element if needed
|
1299
|
-
newTarget =
|
1333
|
+
newTarget = elem[0] === document ? docBody : elem,
|
1300
1334
|
|
1301
1335
|
// Grab metadata from element if plugin is present
|
1302
1336
|
metadata = (elem.metadata) ? elem.metadata(opts.metadata) : NULL,
|
@@ -1346,7 +1380,7 @@ function init(id, opts)
|
|
1346
1380
|
posOptions.my = new PLUGINS.Corner(posOptions.my);
|
1347
1381
|
|
1348
1382
|
// Destroy previous tooltip if overwrite is enabled, or skip element if not
|
1349
|
-
if(
|
1383
|
+
if(elem.data('qtip')) {
|
1350
1384
|
if(config.overwrite) {
|
1351
1385
|
elem.qtip('destroy');
|
1352
1386
|
}
|
@@ -1355,18 +1389,23 @@ function init(id, opts)
|
|
1355
1389
|
}
|
1356
1390
|
}
|
1357
1391
|
|
1392
|
+
// Add has-qtip attribute
|
1393
|
+
elem.attr(HASATTR, true);
|
1394
|
+
|
1358
1395
|
// Remove title attribute and store it if present
|
1359
|
-
if(config.suppress && (title =
|
1396
|
+
if(config.suppress && (title = elem.attr('title'))) {
|
1360
1397
|
// Final attr call fixes event delegatiom and IE default tooltip showing problem
|
1361
|
-
|
1398
|
+
elem.removeAttr('title').attr(oldtitle, title).attr('title', '');
|
1362
1399
|
}
|
1363
1400
|
|
1364
1401
|
// Initialize the tooltip and add API reference
|
1365
1402
|
obj = new QTip(elem, config, id, !!attr);
|
1366
|
-
|
1403
|
+
elem.data('qtip', obj);
|
1367
1404
|
|
1368
1405
|
// Catch remove/removeqtip events on target element to destroy redundant tooltip
|
1369
|
-
elem.
|
1406
|
+
elem.one('remove.qtip-'+id+' removeqtip.qtip-'+id, function() {
|
1407
|
+
var api; if((api = $(this).data('qtip'))) { api.destroy(); }
|
1408
|
+
});
|
1370
1409
|
|
1371
1410
|
return obj;
|
1372
1411
|
}
|
@@ -1440,7 +1479,7 @@ QTIP.bind = function(opts, event)
|
|
1440
1479
|
namespace = '.qtip-'+id+'-create';
|
1441
1480
|
|
1442
1481
|
// Initialize the qTip and re-grab newly sanitized options
|
1443
|
-
api = init
|
1482
|
+
api = init($(this), id, opts);
|
1444
1483
|
if(api === FALSE) { return TRUE; }
|
1445
1484
|
options = api.options;
|
1446
1485
|
|
@@ -1457,19 +1496,19 @@ QTIP.bind = function(opts, event)
|
|
1457
1496
|
};
|
1458
1497
|
|
1459
1498
|
/*
|
1460
|
-
|
1461
|
-
|
1462
|
-
|
1499
|
+
* Make sure hoverIntent functions properly by using mouseleave as a hide event if
|
1500
|
+
* mouseenter/mouseout is used for show.event, even if it isn't in the users options.
|
1501
|
+
*/
|
1463
1502
|
if(/mouse(over|enter)/i.test(events.show) && !/mouse(out|leave)/i.test(events.hide)) {
|
1464
1503
|
events.hide += ' mouseleave' + namespace;
|
1465
1504
|
}
|
1466
1505
|
|
1467
1506
|
/*
|
1468
|
-
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
1472
|
-
|
1507
|
+
* Also make sure initial mouse targetting works correctly by caching mousemove coords
|
1508
|
+
* on show targets before the tooltip has rendered.
|
1509
|
+
*
|
1510
|
+
* Also set onTarget when triggered to keep mouse tracking working
|
1511
|
+
*/
|
1473
1512
|
targets.show.bind('mousemove'+namespace, function(event) {
|
1474
1513
|
storeMouse(event);
|
1475
1514
|
api.cache.onTarget = TRUE;
|
@@ -1508,8 +1547,7 @@ QTIP.bind = function(opts, event)
|
|
1508
1547
|
|
1509
1548
|
// Prerendering is enabled, create tooltip now
|
1510
1549
|
if(options.show.ready || options.prerender) { hoverIntent(event); }
|
1511
|
-
})
|
1512
|
-
.attr('data-hasqtip', TRUE);
|
1550
|
+
});
|
1513
1551
|
};
|
1514
1552
|
|
1515
1553
|
// Setup base plugins
|
@@ -1544,7 +1582,7 @@ PLUGINS = QTIP.plugins = {
|
|
1544
1582
|
offset: function(elem, container) {
|
1545
1583
|
var pos = elem.offset(),
|
1546
1584
|
docBody = elem.closest('body'),
|
1547
|
-
quirks =
|
1585
|
+
quirks = PLUGINS.ie && document.compatMode !== 'CSS1Compat',
|
1548
1586
|
parent = container, scrolled,
|
1549
1587
|
coffset, overflow;
|
1550
1588
|
|
@@ -1579,16 +1617,30 @@ PLUGINS = QTIP.plugins = {
|
|
1579
1617
|
},
|
1580
1618
|
|
1581
1619
|
/*
|
1582
|
-
|
1583
|
-
|
1620
|
+
* IE version detection
|
1621
|
+
*
|
1622
|
+
* Adapted from: http://ajaxian.com/archives/attack-of-the-ie-conditional-comment
|
1623
|
+
* Credit to James Padolsey for the original implemntation!
|
1624
|
+
*/
|
1625
|
+
ie: (function(){
|
1626
|
+
var v = 3, div = document.createElement('div');
|
1627
|
+
while ((div.innerHTML = '<!--[if gt IE '+(++v)+']><i></i><![endif]-->')) {
|
1628
|
+
if(!div.getElementsByTagName('i')[0]) { break; }
|
1629
|
+
}
|
1630
|
+
return v > 4 ? v : FALSE;
|
1631
|
+
}()),
|
1632
|
+
|
1633
|
+
/*
|
1634
|
+
* iOS version detection
|
1635
|
+
*/
|
1584
1636
|
iOS: parseFloat(
|
1585
1637
|
('' + (/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0,''])[1])
|
1586
1638
|
.replace('undefined', '3_2').replace('_', '.').replace('_', '')
|
1587
1639
|
) || FALSE,
|
1588
1640
|
|
1589
1641
|
/*
|
1590
|
-
|
1591
|
-
|
1642
|
+
* jQuery-specific $.fn overrides
|
1643
|
+
*/
|
1592
1644
|
fn: {
|
1593
1645
|
/* Allow other plugins to successfully retrieve the title of an element with a qTip applied */
|
1594
1646
|
attr: function(attr, val) {
|
@@ -1652,8 +1704,8 @@ $.each(PLUGINS.fn, function(name, func) {
|
|
1652
1704
|
if(!$.ui) {
|
1653
1705
|
$['cleanData'+replaceSuffix] = $.cleanData;
|
1654
1706
|
$.cleanData = function( elems ) {
|
1655
|
-
for(var i = 0, elem; (elem = elems[i]) !== undefined; i++) {
|
1656
|
-
try { $( elem ).triggerHandler('removeqtip');
|
1707
|
+
for(var i = 0, elem; (elem = elems[i]) !== undefined && elem.getAttribute(HASATTR); i++) {
|
1708
|
+
try { $( elem ).triggerHandler('removeqtip');}
|
1657
1709
|
catch( e ) {}
|
1658
1710
|
}
|
1659
1711
|
$['cleanData'+replaceSuffix]( elems );
|
@@ -1690,6 +1742,7 @@ QTIP.defaults = {
|
|
1690
1742
|
adjust: {
|
1691
1743
|
x: 0, y: 0,
|
1692
1744
|
mouse: TRUE,
|
1745
|
+
scroll: TRUE,
|
1693
1746
|
resize: TRUE,
|
1694
1747
|
method: 'flipinvert flipinvert'
|
1695
1748
|
},
|