jquery-qtip2-rails 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
},
|