1/** 2 * version: 1.1.0 3 * https://github.com/wenzhixin/hint-css 4 */ 5 6(function ($) { 7 8 function maybeCall(thing, ctx) { 9 return (typeof thing == 'function') ? (thing.call(ctx)) : thing 10 } 11 12 function Hint(element, options) { 13 this.$element = $(element) 14 this.options = options 15 this.enabled = true 16 this.fixTitle() 17 } 18 19 Hint.prototype = { 20 show: function () { 21 $('.hint-css').remove() 22 var title = this.getTitle() 23 if (title && this.enabled) { 24 var $tip = this.tip() 25 26 $tip.find('.hint-css-inner')[this.options.html ? 'html' : 'text'](title) 27 [this.options.html ? 'addClass' : 'removeClass']('hint-css-inner-html') 28 .css({ 29 'text-align': this.options.textAlign, 30 'max-width': this.options.maxWidth ? this.options.maxWidth : '' 31 }) 32 33 $tip[0].className = 'hint-css' // reset classname in case of dynamic gravity 34 $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(document.body) 35 36 if (this.options.className) { 37 $tip.addClass(maybeCall(this.options.className, this.$element[0])) 38 } 39 40 if (this.options.fade) { 41 $tip.stop().css({ 42 opacity: 0, 43 display: 'block', 44 visibility: 'visible' 45 }).animate({opacity: this.options.opacity}) 46 } else { 47 $tip.css({visibility: 'visible', opacity: this.options.opacity}) 48 } 49 this.calculatePosition() 50 this._checkStatus() 51 } 52 }, 53 54 update: function (title) { 55 var $tip = this.tip() 56 if ($tip && title && this.enabled) { 57 58 $tip.find('.hint-css-inner')[this.options.html ? 'html' : 'text'](title) 59 } 60 }, 61 62 calculatePosition: function () { 63 var $tip = this.tip() 64 var pos = $.extend({}, this.$element.offset(), { 65 width: this.$element[0].offsetWidth, 66 height: this.$element[0].offsetHeight 67 }) 68 69 var actualWidth = $tip[0].offsetWidth, 70 actualHeight = $tip[0].offsetHeight, 71 gravity = maybeCall(this.options.gravity, this.$element[0]) 72 73 var tp 74 switch (gravity.charAt(0)) { 75 case 'n': 76 tp = { 77 top: pos.top + pos.height + this.options.offset, 78 left: pos.left + pos.width / 2 - actualWidth / 2 79 } 80 break 81 case 's': 82 tp = { 83 top: pos.top - actualHeight - this.options.offset, 84 left: pos.left + pos.width / 2 - actualWidth / 2 85 } 86 break 87 case 'e': 88 tp = { 89 top: pos.top + pos.height / 2 - actualHeight / 2, 90 left: pos.left - actualWidth - this.options.offset 91 } 92 break 93 case 'w': 94 tp = { 95 top: pos.top + pos.height / 2 - actualHeight / 2, 96 left: pos.left + pos.width + this.options.offset 97 } 98 break 99 } 100 101 if (gravity.length == 2) { 102 if (gravity.charAt(1) == 'w') { 103 tp.left = pos.left + pos.width / 2 - 15 104 } else { 105 tp.left = pos.left + pos.width / 2 - actualWidth + 15 106 } 107 } 108 109 if (gravity === 'n' && tp.top + actualHeight > $(window).height()) { 110 gravity = 's' 111 tp.top = pos.top - actualHeight - this.options.offset 112 } 113 114 if (tp.left < 0 || tp.top < 0) { 115 tp.left = -1000 116 tp.top = -1000 117 } 118 119 $tip.css(tp) 120 $tip.addClass('hint-css-' + gravity) 121 $tip.find('.hint-css-arrow')[0].className = 'hint-css-arrow hint-css-arrow-' + gravity.charAt(0) 122 }, 123 124 hide: function () { 125 if (this.options.fade) { 126 this.tip().stop().fadeOut(function () { 127 $(this).remove() 128 }) 129 } else { 130 this.tip().remove() 131 } 132 window.clearInterval(this._checkingInterval) 133 }, 134 135 fixTitle: function () { 136 var $e = this.$element 137 if ($e.attr('title') && !$e.attr('data-hint')) { 138 $e.attr('data-hint', $e.attr('title') || '').removeAttr('title') 139 } 140 }, 141 142 getTitle: function () { 143 var title, $e = this.$element, o = this.options 144 this.fixTitle() 145 if (typeof o.title == 'string') { 146 title = $e.attr(o.title == 'title' ? 'data-hint' : o.title) 147 } else if (typeof o.title == 'function') { 148 title = o.title.call($e[0]) 149 } 150 title = ('' + title).replace(/(^\s*|\s*$)/, "") 151 return title || o.fallback 152 }, 153 154 tip: function () { 155 if (!this.$tip) { 156 this.$tip = $('<div class="hint-css"></div>').html('<div class="hint-css-arrow"></div><div class="hint-css-inner"></div>') 157 this.$tip.data('hint-pointee', this.$element[0]) 158 } 159 return this.$tip 160 }, 161 162 _checkStatus: function () { 163 if (this._checkingInterval) { 164 window.clearInterval(this._checkingInterval) 165 } 166 var that = this 167 this._checkingInterval = window.setInterval(function () { 168 if (!that.$element || that.$element.is(':hidden')) { 169 that.hide() 170 } 171 }, 300) 172 } 173 } 174 175 // global listen 176 $.hint = function () { 177 var get = function (ele, options) { 178 var hint = ele.data('hint-css') 179 var keyAndValue = ele.data('hint-object') 180 options.html = !!ele.data('hint-html') 181 options.textAlign = ele.data('hint-align') || $.hint.defaults.textAlign 182 options.maxWidth = ele.data('hint-max-width') || 0 183 if (!hint) { 184 if (keyAndValue && typeof keyAndValue === 'object') { 185 hint = new Hint(ele, $.extend({}, $.hint.defaults, options, { 186 className: 'hint-object', 187 html: true, 188 title: function () { 189 try { 190 keyAndValue = JSON.parse(ele.attr('data-hint-object')) 191 } catch (e) { 192 // to nothing 193 } 194 return $('<div>').append($.dialog.getKeyAndValTable(keyAndValue, 2)).html() 195 } 196 })) 197 } else { 198 hint = new Hint(ele, $.extend({}, $.hint.defaults, options)) 199 200 } 201 ele.data('hint-css', hint) 202 } 203 return hint 204 }, 205 getGravity = function ($e) { 206 if ($e.data('gravity')) { 207 return $e.data('gravity') 208 } 209 if ($e.hasClass('hint--top')) { 210 return 's' 211 } else if ($e.hasClass('hint--bottom')) { 212 return 'n' 213 } else if ($e.hasClass('hint--left')) { 214 return 'e' 215 } else if ($e.hasClass('hint--right')) { 216 return 'w' 217 } 218 return 'n' 219 } 220 221 var timer = 0 222 $(document).on('mouseenter', '[data-hint]', function (e) { 223 if ($(this).data('hint-type') === 'ignore') { 224 return 225 } 226 if ( 227 $(this).attr('hint-auto') !== undefined && 228 $(this)[0].offsetWidth >= $(this)[0].scrollWidth 229 ) { 230 return 231 } 232 if (e.stopPropagation) { 233 e.stopPropagation() 234 } 235 timer = setTimeout(function () { 236 var $e = $(e.currentTarget) 237 var hint = get($e, {gravity: getGravity($e)}) 238 hint.hoverState = 'in' 239 hint.show() 240 }, $.hint.defaults.delayIn) 241 }) 242 $(document).on('mouseleave', '[data-hint]', function (e) { 243 if ($(this).data('hint-type') === 'ignore') { 244 return 245 } 246 clearTimeout(timer) 247 var $e = $(e.currentTarget) 248 var hint = get($e, {gravity: getGravity($e)}) 249 hint.hoverState = 'out' 250 hint.hide() 251 }) 252 $(document).on('click', '[data-hint]', function (e) { 253 clearTimeout(timer) 254 }) 255 } 256 257 $.fn.hint = function (method, params) { 258 var $e = this 259 var hint = $('body').data('hint-css') 260 $e.data('hint-type', 'ignore') 261 switch (method) { 262 case 'show': 263 hint = new Hint($e, $.extend({}, $.hint.defaults, { 264 gravity: 'n', 265 className: 'hint-object', 266 html: true, 267 title: function () { 268 return $('<div>').append($.dialog.getKeyAndValTable(params, 2)).html() 269 } 270 })) 271 hint.hoverState = 'in' 272 hint.show() 273 $('body').data('hint-css', hint) 274 break 275 case 'update': 276 hint.update($('<div>').append($.dialog.getKeyAndValTable(params, 2)).html()) 277 break 278 case 'hide': 279 hint.hoverState = 'out' 280 hint.hide() 281 break 282 } 283 } 284 285 $.hint.defaults = { 286 className: null, 287 delayIn: 500, 288 fade: true, 289 fallback: '', 290 gravity: 'n',
291 html: false, //data-hint-html="true|false" 292 live: false, 293 offset: 0, 294 opacity: 0.8, 295 title: 'title', 296 textAlign: 'center', //data-hint-align="center" 297 maxWidth: 0 // data-hint-max-width 298 } 299 300})(jQuery) 301 302$(function () { 303 $.hint() 304})
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.