PageSourceSearch

https://community.roedean.co.uk/assets/cache/roedean/6c383c65cdddcef975b17a157c643071.js

js roedean.co.uk collected 2026-10-02 10:27:47 UTC 13,246 bytes, 344 lines download raw bytes

1// tipsy, facebook style tooltips for jquery
2// version 1.0.0a
3// (c) 2008-2010 jason frame [[email protected]]
4// released under the MIT license
5
6(function($) {
7
8    function Tipsy(element, options) {
9        this.$element = $(element);
10        this.options = options;
11        this.enabled = true;
12        this.fixTitle();
13    }
14
15    Tipsy.prototype = {
16        show: function() {
17            var title = this.getTitle();
18            if (title && this.enabled) {
19                var $tip = this.tip();
20
21                $tip.find('.'+this.options.innerClassName)[this.options.html ? 'html' : 'text'](title);
22                $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
23                $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).appendTo(document.body);
24
25                var pos = $.extend({}, this.$element.offset, {
26                    width: this.$element[0].offsetWidth,
27                    height: this.$element[0].offsetHeight
28                });
29
30                var actualWidth = $tip[0].offsetWidth, actualHeight = $tip[0].offsetHeight;
31                var gravity = (typeof this.options.gravity == 'function')
32                                ? this.options.gravity.call(this.$element[0])
33                                : this.options.gravity;
34
35                var tp;
36                switch (gravity.charAt(0)) {
37                    case 'n':
38                        tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
39                        break;
40                    case 's':
41                        tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
42                        break;
43                    case 'e':
44                        tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
45                        break;
46                    case 'w':
47                        tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
48                        break;
49                }
50
51                if (gravity.length == 2) {
52                    if (gravity.charAt(1) == 'w') {
53                        tp.left = pos.left + pos.width / 2 - 15;
54                    } else {
55                        tp.left = pos.left + pos.width / 2 - actualWidth + 15;
56                    }
57                }
58
59                $tip.css(tp).addClass('tipsy-' + gravity);
60
61                if (this.options.fade) {
62                    $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity});
63                } else {
64                    $tip.css({visibility: 'visible', opacity: this.options.opacity});
65                }
66            }
67        },
68
69        hide: function() {
70            if (this.options.fade) {
71                this.tip().stop().fadeOut(function() { $(this).remove(); });
72            } else {
73                this.tip().remove();
74            }
75        },
76
77        fixTitle: function() {
78            var $e = this.$element;
79            if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') {
80                $e.attr('original-title', $e.attr('title') || '').removeAttr('title');
81            }
82        },
83
84        getTitle: function() {
85            var title, $e = this.$element, o = this.options;
86            this.fixTitle();
87            var title, o = this.options;
88            if (typeof o.title == 'string') {
89                title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
90            } else if (typeof o.title == 'function') {
91                title = o.title.call($e[0]);
92            }
93            title = ('' + title).replace(/(^\s*|\s*$)/, "");
94            return title || o.fallback;
95        },
96
97        tip: function() {
98            if (!this.$tip) {
99                this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="'+this.options.innerClassName+'"></div>');
100            }
101            return this.$tip;
102        },
103
104        validate: function() {
105            if (!this.$element[0].parentNode) {
106                this.hide();
107                this.$element = null;
108                this.options = null;
109            }
110        },
111
112        enable: function() { this.enabled = true; },
113        disable: function() { this.enabled = false; },
114        toggleEnabled: function() { this.enabled = !this.enabled; }
115    };
116
117    $.fn.tipsy = function(options) {
118
119        if (options === true) {
120            return this.data('tipsy');
121        } else if (typeof options == 'string') {
122            var tipsy = this.data('tipsy');
123            if (tipsy) tipsy[options]();
124            return this;
125        }
126
127        options = $.extend({}, $.fn.tipsy.defaults, options);
128
129        function get(ele) {
130            var tipsy = $.data(ele, 'tipsy');
131            if (!tipsy) {
132                tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
133                $.data(ele, 'tipsy', tipsy);
134            }
135            return tipsy;
136        }
137
138        function enter() {
139            var tipsy = get(this);
140            tipsy.hoverState = 'in';
141            if (options.delayIn == 0) {
142                tipsy.show();
143            } else {
144                tipsy.fixTitle();
145                setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
146            }
147        };
148
149        function leave() {
150            var tipsy = get(this);
151            tipsy.hoverState = 'out';
152            if (options.delayOut == 0) {
153                tipsy.hide();
154            } else {
155                setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
156            }
157        };
158
159        if (!options.live) this.each(function() { get(this); });
160
161        if (options.trigger != 'manual') {
162            var eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus',
163                eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
164            if (options.live)
165                $(document).on(eventIn, this.selector, enter).on(eventOut, this.selector, leave);
166            else
167                this.on(eventIn, enter).on(eventOut, leave);
168        }
169
170        return this;
171
172    };
173
174    $.fn.tipsy.defaults = {
175        delayIn: 0,
176        delayOut: 0,
177        fade: false,
178        fallback: '',
179        gravity: 'n',
180        html: false,
181        live: false,
182        offset: 0,
183        opacity: 0.8,
184        title: 'title',
185        trigger: 'hover',
186        innerClassName: 'tipsy-inner'
187    };
188
189    // Overwrite this method to provide options on a per-element basis.
190    // For example, you could store the gravity in a 'tipsy-gravity' attribute:
191    // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
192    // (remember - do not modify 'options' in place!)
193    $.fn.tipsy.elementOptions = function(ele, options) {
194        return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
195    };
196
197    $.fn.tipsy.autoNS = function() {
198        return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
199    };
200
201    $.fn.tipsy.autoWE = function() {
202        return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
203    };
204
205    /**
206     * yields a closure of the supplied parameters, producing a function that takes
207     * no arguments and is suitable for use as an autogravity function like so:
208     *
209     * @param margin (int) - distance from the viewable region edge that an
210     *        element should be before setting its tooltip's gravity to be away
211     *        from that edge.
212     * @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer
213     *        if there are no viewable region edges effecting the tooltip's
214     *        gravity. It will try to vary from this minimally, for example,
215     *        if 'sw' is preferred and an element is near the right viewable
216     *        region edge, but not the top edge, it will set the gravity for
217     *        that element's tooltip to be 'se', preserving the southern
218     *        component.
219     */
220     $.fn.tipsy.autoBounds = function(margin, prefer) {
221        return function() {
222            var dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)},
223                boundTop = $(document).scrollTop() + margin,
224                boundLeft = $(document).scrollLeft() + margin,
225                $this = $(this);
226
227            if ($this.offset().top < boundTop) dir.ns = 'n';
228            if ($this.offset().left < boundLeft) dir.ew = 'w';
229            if ($(window).width() + $(document).scrollLeft() - $this.offset().left < margin) dir.ew = 'e';
230            if ($(window).height() + $(document).scrollTop() - $this.offset().top < margin) dir.ns = 's';
231
232            return dir.ns + (dir.ew ? dir.ew : '');
233        }
234    };
235
236})(jQuery);
237
238/**
239* hoverIntent is similar to jQuery's built-in "hover" function except that
240* instead of firing the onMouseOver event immediately, hoverIntent checks
241* to see if the user's mouse has slowed down (beneath the sensitivity
242* threshold) before firing the onMouseOver event.
243* 
244* hoverIntent r6 // 2011.02.26 // jQuery 1.5.1+
245* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
246* 
247* hoverIntent is currently available for use in all personal or commercial 
248* projects under both MIT and GPL licenses. This means that you can choose 
249* the license that best suits your project, and use it accordingly.
250* 
251* // basic usage (just like .hover) receives onMouseOver and onMouseOut functions
252* $("ul li").hoverIntent( showNav , hideNav );
253* 
254* // advanced usage receives configuration object only
255* $("ul li").hoverIntent({
256*	sensitivity: 7, // number = sensitivity threshold (must be 1 or higher)
257*	interval: 100,   // number = milliseconds of polling interval
258*	over: showNav,  // function = onMouseOver callback (required)
259*	timeout: 0,   // number = milliseconds delay before onMouseOut function call
260*	out: hideNav    // function = onMouseOut callback (required)
261* });
262* 
263* @param  f  onMouseOver function || An object with configuration options
264* @param  g  onMouseOut function  || Nothing (use configuration options object)
265* @author    Brian Cherne brian(at)cherne(dot)net
266*/
267(function($) {
268	$.fn.hoverIntent = function(f,g) {
269		// default configuration options
270		var cfg = {
271			sensitivity: 7,
272			interval: 100,
273			timeout: 0
274		};
275		// override configuration options with user supplied object
276		cfg = $.extend(cfg, g ? { over: f, out: g } : f );
277
278		// instantiate variables
279		// cX, cY = current X and Y position of mouse, updated by mousemove event
280		// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
281		var cX, cY, pX, pY;
282
283		// A private function for getting mouse position
284		var track = function(ev) {
285			cX = ev.pageX;
286			cY = ev.pageY;
287		};
288
289		// A private function for comparing current and previous mouse position
290		var compare = function(ev,ob) {
291			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
292			// compare mouse positions to see if they've crossed the threshold
293			if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
294				$(ob).off("mousemove",track);
295				// set hoverIntent state to true (so mouseOut can be called)
296				ob.hoverIntent_s = 1;
297				return cfg.over.apply(ob,[ev]);
298			} else {
299				// set previous coordinates for next time
300				pX = cX; pY = cY;
301				// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
302				ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
303			}
304		};
305
306		// A private function for delaying the mouseOut function
307		var delay = function(ev,ob) {
308			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
309			ob.hoverIntent_s = 0;
310			return cfg.out.apply(ob,[ev]);
311		};
312
313		// A private function for handling mouse 'hovering'
314		var handleHover = function(e) {
315			// copy objects to be passed into t (required for event object to be passed in IE)
316			var ev = jQuery.extend({},e);
317			var ob = this;
318
319			// cancel hoverIntent timer if it exists
320			if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }
321
322			// if e.type == "mouseenter"
323			if (e.type == "mouseenter") {
324				// set "previous" X and Y position based on initial entry point
325				pX = ev.pageX; pY = ev.pageY;
326				// update "current" X and Y position based on mousemove
327				$(ob).on("mousemove", track);
328				// start polling interval (self-calling timeout) to compare mouse coordinates over time
329				if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}
330
331			// else e.type == "mouseleave"
332			} else {
333				// unbind expensive mousemove event
334				$(ob).off("mousemove", track);
335				// if hoverIntent state is true, then call the mouseOut function after the specified delay
336				if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
337			}
338		};
339
340		// bind the function to the two event listeners
341		return this.on('mouseenter', handleHover).on('mouseleave', handleHover);
342	};
343})(jQuery);
344

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.