PageSourceSearch

https://trainingindustry.com/content/themes/ti/js/lib/dotdotdot/jquery.dotdotdot.js

js trainingindustry.com collected 2026-10-01 09:01:21 UTC 19,798 bytes, 632 lines download raw bytes

1/*
2 *	jQuery dotdotdot 1.8.3
3 *
4 *	Copyright (c) Fred Heusschen
5 *	www.frebsite.nl
6 *
7 *	Plugin website:
8 *	dotdotdot.frebsite.nl
9 *
10 *	Licensed under the MIT license.
11 *	http://en.wikipedia.org/wiki/MIT_License
12 */
13
14;(function ($, undef) {
15    'use strict'
16    if ($.fn.dotdotdot) {
17        return
18    }
19
20    $.fn.dotdotdot = function (o) {
21        if (this.length === 0) {
22            $.fn.dotdotdot.debug(
23                'No element found for "' + this.selector + '".'
24            )
25            return this
26        }
27        if (this.length > 1) {
28            return this.each(function () {
29                $(this).dotdotdot(o)
30            })
31        }
32
33        var $dot = this
34        var orgContent = $dot.contents()
35
36        if ($dot.data('dotdotdot')) {
37            $dot.trigger('destroy.dot')
38        }
39
40        $dot.data('dotdotdot-style', $dot.attr('style') || '')
41        $dot.css('word-wrap', 'break-word')
42        if ($dot.css('white-space') === 'nowrap') {
43            $dot.css('white-space', 'normal')
44        }
45
46        $dot.bind_events = function () {
47            $dot.bind('update.dot', function (e, c) {
48                $dot.removeClass('is-truncated')
49                e.preventDefault()
50                e.stopPropagation()
51
52                switch (typeof opts.height) {
53                    case 'number':
54                        opts.maxHeight = opts.height
55                        break
56
57                    case 'function':
58                        opts.maxHeight = opts.height.call($dot[0])
59                        break
60
61                    default:
62                        opts.maxHeight = getTrueInnerHeight($dot)
63                        break
64                }
65
66                opts.maxHeight += opts.tolerance
67
68                if (typeof c != 'undefined') {
69                    if (
70                        typeof c == 'string' ||
71                        ('nodeType' in c && c.nodeType === 1)
72                    ) {
73                        c = $('<div />').append(c).contents()
74                    }
75                    if (c instanceof $) {
76                        orgContent = c
77                    }
78                }
79
80                $inr = $dot.wrapInner('<div class="dotdotdot" />').children()
81                $inr.contents()
82                    .detach()
83                    .end()
84                    .append(orgContent.clone(true))
85                    .find('br')
86                    .replaceWith('  <br />  ')
87                    .end()
88                    .css({
89                        height: 'auto',
90                        width: 'auto',
91                        border: 'none',
92                        padding: 0,
93                        margin: 0,
94                    })
95
96                var after = false,
97                    trunc = false
98
99                if (conf.afterElement) {
100                    after = conf.afterElement.clone(true)
101                    after.show()
102                    conf.afterElement.detach()
103                }
104
105                if (test($inr, opts)) {
106                    if (opts.wrap == 'children') {
107                        trunc = children($inr, opts, after)
108                    } else {
109                        trunc = ellipsis($inr, $dot, $inr, opts, after)
110                    }
111                }
112                $inr.replaceWith($inr.contents())
113                $inr = null
114
115                if ($.isFunction(opts.callback)) {
116                    opts.callback.call($dot[0], trunc, orgContent)
117                }
118
119                conf.isTruncated = trunc
120                return trunc
121            })
122                .bind('isTruncated.dot', function (e, fn) {
123                    e.preventDefault()
124                    e.stopPropagation()
125
126                    if (typeof fn == 'function') {
127                        fn.call($dot[0], conf.isTruncated)
128                    }
129                    return conf.isTruncated
130                })
131                .bind('originalContent.dot', function (e, fn) {
132                    e.preventDefault()
133                    e.stopPropagation()
134
135                    if (typeof fn == 'function') {
136                        fn.call($dot[0], orgContent)
137                    }
138                    return orgContent
139                })
140                .bind('destroy.dot', function (e) {
141                    e.preventDefault()
142                    e.stopPropagation()
143
144                    $dot.unwatch()
145                        .unbind_events()
146                        .contents()
147                        .detach()
148                        .end()
149                        .append(orgContent)
150                        .attr('style', $dot.data('dotdotdot-style') || '')
151                        .removeClass('is-truncated')
152                        .data('dotdotdot', false)
153                })
154            return $dot
155        } //	/bind_events
156
157        $dot.unbind_events = function () {
158            $dot.unbind('.dot')
159            return $dot
160        } //	/unbind_events
161
162        $dot.watch = function () {
163            $dot.unwatch()
164            if (opts.watch == 'window') {
165                var $window = $(window),
166                    _wWidth = $window.width(),
167                    _wHeight = $window.height()
168
169                $window.bind('resize.dot' + conf.dotId, function () {
170                    if (
171                        _wWidth != $window.width() ||
172                        _wHeight != $window.height() ||
173                        !opts.windowResizeFix
174                    ) {
175                        _wWidth = $window.width()
176                        _wHeight = $window.height()
177
178                        if (watchInt) {
179                            clearInterval(watchInt)
180                        }
181                        watchInt = setTimeout(function () {
182                            $dot.trigger('update.dot')
183                        }, 100)
184                    }
185                })
186            } else {
187                watchOrg = getSizes($dot)
188                watchInt = setInterval(function () {
189                    if ($dot.is(':visible')) {
190                        var watchNew = getSizes($dot)
191                        if (
192                            watchOrg.width != watchNew.width ||
193                            watchOrg.height != watchNew.height
194                        ) {
195                            $dot.trigger('update.dot')
196                            watchOrg = watchNew
197                        }
198                    }
199                }, 500)
200            }
201            return $dot
202        }
203        $dot.unwatch = function () {
204            $(window).unbind('resize.dot' + conf.dotId)
205            if (watchInt) {
206                clearInterval(watchInt)
207            }
208            return $dot
209        }
210
211        var opts = $.extend(true, {}, $.fn.dotdotdot.defaults, o),
212            conf = {},
213            watchOrg = {},
214            watchInt = null,
215            $inr = null
216
217        if (!(opts.lastCharacter.remove instanceof Array)) {
218            opts.lastCharacter.remove =
219                $.fn.dotdotdot.defaultArrays.lastCharacter.remove
220        }
221        if (!(opts.lastCharacter.noEllipsis instanceof Array)) {
222            opts.lastCharacter.noEllipsis =
223                $.fn.dotdotdot.defaultArrays.lastCharacter.noEllipsis
224        }
225
226        conf.afterElement = getElement(opts.after, $dot)
227        conf.isTruncated = false
228        conf.dotId = dotId++
229
230        $dot.data('dotdotdot', true).bind_events().trigger('update.dot')
231
232        if (opts.watch) {
233            $dot.watch()
234        }
235
236        return $dot
237    }
238
239    //	public
240    $.fn.dotdotdot.defaults = {
241        ellipsis: '... ',
242        wrap: 'word',
243        fallbackToLetter: true,
244        lastCharacter: {},
245        tolerance: 0,
246        callback: null,
247        after: null,
248        height: null,
249        watch: false,
250        windowResizeFix: true,
251        maxLength: null,
252    }
253    $.fn.dotdotdot.defaultArrays = {
254        lastCharacter: {
255            remove: [' ', '\u3000', ',', ';', '.', '!', '?'],
256            noEllipsis: [],
257        },
258    }
259    $.fn.dotdotdot.debug = function (msg) {}
260
261    //	private
262    var dotId = 1
263
264    function children($elem, o, after) {
265        var $elements = $elem.children(),
266            isTruncated = false
267
268        $elem.empty()
269
270        for (var a = 0, l = $elements.length; a < l; a++) {
271            var $e = $elements.eq(a)
272            $elem.append($e)
273            if (after) {
274                $elem.append(after)
275            }
276            if (test($elem, o)) {
277                $e.remove()
278                isTruncated = true
279                break
280            } else {
281                if (after) {
282                    after.detach()
283                }
284            }
285        }
286        return isTruncated
287    }
288
289    function ellipsis($elem, $d, $i, o, after) {
290        var isTruncated = false
291
292        //	Don't put the ellipsis directly inside these elements
293        var notx =
294            'a, table, thead, tbody, tfoot, tr, col, colgroup, object, embed, param, ol, ul, dl, blockquote, select, optgroup, option, textarea, script, style'
295
296        //	Don't remove these elements even if they are after the ellipsis
297        var noty = 'script, .dotdotdot-keep'
298
299        $elem
300            .contents()
301            .detach()
302            .each(function () {
303                var e = this,
304                    $e = $(e)
305
306                if (typeof e == 'undefined') {
307                    return true
308                } else if ($e.is(noty)) {
309                    $elem.append($e)
310                } else if (isTruncated) {
311                    return true
312                } else {
313                    $elem.append($e)
314                    if (after && !$e.is(o.after) && !$e.find(o.after).length) {
315                        $elem[$elem.is(notx) ? 'after' : 'append'](after)
316                    }
317                    if (test($i, o)) {
318                        if (e.nodeType == 3) {
319                            // node is TEXT
320                            isTruncated = ellipsisElement($e, $d, $i, o, after)
321                        } else {
322                            isTruncated = ellipsis($e, $d, $i, o, after)
323                        }
324                    }
325
326                    if (!isTruncated) {
327                        if (after) {
328                            after.detach()
329                        }
330                    }
331                }
332            })
333        $d.addClass('is-truncated')
334        return isTruncated
335    }
336
337    function ellipsisElement($e, $d, $i, o, after) {
338        var e = $e[0]
339
340        if (!e) {
341            return false
342        }
343
344        var txt = getTextContent(e),
345            space = txt.indexOf(' ') !== -1 ? ' ' : '\u3000',
346            separator = o.wrap == 'letter' ? '' : space,
347            textArr = txt.split(separator),
348            position = -1,
349            midPos = -1,
350            startPos = 0,
351            endPos = textArr.length - 1
352
353        //	Only one word
354        if (o.fallbackToLetter && startPos === 0 && endPos === 0) {
355            separator = ''
356            textArr = txt.split(separator)
357            endPos = textArr.length - 1
358        }
359
360        if (o.maxLength) {
361            txt = addEllipsis(txt.trim().substr(0, o.maxLength), o)
362            setTextContent(e, txt)
363        } else {
364            while (startPos <= endPos && !(startPos === 0 && endPos === 0)) {
365                var m = Math.floor((startPos + endPos) / 2)
366                if (m == midPos) {
367                    break
368                }
369                midPos = m
370
371                setTextContent(
372                    e,
373                    textArr.slice(0, midPos + 1).join(separator) + o.ellipsis
374                )
375
376                $i.children().each(function () {
377                    $(this).toggle().toggle()
378                })
379
380                if (!test($i, o)) {
381                    position = midPos
382                    startPos = midPos
383                } else {
384                    endPos = midPos
385
386                    //	Fallback to letter
387                    if (o.fallbackToLetter && startPos === 0 && endPos === 0) {
388                        separator = ''
389                        textArr = textArr[0].split(separator)
390                        position = -1
391                        midPos = -1
392                        startPos = 0
393                        endPos = textArr.length - 1
394                    }
395                }
396            }
397
398            if (
399                position != -1 &&
400                !(textArr.length === 1 && textArr[0].length === 0)
401            ) {
402                txt = addEllipsis(
403                    textArr.slice(0, position + 1).join(separator),
404                    o
405                )
406                setTextContent(e, txt)
407            } else {
408                var $w = $e.parent()
409                $e.detach()
410
411                var afterLength =
412                    after && after.closest($w).length ? after.length : 0
413
414                if ($w.contents().length > afterLength) {
415                    e = findLastTextNode($w.contents().eq(-1 - afterLength), $d)
416                } else {
417                    e = findLastTextNode($w, $d, true)
418                    if (!afterLength) {
419                        $w.detach()
420                    }
421                }
422                if (e) {
423                    txt = addEllipsis(getTextContent(e), o)
424                    setTextContent(e, txt)
425                    if (afterLength && after) {
426                        var $parent = after.parent()
427
428                        $(e).parent().append(after)
429
430                        if (!$.trim($parent.html())) {
431                            $parent.remove()
432                        }
433                    }
434                }
435            }
436        }
437
438        return true
439    }
440
441    function test($i, o) {
442        return (
443            $i.innerHeight() > o.maxHeight ||
444            (o.maxLength && $i.text().trim().length > o.maxLength)
445        )
446    }
447
448    function addEllipsis(txt, o) {
449        while ($.inArray(txt.slice(-1), o.lastCharacter.remove) > -1) {
450            txt = txt.slice(0, -1)
451        }
452        if ($.inArray(txt.slice(-1), o.lastCharacter.noEllipsis) < 0) {
453            txt += o.ellipsis
454        }
455        return txt
456    }
457
458    function getSizes($d) {
459        return {
460            width: $d.innerWidth(),
461            height: $d.innerHeight(),
462        }
463    }
464
465    function setTextContent(e, content) {
466        if (e.innerText) {
467            e.innerText = content
468        } else if (e.nodeValue) {
469            e.nodeValue = content
470        } else if (e.textContent) {
471            e.textContent = content
472        }
473    }
474
475    function getTextContent(e) {
476        if (e.innerText) {
477            return e.innerText
478        } else if (e.nodeValue) {
479            return e.nodeValue
480        } else if (e.textContent) {
481            return e.textContent
482        } else {
483            return ''
484        }
485    }
486
487    function getPrevNode(n) {
488        do {
489            n = n.previousSibling
490        } while (n && n.nodeType !== 1 && n.nodeType !== 3)
491
492        return n
493    }
494
495    function findLastTextNode($el, $top, excludeCurrent) {
496        var e = $el && $el[0],
497            p
498        if (e) {
499            if (!excludeCurrent) {
500                if (e.nodeType === 3) {
501                    return e
502                }
503                if ($.trim($el.text())) {
504                    return findLastTextNode($el.contents().last(), $top)
505                }
506            }
507            p = getPrevNode(e)
508            while (!p) {
509                $el = $el.parent()
510                if ($el.is($top) || !$el.length) {
511                    return false
512                }
513                p = getPrevNode($el[0])
514            }
515            if (p) {
516                return findLastTextNode($(p), $top)
517            }
518        }
519        return false
520    }
521
522    function getElement(e, $i) {
523        if (!e) {
524            return false
525        }
526        if (typeof e === 'string') {
527            e = $(e, $i)
528            return e.length ? e : false
529        }
530        return !e.jquery ? false : e
531    }
532
533    function getTrueInnerHeight($el) {
534        var h = $el.innerHeight(),
535            a = ['paddingTop', 'paddingBottom']
536
537        for (var z = 0, l = a.length; z < l; z++) {
538            var m = parseInt($el.css(a[z]), 10)
539            if (isNaN(m)) {
540                m = 0
541            }
542            h -= m
543        }
544        return h
545    }
546
547    //	override jQuery.html
548    var _orgHtml = $.fn.html
549    $.fn.html = function (str) {
550        if (str != undef && !$.isFunction(str) && this.data('dotdotdot')) {
551            return this.trigger('update', [str])
552        }
553        return _orgHtml.apply(this, arguments)
554    }
555
556    //	override jQuery.text
557    var _orgText = $.fn.text
558    $.fn.text = function (str) {
559        if (str != undef && !$.isFunction(str) && this.data('dotdotdot')) {
560            str = $('<div />').text(str).html()
561            return this.trigger('update', [str])
562        }
563        return _orgText.apply(this, arguments)
564    }
565})(jQuery)
566
567/*
568
569## Automatic parsing for CSS classes
570Contributed by [Ramil Valitov](https://github.com/rvalitov)
571
572### The idea
573You can add one or several CSS classes to HTML elements to automatically invoke "jQuery.dotdotdot functionality" and some extra features. It allows to use jQuery.dotdotdot only by adding appropriate CSS classes without JS programming.
574
575### Available classes and their description
576* dot-ellipsis - automatically invoke jQuery.dotdotdot to this element. This class must be included if you plan to use other classes below.
577* dot-resize-update - automatically update if window resize event occurs. It's equivalent to option `watch:'window'`.
578* dot-timer-update - automatically update at regular intervals using setInterval. It's equivalent to option `watch:true`.
579* dot-load-update - automatically update after the window has beem completely rendered. Can be useful if your content is generated dynamically using using JS and, hence, jQuery.dotdotdot can't correctly detect the height of the element before it's rendered completely.
580* dot-height-XXX - available height of content area in pixels, where XXX is a number, e.g. can be `dot-height-35` if you want to set maximum height for 35 pixels. It's equivalent to option `height:'XXX'`.
581
582### Usage examples
583*Adding jQuery.dotdotdot to element*
584
585	<div class="dot-ellipsis">
586	<p>Lorem Ipsum is simply dummy text.</p>
587	</div>
588
589*Adding jQuery.dotdotdot to element with update on window resize*
590
591	<div class="dot-ellipsis dot-resize-update">
592	<p>Lorem Ipsum is simply dummy text.</p>
593	</div>
594
595*Adding jQuery.dotdotdot to element with predefined height of 50px*
596
597	<div class="dot-ellipsis dot-height-50">
598	<p>Lorem Ipsum is simply dummy text.</p>
599	</div>
600
601*/
602
603jQuery(document).ready(function ($) {
604    //We only invoke jQuery.dotdotdot on elements that have dot-ellipsis class
605    $('.dot-ellipsis').each(function () {
606        //Checking if update on window resize required
607        var watch_window = $(this).hasClass('dot-resize-update')
608
609        //Checking if update on timer required
610        var watch_timer = $(this).hasClass('dot-timer-update')
611
612        //Checking if height set
613        var height = 0
614        var classList = $(this).attr('class').split(/\s+/)
615        $.each(classList, function (index, item) {
616            var matchResult = item.match(/^dot-height-(\d+)$/)
617            if (matchResult !== null) height = Number(matchResult[1])
618        })
619
620        //Invoking jQuery.dotdotdot
621        var x = {}
622        if (watch_timer) x.watch = true
623        if (watch_window) x.watch = 'window'
624        if (height > 0) x.height = height
625        $(this).dotdotdot(x)
626    })
627})
628
629//Updating elements (if any) on window.load event
630jQuery(window).on('load', function () {
631    jQuery('.dot-ellipsis.dot-load-update').trigger('update.dot')
632})

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.