1jQuery.noConflict(); 2/*! 3 * jQuery.ellipsis 4 * http://github.com/jjenzz/jquery.ellipsis 5 * -------------------------------------------------------------------------- 6 * Copyright (c) 2013 J. Smith (@jjenzz) 7 * Dual licensed under the MIT and GPL licenses: 8 * http://www.opensource.org/licenses/mit-license.php 9 * http://www.gnu.org/licenses/gpl.html 10 * 11 * adds a class to the last 'allowed' line of text so you can apply 12 * text-overflow: ellipsis; 13 */ 14(function (factory) { 15 'use strict'; 16 17 if (typeof define === 'function' && define.amd) { 18 // AMD. register as an anonymous module 19 define(['jquery'], factory); 20 } else { 21 // browser globals 22 factory(jQuery); 23 } 24}(function ($) { 25 'use strict'; 26 27 var namespace = 'ellipsis', 28 span = '<span style="white-space: nowrap;">', 29 defaults = { 30 lines: 'auto', 31 ellipClass: 'ellip', 32 responsive: false 33 }; 34 35 /** 36 * Ellipsis() 37 * -------------------------------------------------------------------------- 38 * @param {Node} el 39 * @param {Object} opts 40 */ 41 function Ellipsis(el, opts) { 42 var base = this, 43 currLine = 0, 44 lines = [], 45 setStartEllipAt, 46 startEllipAt, 47 currOffset, 48 lineHeight, 49 contHeight, 50 words, 51 htmlEntities; 52 53 // List of HTML entities for escaping. 54 htmlEntities = { 55 '&': '&', 56 '<': '<', 57 '>': '>', 58 '"': '"', 59 "'": ''', 60 '`': '`', 61 '/': '/', 62 '\\': '\' 63 }; 64 65 base.$cont = $(el); 66 base.opts = $.extend({}, defaults, opts); 67 68 /** 69 * create() happens once when 70 * instance is created 71 */ 72 function create() { 73 base.text = base.$cont.text(); 74 base.opts.ellipLineClass = base.opts.ellipClass + '-line'; 75 76 base.$el = $('<span class="' + base.opts.ellipClass + '" />'); 77 base.$el.text(base.text); 78 79 base.$cont.empty().append(base.$el); 80 81 init(); 82 } 83 84 /** 85 * init() 86 */ 87 function init() { 88 base.$el.removeClass("has-child"); 89 // if they only want one line just add 90 // the class and do nothing else 91 if (typeof base.opts.lines === 'number' && base.opts.lines < 2) { 92 base.$el.addClass(base.opts.ellipLineClass); 93 return; 94 } 95 96 contHeight = base.$cont.height(); 97 98 // if they only want to ellipsis the overflow 99 // then do nothing if there is no overflow 100 if (base.opts.lines === 'auto' && base.$el.prop('scrollHeight') <= contHeight) { 101 return; 102 } 103 104 if (!setStartEllipAt) { 105 return; 106 } 107 108 // create an array of words from our string 109 words = $.trim(escapeText(base.text)).split(/\s+/); 110 111 // wrap each word in a span and temporarily append to the DOM 112 base.$el.html(span + words.join('</span> ' + span) + '</span>'); 113 114 // loop through words to determine which word the 115 // ellipsis container should start from (need to 116 // re-query spans from DOM so we can get their offset) 117 base.$el.find('span').each(setStartEllipAt); 118 119 // startEllipAt could be 0 so make sure we're 120 // checking undefined instead of falsey 121 if (startEllipAt != null) { 122 updateText(startEllipAt); 123 } 124 125 if (base.opts.responsive) { 126 //Update max-height to avoid full text showing during resize event 127 $(base.$el).css({ 128 'max-height': '', 129 }).css({ 130 'max-height': base.$el.outerHeight(true) 131 }); 132 } 133 } 134 135 /** 136 * updateText() updates the text in the DOM 137 * with a span around the line that needs 138 * to be truncated 139 * 140 * @param {Number} i 141 */ 142 function updateText(nth) { 143 // add a span that wraps from nth 144 // word to the end of the string 145 words[nth] = '<span class="' + base.opts.ellipLineClass + '">' + words[nth]; 146 words.push('</span>'); 147 148 // update the DOM with 149 // our new string/markup 150 base.$el.html(words.join(' '));
151 base.$el.addClass("has-child"); 152 } 153 154 function escapeText(text) { 155 return String(text).replace(/[&<>"'``\/]/g, function (s) { 156 return htmlEntities[s]; 157 }); 158 } 159 160 // only define the method if it's required 161 if (base.opts.lines === 'auto') { 162 163 /** 164 * setStartEllipByHeight() sets the start 165 * position to the first word in the last 166 * line of the element that doesn't overflow 167 * 168 * @param {Number} i 169 * @param {Node} word 170 */ 171 var setStartEllipByHeight = function (i, word) { 172 var $word = $(word), 173 top = $word.position().top; 174 175 lineHeight = lineHeight || $word.height(); 176 177 if (top === currOffset) { 178 // if it's top matches currOffset 179 // then it's on the same line 180 // as the previous word 181 lines[currLine].push($word); 182 } else { 183 // otherwise we're 184 // on a new line 185 currOffset = top; 186 currLine += 1; 187 lines[currLine] = [$word]; 188 } 189 190 // if the bottom of the word is outside 191 // the element (overflowing) then 192 // stop looping and set startEllipAt to 193 // the first word in the previous line 194 if (top + lineHeight > contHeight) { 195 startEllipAt = i - lines[currLine - 1].length; 196 return false; 197 } 198 }; 199 200 setStartEllipAt = setStartEllipByHeight; 201 } 202 203 // only define the method if it's required 204 if (typeof base.opts.lines === 'number' && base.opts.lines > 1) { 205 206 /** 207 * setStartEllipByLine() sets the start 208 * position to the first word in the line 209 * that was passed to opts. This forces 210 * the ellipsis on a specific line 211 * regardless of overflow 212 * 213 * @param {Number} i 214 * @param {Node} word 215 */ 216 var setStartEllipByLine = function (i, word) { 217 var $word = $(word), 218 top = $word.position().top; 219 220 // if top isn't currOfset 221 // then we're on a new line 222 if (top !== currOffset) { 223 currOffset = top; 224 currLine += 1; 225 } 226 227 // if the word's currLine is equal 228 // to the line limit passed via options 229 // then start ellip from this 230 // word and stop looping 231 if (currLine === base.opts.lines) { 232 startEllipAt = i; 233 return false; 234 } 235 }; 236 237 setStartEllipAt = setStartEllipByLine; 238 } 239 240 // only bind to window resize if required 241 if (base.opts.responsive) { 242 243 /** 244 * resize() resets necessary vars 245 * and content and then re-initialises 246 * the Ellipsis script 247 */ 248 249 var rtime; 250 var timeout = false; 251 var delta = 200; 252 $(window).resize(function () { 253 rtime = new Date(); 254 if (timeout === false) { 255 timeout = true; 256 setTimeout(resize, delta); 257 } 258 }); 259 260 function resize() { 261 if (new Date() - rtime < delta) { 262 setTimeout(resize, delta); 263 } else { 264 timeout = false; 265 lines = []; 266 currLine = 0; 267 currOffset = null; 268 startEllipAt = null; 269 base.$el.html(escapeText(base.text)); 270 setTimeout(init, 100); 271 } 272 } 273 274 } 275 276 // start 'er up 277 create(); 278 } 279 280 $.fn[namespace] = function (opts) { 281 return this.each(function () { 282 try { 283 $(this).data(namespace, (new Ellipsis(this, opts))); 284 } catch (err) { 285 if (window.console) { 286 console.error(namespace + ': ' + err); 287 } 288 } 289 }); 290 }; 291 292}));
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.