PageSourceSearch

https://www.myticket.de/assets/myticket/libs/clamp-js-main/clamp.js?v=91f02ad75e9aafaf96f181bff0f7754b81a804f5

js myticket.de collected 2026-09-24 11:09:06 UTC 8,765 bytes, 278 lines download raw bytes

1/*!
2 * Clamp.js 0.11.5
3 *
4 * Now Maintained by Josh English http://joshengish.com
5 * Joseph Schmitt http://joe.sh
6 * Released under the WTFPL license
7 * http://sam.zoy.org/wtfpl/
8 */
9
10(function(root, factory) {
11  if (typeof define === 'function' && define.amd) {
12    // AMD
13    define([], factory);
14  } else if (typeof exports === 'object') {
15    // Node, CommonJS-like
16    module.exports = {clamp: factory()};
17  } else {
18    // Browser globals
19    root.$clamp = factory();
20  }
21}(this, function() {
22  /**
23   * Clamps a text node.
24   * @param {HTMLElement} element. Element containing the text node to clamp.
25   * @param {Object} options. Options to pass to the clamper.
26   */
27  function clamp(element, options) {
28    options = options || {};
29
30    var self = this,
31      win = window,
32      opt = {
33        clamp: options.clamp || 2,
34        useNativeClamp: typeof(options.useNativeClamp) != 'undefined' ? options.useNativeClamp : true,
35        splitOnChars: options.splitOnChars || ['.', '-', '–', '—', ' '], //Split on sentences (periods), hypens, en-dashes, em-dashes, and words (spaces).
36        animate: options.animate || false,
37        truncationChar: options.truncationChar || '…',
38        truncationHTML: options.truncationHTML
39      },
40
41      sty = element.style,
42      originalText = element.innerHTML,
43
44      supportsNativeClamp = typeof(element.style.webkitLineClamp) != 'undefined',
45      clampValue = opt.clamp,
46      isCSSValue = clampValue.indexOf && (clampValue.indexOf('px') > -1 || clampValue.indexOf('em') > -1),
47      truncationHTMLContainer;
48
49    if (opt.truncationHTML) {
50      truncationHTMLContainer = document.createElement('span');
51      truncationHTMLContainer.innerHTML = opt.truncationHTML;
52    }
53
54
55    // UTILITY FUNCTIONS __________________________________________________________
56
57    /**
58     * Return the current style for an element.
59     * @param {HTMLElement} elem The element to compute.
60     * @param {string} prop The style property.
61     * @returns {number}
62     */
63    function computeStyle(elem, prop) {
64      if (!win.getComputedStyle) {
65        win.getComputedStyle = function(el, pseudo) {
66          this.el = el;
67          this.getPropertyValue = function(prop) {
68            var re = /(\-([a-z]){1})/g;
69            if (prop == 'float') prop = 'styleFloat';
70            if (re.test(prop)) {
71              prop = prop.replace(re, function() {
72                return arguments[2].toUpperCase();
73              });
74            }
75            return el.currentStyle && el.currentStyle[prop] ? el.currentStyle[prop] : null;
76          };
77          return this;
78        };
79      }
80
81      return win.getComputedStyle(elem, null).getPropertyValue(prop);
82    }
83
84    /**
85     * Returns the maximum number of lines of text that should be rendered based
86     * on the current height of the element and the line-height of the text.
87     */
88    function getMaxLines(height) {
89      var availHeight = height || element.clientHeight,
90        lineHeight = getLineHeight(element);
91
92      return Math.max(Math.floor(availHeight / lineHeight), 0);
93    }
94
95    /**
96     * Returns the maximum height a given element should have based on the line-
97     * height of the text and the given clamp value.
98     */
99    function getMaxHeight(clmp) {
100      var lineHeight = getLineHeight(element);
101      // console.log(lineHeight * clmp);
102      return lineHeight * clmp;
103    }
104
105    /**
106     * Returns the line-height of an element as an integer.
107     */
108    function getLineHeight(elem) {
109      var lh = computeStyle(elem, 'line-height');
110      if (lh == 'normal') {
111        // Normal line heights vary from browser to browser. The spec recommends
112        // a value between 1.0 and 1.2 of the font size. Using 1.1 to split the diff.
113        lh = parseInt(computeStyle(elem, 'font-size')) * 1.187;
114      }
115      return Math.ceil(parseFloat(lh));
116    }
117
118
119    // MEAT AND POTATOES (MMMM, POTATOES...) ______________________________________
120    var splitOnChars = opt.splitOnChars.slice(0),
121      splitChar = splitOnChars[0],
122      chunks,
123      lastChunk;
124
125    /**
126     * Gets an element's last child. That may be another node or a node's contents.
127     */
128    function getLastChild(elem) {
129      if (!elem.lastChild) {
130        return;
131      }
132      //Current element has children, need to go deeper and get last child as a text node
133      if (elem.lastChild.childNodes && elem.lastChild.childNodes.length > 0) {
134        return getLastChild(Array.prototype.slice.call(elem.childNodes).pop());
135      }
136      //This is the absolute last child, a text node, but something's wrong with it. Remove it and keep trying
137      else if (!elem.lastChild || !elem.lastChild.nodeValue || elem.lastChild.nodeValue === '' || elem.lastChild.nodeValue == opt.truncationChar) {
138        elem.lastChild.parentNode.removeChild(elem.lastChild);
139        return getLastChild(element);
140      }
141      //This is the last child we want, return it
142      else {
143        return elem.lastChild;
144      }
145    }
146
147    /**
148     * Removes one character at a time from the text until its width or
149     * height is beneath the passed-in max param.
150     */
151    function truncate(target, maxHeight) {
152      if (!target || !maxHeight) {
153        return;
154      }
155
156      /**
157       * Resets global variables.
158       */
159      function reset() {
160        splitOnChars = opt.splitOnChars.slice(0);
161        splitChar = splitOnChars[0];
162        chunks = null;
163        lastChunk = null;
164      }
165      // console.log(splitOnChars);
166
167      var nodeValue = target.nodeValue.replace(opt.truncationChar, '');
168
169      //Grab the next chunks
170      if (!chunks) {
171        //If there are more characters to try, grab the next one
172        if (splitOnChars.length > 0) {
173          splitChar = splitOnChars.shift();
174        }
175        //No characters to chunk by. Go character-by-character
176        else {
177          splitChar = '';
178        }
179
180        chunks = nodeValue.split(splitChar);
181      }
182
183      //If there are chunks left to remove, remove the last one and see if
184      // the nodeValue fits.
185      if (chunks.length > 1) {
186        // console.log('chunks', chunks);
187        lastChunk = chunks.pop();
188        // console.log('lastChunk', lastChunk);
189        applyEllipsis(target, chunks.join(splitChar));
190      }
191      //No more chunks can be removed using this character
192      else {
193        chunks = null;
194      }
195
196      //Insert the custom HTML before the truncation character
197      if (truncationHTMLContainer) {
198        target.nodeValue = target.nodeValue.replace(opt.truncationChar, '');
199        element.innerHTML = target.nodeValue + ' ' + truncationHTMLContainer.innerHTML + opt.truncationChar;
200      }
201
202      //Search produced valid chunks
203      if (chunks) {
204        //It fits
205        if (element.clientHeight <= maxHeight) {
206          // console.log(element.clientHeight, maxHeight);
207          //There's still more characters to try splitting on, not quite done yet
208          if (splitOnChars.length >= 0 && splitChar !== '') {
209            applyEllipsis(target, chunks.join(splitChar) + splitChar + lastChunk);
210            chunks = null;
211          }
212          //Finished!
213          else {
214            return element.innerHTML;
215          }
216        }
217      }
218      //No valid chunks produced
219      else {
220        //No valid chunks even when splitting by letter, time to move
221        //on to the next node
222        if (splitChar === '') {
223          applyEllipsis(target, '');
224          target = getLastChild(element);
225
226          reset();
227        }
228      }
229
230      //If you get here it means still too big, let's keep truncating
231      if (opt.animate) {
232        setTimeout(function() {
233          truncate(target, maxHeight);
234        }, opt.animate === true ? 10 : opt.animate);
235      } else {
236        return truncate(target, maxHeight);
237      }
238    }
239
240    function applyEllipsis(elem, str) {
241      elem.nodeValue = str + opt.truncationChar;
242    }
243
244
245    // CONSTRUCTOR ________________________________________________________________
246
247    if (clampValue == 'auto') {
248      clampValue = getMaxLines();
249    } else if (isCSSValue) {
250      clampValue = getMaxLines(parseInt(clampValue));
251    }
252
253    var clampedText;
254    if (supportsNativeClamp && opt.useNativeClamp) {
255      sty.overflow = 'hidden';
256      sty.textOverflow = 'ellipsis';
257      sty.webkitBoxOrient = 'vertical';
258      sty.display = '-webkit-box';
259      sty.webkitLineClamp = clampValue;
260
261      if (isCSSValue) {
262        sty.height = opt.clamp + 'px';
263      }
264    } else {
265      var height = getMaxHeight(clampValue);
266      if (height < element.clientHeight) {
267        clampedText = truncate(getLastChild(element), height);
268      }
269    }
270
271    return {
272      'original': originalText,
273      'clamped': clampedText
274    };
275  }
276
277  return clamp;
278}));

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.