PageSourceSearch

https://jankelley.com/wp-content/themes/jankelley/assets/js/splitting.js?ver=7.1.2

js jankelley.com collected 2026-09-26 10:25:12 UTC 12,298 bytes, 498 lines download raw bytes

vendor: 4,186 bytes, lines 1-180
1(function (global, factory) {
2	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3	typeof define === 'function' && define.amd ? define(factory) :
4	(global.Splitting = factory());
5}(this, (function () { 'use strict';
6
7var root = document;
8var createText = root.createTextNode.bind(root);
9
10/**
11 * # setProperty
12 * Apply a CSS var
13 * @param el{HTMLElement} 
14 * @param varName {string} 
15 * @param value {string|number}  
16 */
17function setProperty(el, varName, value) {
18    el.style.setProperty(varName, value);
19} 
20
21/**
22 * 
23 * @param {Node} el 
24 * @param {Node} child 
25 */
26function appendChild(el, child) {
27  return el.appendChild(child);
28}
29
30function createElement(parent, key, text, whitespace) {
31  var el = root.createElement('span');
32  key && (el.className = key); 
33  if (text) { 
34      !whitespace && el.setAttribute("data-" + key, text);
35      el.textContent = text; 
36  }
37  return (parent && appendChild(parent, el)) || el;
38}
39
40function getData(el, key) {
41  return el.getAttribute("data-" + key)
42}
43
44/**
45 * 
46 * @param e {import('../types').Target} 
47 * @param parent {HTMLElement}
48 * @returns {HTMLElement[]}
49 */
50function $(e, parent) {
51
52    return !e || e.length == 0
53        ? // null or empty string returns empty array
54          []
55        : e.nodeName
56            ? // a single element is wrapped in an array
57              [e]
58            : // selector and NodeList are converted to Element[]
59              [].slice.call(e[0].nodeName ? e : (parent || root).querySelectorAll(e));
60}
61
62/**
63 * Creates and fills an array with the value provided
64 * @template {T}
65 * @param {number} len
66 * @param {() => T} valueProvider
67 * @return {T}
68 */
69function Array2D(len) {
70    var a = [];
71    for (; len--; ) {
72        a[len] = [];
73    }
74    return a;
75}
76
77function each(items, fn) {
78    items && items.some(fn);
79}
80
81function selectFrom(obj) {
82    return function (key) {
83        return obj[key];
84    }
85}
86
87/**
88 * # Splitting.index
89 * Index split elements and add them to a Splitting instance.
90 *
91 * @param element {HTMLElement}
92 * @param key {string}
93 * @param items {HTMLElement[] | HTMLElement[][]}
94 */
95function index(element, key, items) {
96    var prefix = '--' + key;
97    var cssVar = prefix + "-index";
98
99    each(items, function (items, i) {
100        if (Array.isArray(items)) {
101            each(items, function(item) {
102                setProperty(item, cssVar, i);
103            });
104        } else {
105            setProperty(items, cssVar, i);
106        }
107    });
108
109    setProperty(element, prefix + "-total", items.length);
110}
111
112/**
113 * @type {Record<string, import('./types').ISplittingPlugin>}
114 */
115var plugins = {};
116
117/**
118 * @param by {string}
119 * @param parent {string}
120 * @param deps {string[]}
121 * @return {string[]}
122 */
123function resolvePlugins(by, parent, deps) {
124    // skip if already visited this dependency
125    var index = deps.indexOf(by);
126    if (index == -1) {
127        // if new to dependency array, add to the beginning
128        deps.unshift(by);
129
130        // recursively call this function for all dependencies
131        each(plugins[by].depends, function(p) {
132            resolvePlugins(p, by, deps);
133        });
134    } else {
135        // if this dependency was added already move to the left of
136        // the parent dependency so it gets loaded in order
137        var indexOfParent = deps.indexOf(parent);
138        deps.splice(index, 1);
139        deps.splice(indexOfParent, 0, by);
140    }
141    return deps;
142}
143
144/**
145 * Internal utility for creating plugins... essentially to reduce
146 * the size of the library
147 * @param {string} by 
148 * @param {string} key 
149 * @param {string[]} depends 
150 * @param {Function} split 
151 * @returns {import('./types').ISplittingPlugin}
152 */
153function createPlugin(by, depends, key, split) {
154    return {
155        by: by,
156        depends: depends,
157        key: key,
158        split: split
159    }
160}
161
162/**
163 *
164 * @param by {string}
165 * @returns {import('./types').ISplittingPlugin[]}
166 */
167function resolve(by) {
168    return resolvePlugins(by, 0, []).map(selectFrom(plugins));
169}
170
171/**
172 * Adds a new plugin to splitting
173 * @param opts {import('./types').ISplittingPlugin}
174 */
175function add(opts) {
176    plugins[opts.by] = opts;
177}
178
179/**
180 * # Splitting.split
181 * Split an element's textContent into individual elements
182 * @param el {Node} Element to split
183 * @param key {string}
184 * @param splitOn {string}
185 * @param includeSpace {boolean}
186 * @returns {HTMLElement[]}
187 */
188function splitText(el, key, splitOn, includePrevious, preserveWhitespace) {
189    // Combine any strange text nodes or empty whitespace.
190    el.normalize();
191
192    // Use fragment to prevent unnecessary DOM thrashing.
193    var elements = [];
194    var F = document.createDocumentFragment();
195
196    if (includePrevious) {
197        elements.push(el.previousSibling);
198    }
199
200    var allElements = [];
201    $(el.childNodes).some(function(next) {
202        if (next.tagName && !next.hasChildNodes()) {
203            // keep elements without child nodes (no text and no children)
204            allElements.push(next);
205            return;
206        }
207        // Recursively run through child nodes
208        if (next.childNodes && next.childNodes.length) {
209            allElements.push(next);
210            elements.push.apply(elements, splitText(next, key, splitOn, includePrevious, preserveWhitespace));
211            return;
212        }
213
214        // Get the text to split, trimming out the whitespace
215        /** @type {string} */
216        var wholeText = next.wholeText || '';
217        var contents = wholeText.trim();
218
219        // If there's no text left after trimming whitespace, continue the loop
220        if (contents.length) {
221            // insert leading space if there was one
222            if (wholeText[0] === ' ') {
223                allElements.push(createText(' '));
224            }
225            // Concatenate the split text children back into the full array
226            each(contents.split(splitOn), function(splitText, i) {
227                if (i && preserveWhitespace) {
228                    allElements.push(createElement(F, "whitespace", " ", preserveWhitespace));
229                }
230                var splitEl = createElement(F, key, splitText);
231                elements.push(splitEl);
232                allElements.push(splitEl);
233            }); 
234            // insert trailing space if there was one
235            if (wholeText[wholeText.length - 1] === ' ') {
236                allElements.push(createText(' '));
237            }
238        }
239    });
240
241    each(allElements, function(el) {
242        appendChild(F, el);
243    });
244
245    // Clear out the existing element
246    el.innerHTML = "";
247    appendChild(el, F);
248    return elements;
249}
250
251/** an empty value */
252var _ = 0;
253
254function copy(dest, src) {
255    for (var k in src) {
256        dest[k] = src[k];
257    }
258    return dest;
259}
260
261var WORDS = 'words';
262
263var wordPlugin = createPlugin(
264    /*by: */ WORDS,
265    /*depends: */ _,
266    /*key: */ 'word', 
267    /*split: */ function(el) {
268        return splitText(el, 'word', /\s+/, 0, 1)
269    }
270);
271
272var CHARS = "chars";
273
274var charPlugin = createPlugin(
275    /*by: */ CHARS,
276    /*depends: */ [WORDS],
277    /*key: */ "char", 
278    /*split: */ function(el, options, ctx) {
279        var results = [];
280
281        each(ctx[WORDS], function(word, i) {
282            results.push.apply(results, splitText(word, "char", "", options.whitespace && i));
283        });
284
285        return results;
286    }
287);
288
289/**
290 * # Splitting
291 * 
292 * @param opts {import('./types').ISplittingOptions} 
293 */
294function Splitting (opts) {
295  opts = opts || {};
296  var key = opts.key;
297
298  return $(opts.target || '[data-splitting]').map(function(el) {
299    
300    var ctx = el['🍌'];  
301    if (!opts.force && ctx) {
302      return ctx;
303    }
304
305    ctx = el['🍌'] = { el: el };
306    var items = resolve(opts.by || getData(el, 'splitting') || CHARS);
307    var opts2 = copy({}, opts);
308    each(items, function(plugin) {
309      if (plugin.split) {
310        var pluginBy = plugin.by;
311        var key2 = (key ? '-' + key : '') + plugin.key;
312        var results = plugin.split(el, opts2, ctx);
313        key2 && index(el, key2, results);
314        ctx[pluginBy] = results;
315        el.classList.add(pluginBy);
316      } 
317    });
318
319    el.classList.add('splitting');
320    return ctx;
321  })
322}
323
324/**
325 * # Splitting.html
326 * 
327 * @param opts {import('./types').ISplittingOptions}
328 */
329function html(opts) {
330  opts = opts || {};
331  var parent = opts.target =  createElement();
vendor: 3,960 bytes, lines 332-498
332  parent.innerHTML = opts.content;
333  Splitting(opts);
334  return parent.outerHTML
335}
336
337Splitting.html = html;
338Splitting.add = add;
339
340function detectGrid(el, options, side) {
341    var items = $(options.matching || el.children, el);
342    var c = {};
343
344    each(items, function(w) {
345        var val = Math.round(w[side]);
346        (c[val] || (c[val] = [])).push(w);
347    });
348
349    return Object.keys(c).map(Number).sort(byNumber).map(selectFrom(c));
350}
351
352function byNumber(a, b) {
353    return a - b;
354}
355
356var linePlugin = createPlugin(
357    /*by: */ 'lines',
358    /*depends: */ [WORDS],
359    /*key: */ 'line',
360    /*split: */ function(el, options, ctx) {
361      return detectGrid(el, { matching: ctx[WORDS] }, 'offsetTop')
362    }
363);
364
365var itemPlugin = createPlugin(
366    /*by: */ 'items',
367    /*depends: */ _,
368    /*key: */ 'item', 
369    /*split: */ function(el, options) {
370        return $(options.matching || el.children, el)
371    }
372);
373
374var rowPlugin = createPlugin(
375    /*by: */ 'rows',
376    /*depends: */ _,
377    /*key: */ 'row', 
378    /*split: */ function(el, options) {
379        return detectGrid(el, options, "offsetTop");
380    }
381);
382
383var columnPlugin = createPlugin(
384    /*by: */ 'cols',
385    /*depends: */ _,
386    /*key: */ "col", 
387    /*split: */ function(el, options) {
388        return detectGrid(el, options, "offsetLeft");
389    }
390);
391
392var gridPlugin = createPlugin(
393    /*by: */ 'grid',
394    /*depends: */ ['rows', 'cols']
395);
396
397var LAYOUT = "layout";
398
399var layoutPlugin = createPlugin(
400    /*by: */ LAYOUT,
401    /*depends: */ _,
402    /*key: */ _,
403    /*split: */ function(el, opts) {
404        // detect and set options
405        var rows =  opts.rows = +(opts.rows || getData(el, 'rows') || 1);
406        var columns = opts.columns = +(opts.columns || getData(el, 'columns') || 1);
407
408        // Seek out the first <img> if the value is true 
409        opts.image = opts.image || getData(el, 'image') || el.currentSrc || el.src;
410        if (opts.image) {
411            var img = $("img", el)[0];
412            opts.image = img && (img.currentSrc || img.src);
413        }
414
415        // add optional image to background
416        if (opts.image) {
417            setProperty(el, "background-image", "url(" + opts.image + ")");
418        }
419
420        var totalCells = rows * columns;
421        var elements = [];
422
423        var container = createElement(_, "cell-grid");
424        while (totalCells--) {
425            // Create a span
426            var cell = createElement(container, "cell");
427            createElement(cell, "cell-inner");
428            elements.push(cell);
429        }
430
431        // Append elements back into the parent
432        appendChild(el, container);
433
434        return elements;
435    }
436);
437
438var cellRowPlugin = createPlugin(
439    /*by: */ "cellRows",
440    /*depends: */ [LAYOUT],
441    /*key: */ "row",
442    /*split: */ function(el, opts, ctx) {
443        var rowCount = opts.rows;
444        var result = Array2D(rowCount);
445
446        each(ctx[LAYOUT], function(cell, i, src) {
447            result[Math.floor(i / (src.length / rowCount))].push(cell);
448        });
449
450        return result;
451    }
452);
453
454var cellColumnPlugin = createPlugin(
455    /*by: */ "cellColumns",
456    /*depends: */ [LAYOUT],
457    /*key: */ "col",
458    /*split: */ function(el, opts, ctx) {
459        var columnCount = opts.columns;
460        var result = Array2D(columnCount);
461
462        each(ctx[LAYOUT], function(cell, i) {
463            result[i % columnCount].push(cell);
464        });
465
466        return result;
467    }
468);
469
470var cellPlugin = createPlugin(
471    /*by: */ "cells",
472    /*depends: */ ['cellRows', 'cellColumns'],
473    /*key: */ "cell", 
474    /*split: */ function(el, opt, ctx) { 
475        // re-index the layout as the cells
476        return ctx[LAYOUT];
477    }
478);
479
480// install plugins
481// word/char plugins
482add(wordPlugin);
483add(charPlugin);
484add(linePlugin);
485// grid plugins
486add(itemPlugin);
487add(rowPlugin);
488add(columnPlugin);
489add(gridPlugin);
490// cell-layout plugins
491add(layoutPlugin);
492add(cellRowPlugin);
493add(cellColumnPlugin);
494add(cellPlugin);
495
496return Splitting;
497
498})));

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.