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.
@@ -0,0 +1,14 @@
1
+ /*
2
+ * qTip2 - Pretty powerful tooltips
3
+ * http://craigsworks.com/projects/qtip2/
4
+ *
5
+ * Version: 2.0.0pre
6
+ * Copyright 2009-2010 Craig Michael Thompson - http://craigsworks.com
7
+ *
8
+ * Dual licensed under MIT or GPLv2 licenses
9
+ * http://en.wikipedia.org/wiki/MIT_License
10
+ * http://en.wikipedia.org/wiki/GNU_General_Public_License
11
+ *
12
+ * Date: Thu Apr 26 20:40:09 2012 +0100
13
+ */
14
+
@@ -0,0 +1,143 @@
1
+ PLUGINS.imagemap = function(area, corner, flip)
2
+ {
3
+ if(!area.jquery) { area = $(area); }
4
+
5
+ var shape = (area[0].shape || area.attr('shape')).toLowerCase(),
6
+ baseCoords = (area[0].coords || area.attr('coords')).split(','),
7
+ coords = [],
8
+ image = $('img[usemap="#'+area.parent('map').attr('name')+'"]'),
9
+ imageOffset = image.offset(),
10
+ result = {
11
+ width: 0, height: 0,
12
+ offset: { top: 1e10, right: 0, bottom: 0, left: 1e10 }
13
+ },
14
+ i = 0, next = 0, dimensions;
15
+
16
+ // POLY area coordinate calculator
17
+ // Special thanks to Ed Cradock for helping out with this.
18
+ // Uses a binary search algorithm to find suitable coordinates.
19
+ function polyCoordinates(result, coords, corner)
20
+ {
21
+ var i = 0,
22
+ compareX = 1, compareY = 1,
23
+ realX = 0, realY = 0,
24
+ newWidth = result.width,
25
+ newHeight = result.height;
26
+
27
+ // Use a binary search algorithm to locate most suitable coordinate (hopefully)
28
+ while(newWidth > 0 && newHeight > 0 && compareX > 0 && compareY > 0)
29
+ {
30
+ newWidth = Math.floor(newWidth / 2);
31
+ newHeight = Math.floor(newHeight / 2);
32
+
33
+ if(corner.x === 'left'){ compareX = newWidth; }
34
+ else if(corner.x === 'right'){ compareX = result.width - newWidth; }
35
+ else{ compareX += Math.floor(newWidth / 2); }
36
+
37
+ if(corner.y === 'top'){ compareY = newHeight; }
38
+ else if(corner.y === 'bottom'){ compareY = result.height - newHeight; }
39
+ else{ compareY += Math.floor(newHeight / 2); }
40
+
41
+ i = coords.length; while(i--)
42
+ {
43
+ if(coords.length < 2){ break; }
44
+
45
+ realX = coords[i][0] - result.offset.left;
46
+ realY = coords[i][1] - result.offset.top;
47
+
48
+ if((corner.x === 'left' && realX >= compareX) ||
49
+ (corner.x === 'right' && realX <= compareX) ||
50
+ (corner.x === 'center' && (realX < compareX || realX > (result.width - compareX))) ||
51
+ (corner.y === 'top' && realY >= compareY) ||
52
+ (corner.y === 'bottom' && realY <= compareY) ||
53
+ (corner.y === 'center' && (realY < compareY || realY > (result.height - compareY)))) {
54
+ coords.splice(i, 1);
55
+ }
56
+ }
57
+ }
58
+
59
+ return { left: coords[0][0], top: coords[0][1] };
60
+ }
61
+
62
+ // Make sure we account for padding and borders on the image
63
+ imageOffset.left += Math.ceil((image.outerWidth() - image.width()) / 2);
64
+ imageOffset.top += Math.ceil((image.outerHeight() - image.height()) / 2);
65
+
66
+ // Parse coordinates into proper array
67
+ if(shape === 'poly') {
68
+ i = baseCoords.length; while(i--)
69
+ {
70
+ next = [ parseInt(baseCoords[--i], 10), parseInt(baseCoords[i+1], 10) ];
71
+
72
+ if(next[0] > result.offset.right){ result.offset.right = next[0]; }
73
+ if(next[0] < result.offset.left){ result.offset.left = next[0]; }
74
+ if(next[1] > result.offset.bottom){ result.offset.bottom = next[1]; }
75
+ if(next[1] < result.offset.top){ result.offset.top = next[1]; }
76
+
77
+ coords.push(next);
78
+ }
79
+ }
80
+ else {
81
+ coords = $.map(baseCoords, function(coord){ return parseInt(coord, 10); });
82
+ }
83
+
84
+ // Calculate details
85
+ switch(shape)
86
+ {
87
+ case 'rect':
88
+ result = {
89
+ width: Math.abs(coords[2] - coords[0]),
90
+ height: Math.abs(coords[3] - coords[1]),
91
+ offset: {
92
+ left: Math.min(coords[0], coords[2]),
93
+ top: Math.min(coords[1], coords[3])
94
+ }
95
+ };
96
+ break;
97
+
98
+ case 'circle':
99
+ result = {
100
+ width: coords[2] + 2,
101
+ height: coords[2] + 2,
102
+ offset: { left: coords[0], top: coords[1] }
103
+ };
104
+ break;
105
+
106
+ case 'poly':
107
+ $.extend(result, {
108
+ width: Math.abs(result.offset.right - result.offset.left),
109
+ height: Math.abs(result.offset.bottom - result.offset.top)
110
+ });
111
+
112
+ if(corner.string() === 'centercenter') {
113
+ result.offset = {
114
+ left: result.offset.left + (result.width / 2),
115
+ top: result.offset.top + (result.height / 2)
116
+ };
117
+ }
118
+ else {
119
+ result.offset = polyCoordinates(result, coords.slice(), corner);
120
+
121
+ // If flip adjustment is enabled, also calculate the closest opposite point
122
+ if(flip && (flip[0] === 'flip' || flip[1] === 'flip')) {
123
+ result.flipoffset = polyCoordinates(result, coords.slice(), {
124
+ x: corner.x === 'left' ? 'right' : corner.x === 'right' ? 'left' : 'center',
125
+ y: corner.y === 'top' ? 'bottom' : corner.y === 'bottom' ? 'top' : 'center'
126
+ });
127
+
128
+ result.flipoffset.left -= result.offset.left;
129
+ result.flipoffset.top -= result.offset.top;
130
+ }
131
+ }
132
+
133
+ result.width = result.height = 0;
134
+ break;
135
+ }
136
+
137
+ // Add image position to offset coordinates
138
+ result.offset.left += imageOffset.left;
139
+ result.offset.top += imageOffset.top;
140
+
141
+ return result;
142
+ };
143
+
@@ -0,0 +1,58 @@
1
+ /*jslint browser: true, onevar: true, undef: true, nomen: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: true */
2
+ /*global window: false, jQuery: false, console: false, define: false */
3
+
4
+ // Uses AMD or browser globals to create a jQuery plugin.
5
+ (function(factory) {
6
+ if(typeof define === 'function' && define.amd) {
7
+ define(['jquery'], factory);
8
+ }
9
+ else {
10
+ factory(jQuery);
11
+ }
12
+ }
13
+ (function($) {
14
+
15
+ "use strict"; // Enable ECMAScript "strict" operation for this function. See more: http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
16
+
17
+ // Munge the primitives - Paul Irish tip
18
+ var TRUE = true,
19
+ FALSE = false,
20
+ NULL = null,
21
+ undefined,
22
+
23
+ // Shortcut vars
24
+ QTIP, PLUGINS, MOUSE,
25
+ usedIDs = {},
26
+ uitooltip = 'ui-tooltip',
27
+ widget = 'ui-widget',
28
+ disabled = 'ui-state-disabled',
29
+ selector = 'div.qtip.'+uitooltip,
30
+ defaultClass = uitooltip + '-default',
31
+ focusClass = uitooltip + '-focus',
32
+ hoverClass = uitooltip + '-hover',
33
+ fluidClass = uitooltip + '-fluid',
34
+ hideOffset = '-31000px',
35
+ replaceSuffix = '_replacedByqTip',
36
+ oldtitle = 'oldtitle',
37
+ trackingBound;
38
+
39
+ /* Thanks to Paul Irish for this one: http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/ */
40
+ function log() {
41
+ log.history = log.history || [];
42
+ log.history.push(arguments);
43
+
44
+ // Make sure console is present
45
+ if('object' === typeof console) {
46
+
47
+ // Setup console and arguments
48
+ var c = console[ console.warn ? 'warn' : 'log' ],
49
+ args = Array.prototype.slice.call(arguments), a;
50
+
51
+ // Add qTip2 marker to first argument if it's a string
52
+ if(typeof arguments[0] === 'string') { args[0] = 'qTip2: ' + args[0]; }
53
+
54
+ // Apply console.warn or .log if not supported
55
+ a = c.apply ? c.apply(console, args) : c(args);
56
+ }
57
+ }
58
+
@@ -0,0 +1,286 @@
1
+ function Modal(api)
2
+ {
3
+ var self = this,
4
+ options = api.options.show.modal,
5
+ elems = api.elements,
6
+ tooltip = elems.tooltip,
7
+ overlaySelector = '#qtip-overlay',
8
+ globalNamespace = '.qtipmodal',
9
+ namespace = globalNamespace + api.id,
10
+ attr = 'is-modal-qtip',
11
+ docBody = $(document.body),
12
+ overlay;
13
+
14
+ // Setup option set checks
15
+ api.checks.modal = {
16
+ '^show.modal.(on|blur)$': function() {
17
+ // Initialise
18
+ self.init();
19
+
20
+ // Show the modal if not visible already and tooltip is visible
21
+ elems.overlay.toggle( tooltip.is(':visible') );
22
+ }
23
+ };
24
+
25
+ $.extend(self, {
26
+ init: function()
27
+ {
28
+ // If modal is disabled... return
29
+ if(!options.on) { return self; }
30
+
31
+ // Create the overlay if needed
32
+ overlay = self.create();
33
+
34
+ // Add unique attribute so we can grab modal tooltips easily via a selector
35
+ tooltip.attr(attr, TRUE)
36
+
37
+ // Set z-index
38
+ .css('z-index', PLUGINS.modal.zindex + $(selector+'['+attr+']').length)
39
+
40
+ // Remove previous bound events in globalNamespace
41
+ .unbind(globalNamespace).unbind(namespace)
42
+
43
+ // Apply our show/hide/focus modal events
44
+ .bind('tooltipshow'+globalNamespace+' tooltiphide'+globalNamespace, function(event, api, duration) {
45
+ var oEvent = event.originalEvent;
46
+
47
+ // Make sure mouseout doesn't trigger a hide when showing the modal and mousing onto backdrop
48
+ if(event.target === tooltip[0]) {
49
+ if(oEvent && event.type === 'tooltiphide' && /mouse(leave|enter)/.test(oEvent.type) && $(oEvent.relatedTarget).closest(overlay[0]).length) {
50
+ try { event.preventDefault(); } catch(e) {}
51
+ }
52
+ else if(!oEvent || (oEvent && !oEvent.solo)) {
53
+ self[ event.type.replace('tooltip', '') ](event, duration);
54
+ }
55
+ }
56
+ })
57
+
58
+ // Adjust modal z-index on tooltip focus
59
+ .bind('tooltipfocus'+globalNamespace, function(event) {
60
+ // If focus was cancelled before it reearch us, don't do anything
61
+ if(event.isDefaultPrevented() || event.target !== tooltip[0]) { return; }
62
+
63
+ var qtips = $(selector).filter('['+attr+']'),
64
+
65
+ // Keep the modal's lower than other, regular qtips
66
+ newIndex = PLUGINS.modal.zindex + qtips.length,
67
+ curIndex = parseInt(tooltip[0].style.zIndex, 10);
68
+
69
+ // Set overlay z-index
70
+ overlay[0].style.zIndex = newIndex - 1;
71
+
72
+ // Reduce modal z-index's and keep them properly ordered
73
+ qtips.each(function() {
74
+ if(this.style.zIndex > curIndex) {
75
+ this.style.zIndex -= 1;
76
+ }
77
+ });
78
+
79
+ // Fire blur event for focused tooltip
80
+ qtips.end().filter('.' + focusClass).qtip('blur', event.originalEvent);
81
+
82
+ // Set the new z-index
83
+ tooltip.addClass(focusClass)[0].style.zIndex = newIndex;
84
+
85
+ // Prevent default handling
86
+ try { event.preventDefault(); } catch(e) {}
87
+ })
88
+
89
+ // Focus any other visible modals when this one hides
90
+ .bind('tooltiphide'+globalNamespace, function(event) {
91
+ if(event.target === tooltip[0]) {
92
+ $('[' + attr + ']').filter(':visible').not(tooltip).last().qtip('focus', event);
93
+ }
94
+ });
95
+
96
+ // Apply keyboard "Escape key" close handler
97
+ if(options.escape) {
98
+ $(window).unbind(namespace).bind('keydown'+namespace, function(event) {
99
+ if(event.keyCode === 27 && tooltip.hasClass(focusClass)) {
100
+ api.hide(event);
101
+ }
102
+ });
103
+ }
104
+
105
+ // Apply click handler for blur option
106
+ if(options.blur) {
107
+ elems.overlay.unbind(namespace).bind('click'+namespace, function(event) {
108
+ if(tooltip.hasClass(focusClass)) { api.hide(event); }
109
+ });
110
+ }
111
+
112
+ return self;
113
+ },
114
+
115
+ create: function()
116
+ {
117
+ var elem = $(overlaySelector);
118
+
119
+ // Return if overlay is already rendered
120
+ if(elem.length) {
121
+ // Modal overlay should always be below all tooltips if possible
122
+ return (elems.overlay = elem.insertAfter( $(selector).last() ));
123
+ }
124
+
125
+ // Create document overlay
126
+ overlay = elems.overlay = $('<div />', {
127
+ id: overlaySelector.substr(1),
128
+ html: '<div></div>',
129
+ mousedown: function() { return FALSE; }
130
+ })
131
+ .insertAfter( $(selector).last() );
132
+
133
+ // Update position on window resize or scroll
134
+ function resize() {
135
+ overlay.css({
136
+ height: $(window).height(),
137
+ width: $(window).width()
138
+ });
139
+ }
140
+ $(window).unbind(globalNamespace).bind('resize'+globalNamespace, resize);
141
+ resize(); // Fire it initially too
142
+
143
+ return overlay;
144
+ },
145
+
146
+ toggle: function(event, state, duration)
147
+ {
148
+ // Make sure default event hasn't been prevented
149
+ if(event && event.isDefaultPrevented()) { return self; }
150
+
151
+ var effect = options.effect,
152
+ type = state ? 'show': 'hide',
153
+ visible = overlay.is(':visible'),
154
+ modals = $('[' + attr + ']').filter(':visible').not(tooltip),
155
+ zindex;
156
+
157
+ // Create our overlay if it isn't present already
158
+ if(!overlay) { overlay = self.create(); }
159
+
160
+ // Prevent modal from conflicting with show.solo, and don't hide backdrop is other modals are visible
161
+ if((overlay.is(':animated') && visible === state) || (!state && modals.length)) { return self; }
162
+
163
+ // State specific...
164
+ if(state) {
165
+ // Set position
166
+ overlay.css({ left: 0, top: 0 });
167
+
168
+ // Toggle backdrop cursor style on show
169
+ overlay.toggleClass('blurs', options.blur);
170
+
171
+ // Make sure we can't focus anything outside the tooltip
172
+ docBody.bind('focusin'+namespace, function(event) {
173
+ var target = $(event.target),
174
+ container = target.closest('.qtip'),
175
+
176
+ // Determine if input container target is above this
177
+ targetOnTop = container.length < 1 ? FALSE :
178
+ (parseInt(container[0].style.zIndex, 10) > parseInt(tooltip[0].style.zIndex, 10));
179
+
180
+ // If we're showing a modal, but focus has landed on an input below
181
+ // this modal, divert focus to the first visible input in this modal
182
+ if(!targetOnTop && ($(event.target).closest(selector)[0] !== tooltip[0])) {
183
+ tooltip.find('input:visible').filter(':first').focus();
184
+ }
185
+ });
186
+ }
187
+ else {
188
+ // Undelegate focus handler
189
+ docBody.undelegate('*', 'focusin'+namespace);
190
+ }
191
+
192
+ // Stop all animations
193
+ overlay.stop(TRUE, FALSE);
194
+
195
+ // Use custom function if provided
196
+ if($.isFunction(effect)) {
197
+ effect.call(overlay, state);
198
+ }
199
+
200
+ // If no effect type is supplied, use a simple toggle
201
+ else if(effect === FALSE) {
202
+ overlay[ type ]();
203
+ }
204
+
205
+ // Use basic fade function
206
+ else {
207
+ overlay.fadeTo( parseInt(duration, 10) || 90, state ? 1 : 0, function() {
208
+ if(!state) { $(this).hide(); }
209
+ });
210
+ }
211
+
212
+ // Reset position on hide
213
+ if(!state) {
214
+ overlay.queue(function(next) {
215
+ overlay.css({ left: '', top: '' });
216
+ next();
217
+ });
218
+ }
219
+
220
+ return self;
221
+ },
222
+
223
+ show: function(event, duration) { return self.toggle(event, TRUE, duration); },
224
+ hide: function(event, duration) { return self.toggle(event, FALSE, duration); },
225
+
226
+ destroy: function()
227
+ {
228
+ var delBlanket = overlay;
229
+
230
+ if(delBlanket) {
231
+ // Check if any other modal tooltips are present
232
+ delBlanket = $('[' + attr + ']').not(tooltip).length < 1;
233
+
234
+ // Remove overlay if needed
235
+ if(delBlanket) {
236
+ elems.overlay.remove();
237
+ $(window).unbind(globalNamespace);
238
+ }
239
+ else {
240
+ elems.overlay.unbind(globalNamespace+api.id);
241
+ }
242
+
243
+ // Undelegate focus handler
244
+ docBody.undelegate('*', 'focusin'+namespace);
245
+ }
246
+
247
+ // Remove bound events
248
+ return tooltip.removeAttr(attr).unbind(globalNamespace);
249
+ }
250
+ });
251
+
252
+ self.init();
253
+ }
254
+
255
+ PLUGINS.modal = function(api) {
256
+ var self = api.plugins.modal;
257
+
258
+ return 'object' === typeof self ? self : (api.plugins.modal = new Modal(api));
259
+ };
260
+
261
+ // Plugin needs to be initialized on render
262
+ PLUGINS.modal.initialize = 'render';
263
+
264
+ // Setup sanitiztion rules
265
+ PLUGINS.modal.sanitize = function(opts) {
266
+ if(opts.show) {
267
+ if(typeof opts.show.modal !== 'object') { opts.show.modal = { on: !!opts.show.modal }; }
268
+ else if(typeof opts.show.modal.on === 'undefined') { opts.show.modal.on = TRUE; }
269
+ }
270
+ };
271
+
272
+ // Base z-index for all modal tooltips (use qTip core z-index as a base)
273
+ PLUGINS.modal.zindex = QTIP.zindex + 1000;
274
+
275
+ // Extend original api defaults
276
+ $.extend(TRUE, QTIP.defaults, {
277
+ show: {
278
+ modal: {
279
+ on: FALSE,
280
+ effect: TRUE,
281
+ blur: TRUE,
282
+ escape: TRUE
283
+ }
284
+ }
285
+ });
286
+