jquery-qtip2-rails 0.0.1
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/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +87 -0
- data/Rakefile +2 -0
- data/jquery-qtip2-rails.gemspec +19 -0
- data/lib/jquery-qtip2-rails.rb +10 -0
- data/lib/jquery-qtip2-rails/version.rb +7 -0
- data/vendor/assets/javascripts/jquery-qtip/ajax/ajax.js +167 -0
- data/vendor/assets/javascripts/jquery-qtip/bgiframe/bgiframe.js +76 -0
- data/vendor/assets/javascripts/jquery-qtip/core.js +1923 -0
- data/vendor/assets/javascripts/jquery-qtip/header.txt +14 -0
- data/vendor/assets/javascripts/jquery-qtip/imagemap/imagemap.js +143 -0
- data/vendor/assets/javascripts/jquery-qtip/intro.js +58 -0
- data/vendor/assets/javascripts/jquery-qtip/modal/modal.js +286 -0
- data/vendor/assets/javascripts/jquery-qtip/outro.js +2 -0
- data/vendor/assets/javascripts/jquery-qtip/svg/svg.js +43 -0
- data/vendor/assets/javascripts/jquery-qtip/tips/tips.js +610 -0
- data/vendor/assets/javascripts/jquery.qtip.basic.js +4 -0
- data/vendor/assets/javascripts/jquery.qtip.js +10 -0
- data/vendor/assets/stylesheets/jquery-qtip/core.css +123 -0
- data/vendor/assets/stylesheets/jquery-qtip/extra.css +424 -0
- data/vendor/assets/stylesheets/jquery-qtip/header.txt +14 -0
- data/vendor/assets/stylesheets/jquery-qtip/modal/modal.css +23 -0
- data/vendor/assets/stylesheets/jquery-qtip/styles.css +127 -0
- data/vendor/assets/stylesheets/jquery-qtip/tips/tips.css +22 -0
- data/vendor/assets/stylesheets/jquery.qtip.css +8 -0
- metadata +94 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
PLUGINS.svg = function(svg, corner)
|
2
|
+
{
|
3
|
+
var doc = $(document),
|
4
|
+
elem = svg[0],
|
5
|
+
result = {
|
6
|
+
width: 0, height: 0,
|
7
|
+
offset: { top: 1e10, left: 1e10 }
|
8
|
+
},
|
9
|
+
box, mtx, root, point, tPoint;
|
10
|
+
|
11
|
+
if (elem.getBBox && elem.parentNode) {
|
12
|
+
box = elem.getBBox();
|
13
|
+
mtx = elem.getScreenCTM();
|
14
|
+
root = elem.farthestViewportElement || elem;
|
15
|
+
|
16
|
+
// Return if no method is found
|
17
|
+
if(!root.createSVGPoint) { return result; }
|
18
|
+
|
19
|
+
// Create our point var
|
20
|
+
point = root.createSVGPoint();
|
21
|
+
|
22
|
+
// Adjust top and left
|
23
|
+
point.x = box.x;
|
24
|
+
point.y = box.y;
|
25
|
+
tPoint = point.matrixTransform(mtx);
|
26
|
+
result.offset.left = tPoint.x;
|
27
|
+
result.offset.top = tPoint.y;
|
28
|
+
|
29
|
+
// Adjust width and height
|
30
|
+
point.x += box.width;
|
31
|
+
point.y += box.height;
|
32
|
+
tPoint = point.matrixTransform(mtx);
|
33
|
+
result.width = tPoint.x - result.offset.left;
|
34
|
+
result.height = tPoint.y - result.offset.top;
|
35
|
+
|
36
|
+
// Adjust by scroll offset
|
37
|
+
result.offset.left += doc.scrollLeft();
|
38
|
+
result.offset.top += doc.scrollTop();
|
39
|
+
}
|
40
|
+
|
41
|
+
return result;
|
42
|
+
};
|
43
|
+
|
@@ -0,0 +1,610 @@
|
|
1
|
+
// Tip coordinates calculator
|
2
|
+
function calculateTip(corner, width, height)
|
3
|
+
{
|
4
|
+
var width2 = Math.ceil(width / 2), height2 = Math.ceil(height / 2),
|
5
|
+
|
6
|
+
// Define tip coordinates in terms of height and width values
|
7
|
+
tips = {
|
8
|
+
bottomright: [[0,0], [width,height], [width,0]],
|
9
|
+
bottomleft: [[0,0], [width,0], [0,height]],
|
10
|
+
topright: [[0,height], [width,0], [width,height]],
|
11
|
+
topleft: [[0,0], [0,height], [width,height]],
|
12
|
+
topcenter: [[0,height], [width2,0], [width,height]],
|
13
|
+
bottomcenter: [[0,0], [width,0], [width2,height]],
|
14
|
+
rightcenter: [[0,0], [width,height2], [0,height]],
|
15
|
+
leftcenter: [[width,0], [width,height], [0,height2]]
|
16
|
+
};
|
17
|
+
|
18
|
+
// Set common side shapes
|
19
|
+
tips.lefttop = tips.bottomright; tips.righttop = tips.bottomleft;
|
20
|
+
tips.leftbottom = tips.topright; tips.rightbottom = tips.topleft;
|
21
|
+
|
22
|
+
return tips[ corner.string() ];
|
23
|
+
}
|
24
|
+
|
25
|
+
|
26
|
+
function Tip(qTip, command)
|
27
|
+
{
|
28
|
+
var self = this,
|
29
|
+
opts = qTip.options.style.tip,
|
30
|
+
elems = qTip.elements,
|
31
|
+
tooltip = elems.tooltip,
|
32
|
+
cache = { top: 0, left: 0 },
|
33
|
+
size = {
|
34
|
+
width: opts.width,
|
35
|
+
height: opts.height
|
36
|
+
},
|
37
|
+
color = { },
|
38
|
+
border = opts.border || 0,
|
39
|
+
namespace = '.qtip-tip',
|
40
|
+
hasCanvas = !!($('<canvas />')[0] || {}).getContext;
|
41
|
+
|
42
|
+
self.corner = NULL;
|
43
|
+
self.mimic = NULL;
|
44
|
+
self.border = border;
|
45
|
+
self.offset = opts.offset;
|
46
|
+
self.size = size;
|
47
|
+
|
48
|
+
// Add new option checks for the plugin
|
49
|
+
qTip.checks.tip = {
|
50
|
+
'^position.my|style.tip.(corner|mimic|border)$': function() {
|
51
|
+
// Make sure a tip can be drawn
|
52
|
+
if(!self.init()) {
|
53
|
+
self.destroy();
|
54
|
+
}
|
55
|
+
|
56
|
+
// Reposition the tooltip
|
57
|
+
qTip.reposition();
|
58
|
+
},
|
59
|
+
'^style.tip.(height|width)$': function() {
|
60
|
+
// Re-set dimensions and redraw the tip
|
61
|
+
size = {
|
62
|
+
width: opts.width,
|
63
|
+
height: opts.height
|
64
|
+
};
|
65
|
+
self.create();
|
66
|
+
self.update();
|
67
|
+
|
68
|
+
// Reposition the tooltip
|
69
|
+
qTip.reposition();
|
70
|
+
},
|
71
|
+
'^content.title.text|style.(classes|widget)$': function() {
|
72
|
+
if(elems.tip && elems.tip.length) {
|
73
|
+
self.update();
|
74
|
+
}
|
75
|
+
}
|
76
|
+
};
|
77
|
+
|
78
|
+
function swapDimensions() {
|
79
|
+
var temp = size.width;
|
80
|
+
size.width = size.height;
|
81
|
+
size.height = temp;
|
82
|
+
}
|
83
|
+
|
84
|
+
function resetDimensions() {
|
85
|
+
size.width = opts.width;
|
86
|
+
size.height = opts.height;
|
87
|
+
}
|
88
|
+
|
89
|
+
function reposition(event, api, pos, viewport) {
|
90
|
+
if(!elems.tip) { return; }
|
91
|
+
|
92
|
+
var newCorner = self.corner.clone(),
|
93
|
+
adjust = pos.adjusted,
|
94
|
+
method = qTip.options.position.adjust.method.split(' '),
|
95
|
+
horizontal = method[0],
|
96
|
+
vertical = method[1] || method[0],
|
97
|
+
shift = { left: FALSE, top: FALSE, x: 0, y: 0 },
|
98
|
+
offset, css = {}, props;
|
99
|
+
|
100
|
+
// Make sure our tip position isn't fixed e.g. doesn't adjust with viewport
|
101
|
+
if(self.corner.fixed !== TRUE) {
|
102
|
+
// Horizontal - Shift or flip method
|
103
|
+
if(horizontal === 'shift' && newCorner.precedance === 'x' && adjust.left && newCorner.y !== 'center') {
|
104
|
+
newCorner.precedance = newCorner.precedance === 'x' ? 'y' : 'x';
|
105
|
+
}
|
106
|
+
else if(horizontal !== 'shift' && adjust.left){
|
107
|
+
newCorner.x = newCorner.x === 'center' ? (adjust.left > 0 ? 'left' : 'right') : (newCorner.x === 'left' ? 'right' : 'left');
|
108
|
+
}
|
109
|
+
|
110
|
+
// Vertical - Shift or flip method
|
111
|
+
if(vertical === 'shift' && newCorner.precedance === 'y' && adjust.top && newCorner.x !== 'center') {
|
112
|
+
newCorner.precedance = newCorner.precedance === 'y' ? 'x' : 'y';
|
113
|
+
}
|
114
|
+
else if(vertical !== 'shift' && adjust.top) {
|
115
|
+
newCorner.y = newCorner.y === 'center' ? (adjust.top > 0 ? 'top' : 'bottom') : (newCorner.y === 'top' ? 'bottom' : 'top');
|
116
|
+
}
|
117
|
+
|
118
|
+
// Update and redraw the tip if needed (check cached details of last drawn tip)
|
119
|
+
if(newCorner.string() !== cache.corner.string() && (cache.top !== adjust.top || cache.left !== adjust.left)) {
|
120
|
+
self.update(newCorner, FALSE);
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
// Setup tip offset properties
|
125
|
+
offset = self.position(newCorner, adjust);
|
126
|
+
if(offset.right !== undefined) { offset.left = -offset.right; }
|
127
|
+
if(offset.bottom !== undefined) { offset.top = -offset.bottom; }
|
128
|
+
offset.user = Math.max(0, opts.offset);
|
129
|
+
|
130
|
+
// Viewport "shift" specific adjustments
|
131
|
+
if(shift.left = (horizontal === 'shift' && !!adjust.left)) {
|
132
|
+
if(newCorner.x === 'center') {
|
133
|
+
css['margin-left'] = shift.x = offset['margin-left'] - adjust.left;
|
134
|
+
}
|
135
|
+
else {
|
136
|
+
props = offset.right !== undefined ?
|
137
|
+
[ adjust.left, -offset.left ] : [ -adjust.left, offset.left ];
|
138
|
+
|
139
|
+
if( (shift.x = Math.max(props[0], props[1])) > props[0] ) {
|
140
|
+
pos.left -= adjust.left;
|
141
|
+
shift.left = FALSE;
|
142
|
+
}
|
143
|
+
|
144
|
+
css[ offset.right !== undefined ? 'right' : 'left' ] = shift.x;
|
145
|
+
}
|
146
|
+
}
|
147
|
+
if(shift.top = (vertical === 'shift' && !!adjust.top)) {
|
148
|
+
if(newCorner.y === 'center') {
|
149
|
+
css['margin-top'] = shift.y = offset['margin-top'] - adjust.top;
|
150
|
+
}
|
151
|
+
else {
|
152
|
+
props = offset.bottom !== undefined ?
|
153
|
+
[ adjust.top, -offset.top ] : [ -adjust.top, offset.top ];
|
154
|
+
|
155
|
+
if( (shift.y = Math.max(props[0], props[1])) > props[0] ) {
|
156
|
+
pos.top -= adjust.top;
|
157
|
+
shift.top = FALSE;
|
158
|
+
}
|
159
|
+
|
160
|
+
css[ offset.bottom !== undefined ? 'bottom' : 'top' ] = shift.y;
|
161
|
+
}
|
162
|
+
}
|
163
|
+
|
164
|
+
/*
|
165
|
+
* If the tip is adjusted in both dimensions, or in a
|
166
|
+
* direction that would cause it to be anywhere but the
|
167
|
+
* outer border, hide it!
|
168
|
+
*/
|
169
|
+
elems.tip.css(css).toggle(
|
170
|
+
!((shift.x && shift.y) || (newCorner.x === 'center' && shift.y) || (newCorner.y === 'center' && shift.x))
|
171
|
+
);
|
172
|
+
|
173
|
+
// Adjust position to accomodate tip dimensions
|
174
|
+
pos.left -= offset.left.charAt ? offset.user : horizontal !== 'shift' || shift.top || !shift.left && !shift.top ? offset.left : 0;
|
175
|
+
pos.top -= offset.top.charAt ? offset.user : vertical !== 'shift' || shift.left || !shift.left && !shift.top ? offset.top : 0;
|
176
|
+
|
177
|
+
// Cache details
|
178
|
+
cache.left = adjust.left; cache.top = adjust.top;
|
179
|
+
cache.corner = newCorner.clone();
|
180
|
+
}
|
181
|
+
|
182
|
+
/* border width calculator */
|
183
|
+
function borderWidth(corner, side, backup) {
|
184
|
+
side = !side ? corner[corner.precedance] : side;
|
185
|
+
|
186
|
+
var isFluid = tooltip.hasClass(fluidClass),
|
187
|
+
isTitleTop = elems.titlebar && corner.y === 'top',
|
188
|
+
elem = isTitleTop ? elems.titlebar : elems.content,
|
189
|
+
css = 'border-' + side + '-width',
|
190
|
+
val;
|
191
|
+
|
192
|
+
// Grab the border-width value (add fluid class if needed)
|
193
|
+
tooltip.addClass(fluidClass);
|
194
|
+
val = parseInt(elem.css(css), 10);
|
195
|
+
val = (backup ? val || parseInt(tooltip.css(css), 10) : val) || 0;
|
196
|
+
tooltip.toggleClass(fluidClass, isFluid);
|
197
|
+
|
198
|
+
return val;
|
199
|
+
}
|
200
|
+
|
201
|
+
function borderRadius(corner) {
|
202
|
+
var isTitleTop = elems.titlebar && corner.y === 'top',
|
203
|
+
elem = isTitleTop ? elems.titlebar : elems.content,
|
204
|
+
moz = $.browser.mozilla,
|
205
|
+
prefix = moz ? '-moz-' : $.browser.webkit ? '-webkit-' : '',
|
206
|
+
side = corner.y + (moz ? '' : '-') + corner.x,
|
207
|
+
css = prefix + (moz ? 'border-radius-' + side : 'border-' + side + '-radius');
|
208
|
+
|
209
|
+
return parseInt(elem.css(css), 10) || parseInt(tooltip.css(css), 10) || 0;
|
210
|
+
}
|
211
|
+
|
212
|
+
function calculateSize(corner) {
|
213
|
+
var y = corner.precedance === 'y',
|
214
|
+
width = size [ y ? 'width' : 'height' ],
|
215
|
+
height = size [ y ? 'height' : 'width' ],
|
216
|
+
isCenter = corner.string().indexOf('center') > -1,
|
217
|
+
base = width * (isCenter ? 0.5 : 1),
|
218
|
+
pow = Math.pow,
|
219
|
+
round = Math.round,
|
220
|
+
bigHyp, ratio, result,
|
221
|
+
|
222
|
+
smallHyp = Math.sqrt( pow(base, 2) + pow(height, 2) ),
|
223
|
+
|
224
|
+
hyp = [
|
225
|
+
(border / base) * smallHyp, (border / height) * smallHyp
|
226
|
+
];
|
227
|
+
hyp[2] = Math.sqrt( pow(hyp[0], 2) - pow(border, 2) );
|
228
|
+
hyp[3] = Math.sqrt( pow(hyp[1], 2) - pow(border, 2) );
|
229
|
+
|
230
|
+
bigHyp = smallHyp + hyp[2] + hyp[3] + (isCenter ? 0 : hyp[0]);
|
231
|
+
ratio = bigHyp / smallHyp;
|
232
|
+
|
233
|
+
result = [ round(ratio * height), round(ratio * width) ];
|
234
|
+
return { height: result[ y ? 0 : 1 ], width: result[ y ? 1 : 0 ] };
|
235
|
+
}
|
236
|
+
|
237
|
+
$.extend(self, {
|
238
|
+
init: function()
|
239
|
+
{
|
240
|
+
var enabled = self.detectCorner() && (hasCanvas || $.browser.msie);
|
241
|
+
|
242
|
+
// Determine tip corner and type
|
243
|
+
if(enabled) {
|
244
|
+
// Create a new tip and draw it
|
245
|
+
self.create();
|
246
|
+
self.update();
|
247
|
+
|
248
|
+
// Bind update events
|
249
|
+
tooltip.unbind(namespace).bind('tooltipmove'+namespace, reposition);
|
250
|
+
}
|
251
|
+
|
252
|
+
return enabled;
|
253
|
+
},
|
254
|
+
|
255
|
+
detectCorner: function()
|
256
|
+
{
|
257
|
+
var corner = opts.corner,
|
258
|
+
posOptions = qTip.options.position,
|
259
|
+
at = posOptions.at,
|
260
|
+
my = posOptions.my.string ? posOptions.my.string() : posOptions.my;
|
261
|
+
|
262
|
+
// Detect corner and mimic properties
|
263
|
+
if(corner === FALSE || (my === FALSE && at === FALSE)) {
|
264
|
+
return FALSE;
|
265
|
+
}
|
266
|
+
else {
|
267
|
+
if(corner === TRUE) {
|
268
|
+
self.corner = new PLUGINS.Corner(my);
|
269
|
+
}
|
270
|
+
else if(!corner.string) {
|
271
|
+
self.corner = new PLUGINS.Corner(corner);
|
272
|
+
self.corner.fixed = TRUE;
|
273
|
+
}
|
274
|
+
}
|
275
|
+
|
276
|
+
// Cache it
|
277
|
+
cache.corner = new PLUGINS.Corner( self.corner.string() );
|
278
|
+
|
279
|
+
return self.corner.string() !== 'centercenter';
|
280
|
+
},
|
281
|
+
|
282
|
+
detectColours: function(actual) {
|
283
|
+
var i, fill, border,
|
284
|
+
tip = elems.tip.css('cssText', ''),
|
285
|
+
corner = actual || self.corner,
|
286
|
+
precedance = corner[ corner.precedance ],
|
287
|
+
|
288
|
+
borderSide = 'border-' + precedance + '-color',
|
289
|
+
borderSideCamel = 'border' + precedance.charAt(0) + precedance.substr(1) + 'Color',
|
290
|
+
|
291
|
+
invalid = /rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i,
|
292
|
+
backgroundColor = 'background-color',
|
293
|
+
transparent = 'transparent',
|
294
|
+
important = ' !important',
|
295
|
+
|
296
|
+
bodyBorder = $(document.body).css('color'),
|
297
|
+
contentColour = qTip.elements.content.css('color'),
|
298
|
+
|
299
|
+
useTitle = elems.titlebar && (corner.y === 'top' || (corner.y === 'center' && tip.position().top + (size.height / 2) + opts.offset < elems.titlebar.outerHeight(1))),
|
300
|
+
colorElem = useTitle ? elems.titlebar : elems.content;
|
301
|
+
|
302
|
+
// Apply the fluid class so we can see our CSS values properly
|
303
|
+
tooltip.addClass(fluidClass);
|
304
|
+
|
305
|
+
// Detect tip colours from CSS styles
|
306
|
+
color.fill = fill = tip.css(backgroundColor);
|
307
|
+
color.border = border = tip[0].style[ borderSideCamel ] || tip.css(borderSide) || tooltip.css(borderSide);
|
308
|
+
|
309
|
+
// Make sure colours are valid
|
310
|
+
if(!fill || invalid.test(fill)) {
|
311
|
+
color.fill = colorElem.css(backgroundColor) || transparent;
|
312
|
+
if(invalid.test(color.fill)) {
|
313
|
+
color.fill = tooltip.css(backgroundColor) || fill;
|
314
|
+
}
|
315
|
+
}
|
316
|
+
if(!border || invalid.test(border) || border === bodyBorder) {
|
317
|
+
color.border = colorElem.css(borderSide) || transparent;
|
318
|
+
if(invalid.test(color.border)) {
|
319
|
+
color.border = border;
|
320
|
+
}
|
321
|
+
}
|
322
|
+
|
323
|
+
// Reset background and border colours
|
324
|
+
$('*', tip).add(tip).css('cssText', backgroundColor+':'+transparent+important+';border:0'+important+';');
|
325
|
+
|
326
|
+
// Remove fluid class
|
327
|
+
tooltip.removeClass(fluidClass);
|
328
|
+
},
|
329
|
+
|
330
|
+
create: function()
|
331
|
+
{
|
332
|
+
var width = size.width,
|
333
|
+
height = size.height,
|
334
|
+
vml;
|
335
|
+
|
336
|
+
// Remove previous tip element if present
|
337
|
+
if(elems.tip) { elems.tip.remove(); }
|
338
|
+
|
339
|
+
// Create tip element and prepend to the tooltip
|
340
|
+
elems.tip = $('<div />', { 'class': 'ui-tooltip-tip' }).css({ width: width, height: height }).prependTo(tooltip);
|
341
|
+
|
342
|
+
// Create tip drawing element(s)
|
343
|
+
if(hasCanvas) {
|
344
|
+
// save() as soon as we create the canvas element so FF2 doesn't bork on our first restore()!
|
345
|
+
$('<canvas />').appendTo(elems.tip)[0].getContext('2d').save();
|
346
|
+
}
|
347
|
+
else {
|
348
|
+
vml = '<vml:shape coordorigin="0,0" style="display:inline-block; position:absolute; behavior:url(#default#VML);"></vml:shape>';
|
349
|
+
elems.tip.html(vml + vml);
|
350
|
+
|
351
|
+
// Prevent mousing down on the tip since it causes problems with .live() handling in IE due to VML
|
352
|
+
$('*', elems.tip).bind('click mousedown', function(event) { event.stopPropagation(); });
|
353
|
+
}
|
354
|
+
},
|
355
|
+
|
356
|
+
update: function(corner, position)
|
357
|
+
{
|
358
|
+
var tip = elems.tip,
|
359
|
+
inner = tip.children(),
|
360
|
+
width = size.width,
|
361
|
+
height = size.height,
|
362
|
+
regular = 'px solid ',
|
363
|
+
transparent = 'px dashed transparent', // Dashed IE6 border-transparency hack. Awesome!
|
364
|
+
mimic = opts.mimic,
|
365
|
+
round = Math.round,
|
366
|
+
precedance, context, coords, translate, newSize;
|
367
|
+
|
368
|
+
// Re-determine tip if not already set
|
369
|
+
if(!corner) { corner = cache.corner || self.corner; }
|
370
|
+
|
371
|
+
// Use corner property if we detect an invalid mimic value
|
372
|
+
if(mimic === FALSE) { mimic = corner; }
|
373
|
+
|
374
|
+
// Otherwise inherit mimic properties from the corner object as necessary
|
375
|
+
else {
|
376
|
+
mimic = new PLUGINS.Corner(mimic);
|
377
|
+
mimic.precedance = corner.precedance;
|
378
|
+
|
379
|
+
if(mimic.x === 'inherit') { mimic.x = corner.x; }
|
380
|
+
else if(mimic.y === 'inherit') { mimic.y = corner.y; }
|
381
|
+
else if(mimic.x === mimic.y) {
|
382
|
+
mimic[ corner.precedance ] = corner[ corner.precedance ];
|
383
|
+
}
|
384
|
+
}
|
385
|
+
precedance = mimic.precedance;
|
386
|
+
|
387
|
+
// Ensure the tip width.height are relative to the tip position
|
388
|
+
if(corner.precedance === 'x') { swapDimensions(); }
|
389
|
+
else { resetDimensions(); }
|
390
|
+
|
391
|
+
// Set the tip dimensions
|
392
|
+
elems.tip.css({
|
393
|
+
width: (width = size.width),
|
394
|
+
height: (height = size.height)
|
395
|
+
});
|
396
|
+
|
397
|
+
// Update our colours
|
398
|
+
self.detectColours(corner);
|
399
|
+
|
400
|
+
// Detect border width, taking into account colours
|
401
|
+
if(color.border !== 'transparent' && color.border !== '#123456') {
|
402
|
+
// Grab border width
|
403
|
+
border = borderWidth(corner, NULL, TRUE);
|
404
|
+
|
405
|
+
// If border width isn't zero, use border color as fill (1.0 style tips)
|
406
|
+
if(opts.border === 0 && border > 0) { color.fill = color.border; }
|
407
|
+
|
408
|
+
// Set border width (use detected border width if opts.border is true)
|
409
|
+
self.border = border = opts.border !== TRUE ? opts.border : border;
|
410
|
+
}
|
411
|
+
|
412
|
+
// Border colour was invalid, set border to zero
|
413
|
+
else { self.border = border = 0; }
|
414
|
+
|
415
|
+
// Calculate coordinates
|
416
|
+
coords = calculateTip(mimic, width , height);
|
417
|
+
|
418
|
+
// Determine tip size
|
419
|
+
self.size = newSize = calculateSize(corner);
|
420
|
+
tip.css(newSize);
|
421
|
+
|
422
|
+
// Calculate tip translation
|
423
|
+
if(corner.precedance === 'y') {
|
424
|
+
translate = [
|
425
|
+
round(mimic.x === 'left' ? border : mimic.x === 'right' ? newSize.width - width - border : (newSize.width - width) / 2),
|
426
|
+
round(mimic.y === 'top' ? newSize.height - height : 0)
|
427
|
+
];
|
428
|
+
}
|
429
|
+
else {
|
430
|
+
translate = [
|
431
|
+
round(mimic.x === 'left' ? newSize.width - width : 0),
|
432
|
+
round(mimic.y === 'top' ? border : mimic.y === 'bottom' ? newSize.height - height - border : (newSize.height - height) / 2)
|
433
|
+
];
|
434
|
+
}
|
435
|
+
|
436
|
+
// Canvas drawing implementation
|
437
|
+
if(hasCanvas) {
|
438
|
+
// Set the canvas size using calculated size
|
439
|
+
inner.attr(newSize);
|
440
|
+
|
441
|
+
// Grab canvas context and clear/save it
|
442
|
+
context = inner[0].getContext('2d');
|
443
|
+
context.restore(); context.save();
|
444
|
+
context.clearRect(0,0,3000,3000);
|
445
|
+
|
446
|
+
// Translate origin
|
447
|
+
context.translate(translate[0], translate[1]);
|
448
|
+
|
449
|
+
// Draw the tip
|
450
|
+
context.beginPath();
|
451
|
+
context.moveTo(coords[0][0], coords[0][1]);
|
452
|
+
context.lineTo(coords[1][0], coords[1][1]);
|
453
|
+
context.lineTo(coords[2][0], coords[2][1]);
|
454
|
+
context.closePath();
|
455
|
+
context.fillStyle = color.fill;
|
456
|
+
context.strokeStyle = color.border;
|
457
|
+
context.lineWidth = border * 2;
|
458
|
+
context.lineJoin = 'miter';
|
459
|
+
context.miterLimit = 100;
|
460
|
+
if(border) { context.stroke(); }
|
461
|
+
context.fill();
|
462
|
+
}
|
463
|
+
|
464
|
+
// VML (IE Proprietary implementation)
|
465
|
+
else {
|
466
|
+
// Setup coordinates string
|
467
|
+
coords = 'm' + coords[0][0] + ',' + coords[0][1] + ' l' + coords[1][0] +
|
468
|
+
',' + coords[1][1] + ' ' + coords[2][0] + ',' + coords[2][1] + ' xe';
|
469
|
+
|
470
|
+
// Setup VML-specific offset for pixel-perfection
|
471
|
+
translate[2] = border && /^(r|b)/i.test(corner.string()) ?
|
472
|
+
parseFloat($.browser.version, 10) === 8 ? 2 : 1 : 0;
|
473
|
+
|
474
|
+
// Set initial CSS
|
475
|
+
inner.css({
|
476
|
+
antialias: ''+(mimic.string().indexOf('center') > -1),
|
477
|
+
left: translate[0] - (translate[2] * Number(precedance === 'x')),
|
478
|
+
top: translate[1] - (translate[2] * Number(precedance === 'y')),
|
479
|
+
width: width + border,
|
480
|
+
height: height + border
|
481
|
+
})
|
482
|
+
.each(function(i) {
|
483
|
+
var $this = $(this);
|
484
|
+
|
485
|
+
// Set shape specific attributes
|
486
|
+
$this[ $this.prop ? 'prop' : 'attr' ]({
|
487
|
+
coordsize: (width+border) + ' ' + (height+border),
|
488
|
+
path: coords,
|
489
|
+
fillcolor: color.fill,
|
490
|
+
filled: !!i,
|
491
|
+
stroked: !!!i
|
492
|
+
})
|
493
|
+
.css({ display: border || i ? 'block' : 'none' });
|
494
|
+
|
495
|
+
// Check if border is enabled and add stroke element
|
496
|
+
if(!i && $this.html() === '') {
|
497
|
+
$this.html(
|
498
|
+
'<vml:stroke weight="'+(border*2)+'px" color="'+color.border+'" miterlimit="1000" joinstyle="miter" ' +
|
499
|
+
' style="behavior:url(#default#VML); display:inline-block;" />'
|
500
|
+
);
|
501
|
+
}
|
502
|
+
});
|
503
|
+
}
|
504
|
+
|
505
|
+
// Position if needed
|
506
|
+
if(position !== FALSE) { self.position(corner); }
|
507
|
+
},
|
508
|
+
|
509
|
+
// Tip positioning method
|
510
|
+
position: function(corner)
|
511
|
+
{
|
512
|
+
var tip = elems.tip,
|
513
|
+
position = {},
|
514
|
+
userOffset = Math.max(0, opts.offset),
|
515
|
+
precedance, dimensions, corners;
|
516
|
+
|
517
|
+
// Return if tips are disabled or tip is not yet rendered
|
518
|
+
if(opts.corner === FALSE || !tip) { return FALSE; }
|
519
|
+
|
520
|
+
// Inherit corner if not provided
|
521
|
+
corner = corner || self.corner;
|
522
|
+
precedance = corner.precedance;
|
523
|
+
|
524
|
+
// Determine which tip dimension to use for adjustment
|
525
|
+
dimensions = calculateSize(corner);
|
526
|
+
|
527
|
+
// Setup corners and offset array
|
528
|
+
corners = [ corner.x, corner.y ];
|
529
|
+
if(precedance === 'x') { corners.reverse(); }
|
530
|
+
|
531
|
+
// Calculate tip position
|
532
|
+
$.each(corners, function(i, side) {
|
533
|
+
var b, br;
|
534
|
+
|
535
|
+
if(side === 'center') {
|
536
|
+
b = precedance === 'y' ? 'left' : 'top';
|
537
|
+
position[ b ] = '50%';
|
538
|
+
position['margin-' + b] = -Math.round(dimensions[ precedance === 'y' ? 'width' : 'height' ] / 2) + userOffset;
|
539
|
+
}
|
540
|
+
else {
|
541
|
+
b = borderWidth(corner, side, TRUE);
|
542
|
+
br = borderRadius(corner);
|
543
|
+
|
544
|
+
position[ side ] = i ?
|
545
|
+
border ? borderWidth(corner, side) : 0 :
|
546
|
+
userOffset + (br > b ? br : 0);
|
547
|
+
}
|
548
|
+
});
|
549
|
+
|
550
|
+
// Adjust for tip dimensions
|
551
|
+
position[ corner[precedance] ] -= dimensions[ precedance === 'x' ? 'width' : 'height' ];
|
552
|
+
|
553
|
+
// Set and return new position
|
554
|
+
tip.css({ top: '', bottom: '', left: '', right: '', margin: '' }).css(position);
|
555
|
+
return position;
|
556
|
+
},
|
557
|
+
|
558
|
+
destroy: function()
|
559
|
+
{
|
560
|
+
// Remove the tip element
|
561
|
+
if(elems.tip) { elems.tip.remove(); }
|
562
|
+
elems.tip = false;
|
563
|
+
|
564
|
+
// Unbind events
|
565
|
+
tooltip.unbind(namespace);
|
566
|
+
}
|
567
|
+
});
|
568
|
+
|
569
|
+
self.init();
|
570
|
+
}
|
571
|
+
|
572
|
+
PLUGINS.tip = function(api)
|
573
|
+
{
|
574
|
+
var self = api.plugins.tip;
|
575
|
+
|
576
|
+
return 'object' === typeof self ? self : (api.plugins.tip = new Tip(api));
|
577
|
+
};
|
578
|
+
|
579
|
+
// Initialize tip on render
|
580
|
+
PLUGINS.tip.initialize = 'render';
|
581
|
+
|
582
|
+
// Setup plugin sanitization options
|
583
|
+
PLUGINS.tip.sanitize = function(options)
|
584
|
+
{
|
585
|
+
var style = options.style, opts;
|
586
|
+
if(style && 'tip' in style) {
|
587
|
+
opts = options.style.tip;
|
588
|
+
if(typeof opts !== 'object'){ options.style.tip = { corner: opts }; }
|
589
|
+
if(!(/string|boolean/i).test(typeof opts.corner)) { opts.corner = TRUE; }
|
590
|
+
if(typeof opts.width !== 'number'){ delete opts.width; }
|
591
|
+
if(typeof opts.height !== 'number'){ delete opts.height; }
|
592
|
+
if(typeof opts.border !== 'number' && opts.border !== TRUE){ delete opts.border; }
|
593
|
+
if(typeof opts.offset !== 'number'){ delete opts.offset; }
|
594
|
+
}
|
595
|
+
};
|
596
|
+
|
597
|
+
// Extend original qTip defaults
|
598
|
+
$.extend(TRUE, QTIP.defaults, {
|
599
|
+
style: {
|
600
|
+
tip: {
|
601
|
+
corner: TRUE,
|
602
|
+
mimic: FALSE,
|
603
|
+
width: 6,
|
604
|
+
height: 6,
|
605
|
+
border: TRUE,
|
606
|
+
offset: 0
|
607
|
+
}
|
608
|
+
}
|
609
|
+
});
|
610
|
+
|