PageSourceSearch

https://nagoya-cci.or.jp/js/jquery.balloon.js

js nagoya-cci.or.jp collected 2026-10-02 07:45:20 UTC 11,155 bytes, 279 lines download raw bytes

1
2/**
3 * Hover balloon on elements without css and images.
4 *
5 * Copyright (c) 2011 Hayato Takenaka
6 * Dual licensed under the MIT and GPL licenses:
7 * http://www.opensource.org/licenses/mit-license.php
8 * http://www.gnu.org/licenses/gpl.html
9 * @author: Hayato Takenaka (http://urin.take-uma.net)
10 * @version: 0.3.0 - 2012/02/25
11**/
12;(function($) {
13	//-----------------------------------------------------------------------------
14	// Private
15	//-----------------------------------------------------------------------------
16	// Helper for meta programming
17	var Meta = {};
18	Meta.pos  = $.extend(["top", "bottom", "left", "right"], {camel: ["Top", "Bottom", "Left", "Right"]});
19	Meta.size = $.extend(["height", "width"], {camel: ["Height", "Width"]});
20	Meta.getRelativeNames = function(position) {
21		var idx = {
22			pos: {
23				o: position,                                          // origin
24				f: (position % 2 == 0) ? position + 1 : position - 1, // faced
25				p1: (position % 2 == 0) ? position : position - 1,
26				p2: (position % 2 == 0) ? position + 1 : position,
27				c1: (position < 2) ? 2 : 0,
28				c2: (position < 2) ? 3 : 1
29			},
30			size: {
31				p: (position < 2) ? 0 : 1, // parallel
32				c: (position < 2) ? 1 : 0  // cross
33			}
34		};
35		var names = {};
36		for(var m1 in idx) {
37			if(!names[m1]) names[m1] = {};
38			for(var m2 in idx[m1]) {
39				names[m1][m2] = Meta[m1][idx[m1][m2]];
40				if(!names.camel) names.camel = {};
41				if(!names.camel[m1]) names.camel[m1] = {};
42				names.camel[m1][m2] = Meta[m1].camel[idx[m1][m2]];
43			}
44		}
45		names.isTopLeft = (names.pos.o == names.pos.p1);
46		return names;
47	};
48
49	// Helper class to handle position and size as numerical pixels.
50	function NumericalBoxElement() { this.initialize.apply(this, arguments); }
51	(function() {
52		// Method factories
53		var Methods = {
54			setBorder: function(pos, isVertical) {
55				return function(value) {
56					this.$.css("border-" + pos.toLowerCase() + "-width", value + "px");
57					this["border" + pos] = value;
58					return (this.isActive) ? digitalize(this, isVertical) : this;
59				}
60			},
61			setPosition: function(pos, isVertical) {
62				return function(value) {
63					this.$.css(pos.toLowerCase(), value + "px");
64					this[pos.toLowerCase()] = value;
65					return (this.isActive) ? digitalize(this, isVertical) : this;
66				}
67			}
68		};
69
70		NumericalBoxElement.prototype = {
71			initialize: function($element) {
72				this.$ = $element;
73				$.extend(true, this, this.$.offset(), {center: {}, inner: {center: {}}});
74				for(var i = 0; i < Meta.pos.length; i++) {
75					this["border" + Meta.pos.camel[i]] = parseInt(this.$.css("border-" + Meta.pos[i] + "-width")) || 0;
76				}
77				this.active();
78			},
79			active: function() { this.isActive = true; digitalize(this); return this; },
80			inactive: function() { this.isActive = false; return this; }
81		};
82		for(var i = 0; i < Meta.pos.length; i++) {
83			NumericalBoxElement.prototype["setBorder" + Meta.pos.camel[i]] = Methods.setBorder(Meta.pos.camel[i], (i < 2));
84			if(i % 2 == 0)
85				NumericalBoxElement.prototype["set" + Meta.pos.camel[i]] = Methods.setPosition(Meta.pos.camel[i], (i < 2));
86		}
87
88		function digitalize(box, isVertical) {
89			if(isVertical == undefined) { digitalize(box, true); return digitalize(box, false); }
90			var m = Meta.getRelativeNames((isVertical) ? 0 : 2);
91			box[m.size.p] = box.$["outer" + m.camel.size.p]();
92			box[m.pos.f] = box[m.pos.o] + box[m.size.p];
93			box.center[m.pos.o] = box[m.pos.o] + box[m.size.p] / 2;
94			box.inner[m.pos.o] = box[m.pos.o] + box["border" + m.camel.pos.o];
95			box.inner[m.size.p] = box.$["inner" + m.camel.size.p]();
96			box.inner[m.pos.f] = box.inner[m.pos.o] + box.inner[m.size.p];
97			box.inner.center[m.pos.o] = box.inner[m.pos.f] + box.inner[m.size.p] / 2;
98			return box;
99		}
100	})();
101
102	// Adjust position of balloon body
103	function makeupBalloon($target, $balloon, options) {
104		$balloon.stop(true, true);
105		var outerTip, innerTip,
106			initTipStyle = {position: "absolute", height: "0", width: "0", border: "solid 0 transparent"},
107			target = new NumericalBoxElement($target),
108			balloon = new NumericalBoxElement($balloon);
109		balloon.setTop(-options.offsetY
110			+ ((options.position && options.position.indexOf("top") >= 0) ? target.top - balloon.height
111			: ((options.position && options.position.indexOf("bottom") >= 0) ? target.bottom
112			: target.center.top - balloon.height / 2)));
113		balloon.setLeft(options.offsetX
114			+ ((options.position && options.position.indexOf("left") >= 0) ? target.left - balloon.width
115			: ((options.position && options.position.indexOf("right") >= 0) ? target.right
116			: target.center.left - balloon.width / 2)));
117		if(options.tipSize > 0) {
118			// Add hidden balloon tips into balloon body.
119			if($balloon.data("outerTip")) { $balloon.data("outerTip").remove(); $balloon.removeData("outerTip"); }
120			if($balloon.data("innerTip")) { $balloon.data("innerTip").remove(); $balloon.removeData("innerTip"); }
121			outerTip = new NumericalBoxElement($("<div>").css(initTipStyle).appendTo($balloon));
122			innerTip = new NumericalBoxElement($("<div>").css(initTipStyle).appendTo($balloon));
123			// Make tip triangle, adjust position of tips.
124			var m;
125			for(var i = 0; i < Meta.pos.length; i++) {
126				m = Meta.getRelativeNames(i);
127				if(balloon.center[m.pos.c1] >= target[m.pos.c1] &&
128					balloon.center[m.pos.c1] <= target[m.pos.c2]) {
129					if(i % 2 == 0) {
130						if(balloon[m.pos.o] >= target[m.pos.o] && balloon[m.pos.f] >= target[m.pos.f]) break;
131					} else {
132						if(balloon[m.pos.o] <= target[m.pos.o] && balloon[m.pos.f] <= target[m.pos.f]) break;
133					}
134				}
135				m = null;
136			}
137			if(m) {
138				balloon["set" + m.camel.pos.p1]
139					(balloon[m.pos.p1] + ((m.isTopLeft) ? 1 : -1) * (options.tipSize - balloon["border" + m.camel.pos.o]));
140				makeTip(balloon, outerTip, m, options.tipSize, $balloon.css("border-" + m.pos.o + "-color"));
141				makeTip(balloon, innerTip, m, options.tipSize - 2 * balloon["border" + m.camel.pos.o], $balloon.css("background-color"));
142				$balloon.data("outerTip", outerTip.$).data("innerTip", innerTip.$);
143			} else {
144				$.each([outerTip.$, innerTip.$], function() { this.remove(); });
145			}
146		}
147		// Make up balloon tip.
148		function makeTip(balloon, tip, m, tipSize, color) {
149			var len = Math.round(tipSize / 1.7320508);
150			tip.inactive()
151				["setBorder" + m.camel.pos.f](tipSize)
152				["setBorder" + m.camel.pos.c1](len)
153				["setBorder" + m.camel.pos.c2](len)
154				["set" + m.camel.pos.p1]((m.isTopLeft) ? -tipSize : balloon.inner[m.size.p])
155				["set" + m.camel.pos.c1](balloon.inner[m.size.c] / 2 - len)
156				.active()
157				.$.css("border-" + m.pos.f + "-color", color);
158		}
159	}
160
161	// True if the event comes from the target or balloon.
162	function isValidTargetEvent($target, e) {
163		var b = $target.data("balloon") && $target.data("balloon").get(0);
164		return !(b && (b == e.relatedTarget || $.contains(b, e.relatedTarget)));
165	}
166
167	//-----------------------------------------------------------------------------
168	// Public
169	//-----------------------------------------------------------------------------
170	$.fn.balloon = function(options) {
171		options = $.extend(true, {}, $.balloon.defaults, options);
172		return this.one("mouseenter", function(e) {
173			var $target = $(this), t = this;
174			var $balloon = $target.unbind("mouseenter", arguments.callee)
175				.showBalloon(options).mouseenter(function(e) {
176					isValidTargetEvent($target, e) && $target.showBalloon();
177				}).data("balloon");
178			if($balloon) {
179				$balloon.mouseleave(function(e) {
180					if(t == e.relatedTarget || $.contains(t, e.relatedTarget)) return;
181					$target.hideBalloon();
182				}).mouseenter(function(e) { $target.showBalloon(); });
183			}
184		}).mouseleave(function(e) {
185			var $target = $(this);
186			isValidTargetEvent($target, e) && $target.hideBalloon();
187		});
188	};
189
190	$.fn.showBalloon = function(options) {
191		var $target, $balloon, offTimer;
192		if(!$.balloon.defaults.css) $.balloon.defaults.css = {};
193		if(options || !this.data("options"))
194			this.data("options", $.extend(true, {}, $.balloon.defaults, options));
195		options = this.data("options");
196		return this.each(function() {
197			$target = $(this);
198			(offTimer = $target.data("offTimer")) && clearTimeout(offTimer);
199			var contents = $.isFunction(options.contents)
200				? options.contents()
201				: (options.contents || $target.attr("title"));
202			var isNew = !($balloon = $target.data("balloon"));
203			if(isNew) $balloon = $("<div>").append(contents);
204			if(!options.url && (!$balloon || $balloon.html() == "")) return;
205			if(!isNew && contents && contents != $balloon.html()) $balloon.empty().append(contents);
206			$target.removeAttr("title");
207			if(options.url) {
208				$balloon.load($.isFunction(options.url) ? options.url(this) : options.url, function(res, sts, xhr) {
209					if(options.ajaxComplete) options.ajaxComplete(res, sts, xhr);
210					makeupBalloon($target, $balloon, options);
211				});
212			}
213			if(isNew) {
214				$balloon
215					.addClass(options.classname)
216					.css(options.css)
217					.css({visibility: "hidden", position: "absolute"})
218					.appendTo("body");
219				$target.data("balloon", $balloon);
220				makeupBalloon($target, $balloon, options);
221				$balloon.hide().css("visibility", "visible");
222			} else {
223				makeupBalloon($target, $balloon, options);
224			}
225			$target.data("onTimer", setTimeout(function() {
226				if(options.showAnimation) {
227					options.showAnimation.apply($balloon.stop(true, true), [options.showDuration]);
228				} else {
229					$balloon.show(options.showDuration, function() {
230						if(this.style.removeAttribute) { this.style.removeAttribute("filter"); }
231					});
232				}
233			}, options.delay));
234		});
235	};
236
237	$.fn.hideBalloon = function() {
238		var options = this.data("options"), onTimer, offTimer;
239		return this.each(function() {
240			var $target = $(this);
241			(onTimer = $target.data("onTimer")) && clearTimeout(onTimer);
242			(offTimer = $target.data("offTimer")) && clearTimeout(offTimer);
243			$target.data("offTimer", setTimeout(function() {
244				var $balloon = $target.data("balloon");
245				if(options.hideAnimation) {
246					$balloon && options.hideAnimation.apply($balloon.stop(true, true), [options.hideDuration]);
247				} else {
248					$balloon && $balloon.stop(true, true).hide(options.hideDuration);
249				}
250			},
251			options.minLifetime));
252		});
253	};
254
255	$.balloon = {
256		defaults: {
257			contents: null, url: null, ajaxComplete: null, classname: null,
258			position: "top", offsetX: 0, offsetY: 0, tipSize: 12,
259			delay: 0, minLifetime: 200,
260			showDuration: 100, showAnimation: null,
261			hideDuration:  80, hideAnimation: function(d) { this.fadeOut(d); },
262			css: {
263				minWidth       : "20px",
264				padding        : "5px",
265				borderRadius   : "6px",
266				border         : "solid 1px #777",
267				boxShadow      : "4px 4px 4px #555",
268				color          : "#666",
269				backgroundColor: "#efefef",
270				opacity        : ($.support.opacity) ? "0.85" : null,
271				zIndex         : "32767",
272				textAlign      : "left"
273			}
274		}
275	};
276})(jQuery);
277
278
279

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.