vendor: 12,852 bytes, lines 1-315
1/** 2 * Hover balloon on elements without css and images. 3 * 4 * Copyright (c) 2011 Hayato Takenaka 5 * Dual licensed under the MIT and GPL licenses: 6 * http://www.opensource.org/licenses/mit-license.php 7 * http://www.gnu.org/licenses/gpl.html 8 * @author: Hayato Takenaka (http://urin.github.com) 9 * @version: 0.6.2 - 2015/04/30 10**/ 11(function($) { 12 "use strict"; 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 == null) { 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"), options.tipPosition); 141 makeTip(balloon, innerTip, m, options.tipSize - 2 * balloon["border" + m.camel.pos.o], $balloon.css("background-color"), options.tipPosition); 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] / options.tipPosition - 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 return this.one("mouseenter", function first(e) { 172 var $target = $(this), t = this; 173 var $balloon = $target.off("mouseenter", first) 174 .showBalloon(options).on("mouseenter", function(e) { 175 isValidTargetEvent($target, e) && $target.showBalloon(); 176 }).data("balloon"); 177 if($balloon) { 178 $balloon.on("mouseleave", function(e) { 179 if(t === e.relatedTarget || $.contains(t, e.relatedTarget)) return; 180 $target.hideBalloon(); 181 }).on("mouseenter", function(e) { 182 if(t === e.relatedTarget || $.contains(t, e.relatedTarget)) return; 183 $balloon.stop(true, true); 184 $target.showBalloon(); 185 }); 186 } 187 }).on("mouseleave", function(e) { 188 var $target = $(this); 189 isValidTargetEvent($target, e) && $target.hideBalloon(); 190 }); 191 }; 192 193 $.fn.showBalloon = function(options) { 194 var $target, $balloon; 195 if(options || !this.data("options")) { 196 if($.balloon.defaults.css === null) $.balloon.defaults.css = {}; 197 this.data("options", $.extend(true, {}, $.balloon.defaults, options || {})); 198 } 199 options = this.data("options"); 200 return this.each(function() { 201 var isNew, contents; 202 $target = $(this); 203 isNew = !$target.data("balloon"); 204 $balloon = $target.data("balloon") || $("<div>"); 205 if(!isNew && $balloon.data("active")) { return; } 206 $balloon.data("active", true); 207 clearTimeout($target.data("minLifetime")); 208 contents = $.isFunction(options.contents) 209 ? options.contents.apply(this) 210 : (options.contents || (options.contents = $target.attr("title") || $target.attr("alt"))); 211 $balloon.append(contents); 212 if(!options.url && $balloon.html() === "") { return; } 213 if(!isNew && contents !== $balloon.html()) $balloon.empty().append(contents); 214 $target.removeAttr("title"); 215 if(options.url) { 216 $balloon.load($.isFunction(options.url) ? options.url(this) : options.url, function(res, sts, xhr) { 217 if(options.ajaxComplete) options.ajaxComplete(res, sts, xhr); 218 makeupBalloon($target, $balloon, options); 219 }); 220 } 221 if(isNew) { 222 $balloon 223 .addClass(options.classname) 224 .css(options.css || {}) 225 .css({visibility: "hidden", position: "absolute"}) 226 .appendTo("body"); 227 $target.data("balloon", $balloon); 228 makeupBalloon($target, $balloon, options); 229 $balloon.hide().css("visibility", "visible"); 230 } else { 231 makeupBalloon($target, $balloon, options); 232 } 233 $target.data("delay", setTimeout(function() { 234 if(options.showAnimation) { 235 options.showAnimation.apply( 236 $balloon.stop(true, true), [ 237 options.showDuration, function() { 238 options.showComplete && options.showComplete.apply($balloon); 239 } 240 ] 241 ); 242 } else { 243 $balloon.show(options.showDuration, function() { 244 if(this.style.removeAttribute) { this.style.removeAttribute("filter"); } 245 options.showComplete && options.showComplete.apply($balloon); 246 }); 247 } 248 if(options.maxLifetime) { 249 clearTimeout($target.data("maxLifetime")); 250 $target.data("maxLifetime", 251 setTimeout(function() { $target.hideBalloon(); }, options.maxLifetime) 252 ); 253 } 254 }, options.delay)); 255 }); 256 }; 257 258 $.fn.hideBalloon = function() { 259 var options = this.data("options"); 260 if(!this.data("balloon")) return this; 261 return this.each(function() { 262 var $target = $(this); 263 clearTimeout($target.data("delay")); 264 clearTimeout($target.data("minLifetime")); 265 $target.data("minLifetime", setTimeout(function() { 266 var $balloon = $target.data("balloon"); 267 if(options.hideAnimation) { 268 options.hideAnimation.apply( 269 $balloon.stop(true, true), 270 [ 271 options.hideDuration, 272 function(d) { 273 $(this).data("active", false); 274 options.hideComplete && options.hideComplete(d); 275 } 276 ] 277 ); 278 } else { 279 $balloon.stop(true, true).hide( 280 options.hideDuration, 281 function(d) { 282 $(this).data("active", false); 283 options.hideComplete && options.hideComplete(d); 284 } 285 ); 286 } 287 }, 288 options.minLifetime)); 289 }); 290 }; 291 292 $.balloon = { 293 defaults: { 294 contents: null, url: null, ajaxComplete: null, classname: null, 295 position: "top", offsetX: 0, offsetY: 0, tipSize: 12, tipPosition: 2, 296 delay: 0, minLifetime: 200, maxLifetime: 0, 297 showDuration: 100, showAnimation: null, 298 hideDuration: 80, hideAnimation: function(d, c) { this.fadeOut(d, c); }, 299 showComplete: null, hideComplete: null, 300 css: { 301 minWidth : "20px", 302 padding : "8px", 303 borderRadius : "6px", 304 border : "2px solid #666", 305 boxShadow : "4px 4px 4px #555", 306 color : "#000", 307 backgroundColor: "#CCFF99", 308 opacity : "0.75", 309 zIndex : "32767", 310 textAlign : "left" 311 } 312 } 313 }; 314})(jQuery); 315
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.