PageSourceSearch

https://thesipmag.com/wp-content/plugins/sip-archive/assets/sip-archive.js?ver=1.0.0

js thesipmag.com collected 2026-09-29 06:34:16 UTC 3,148 bytes, 126 lines download raw bytes

1/**
2 * The 'Sip Archive: the finding aid.
3 *
4 * Every story is already in the HTML. This just hides the ones that do not
5 * match. If the script never loads, the reader still sees the full list.
6 */
7( function () {
8	'use strict';
9
10	function initBrowser( root ) {
11
12		var list    = root.querySelector( '[data-sip-list]' );
13		var items   = Array.prototype.slice.call( root.querySelectorAll( '.sip-browser__item' ) );
14		var count   = root.querySelector( '[data-sip-count]' );
15		var empty   = root.querySelector( '[data-sip-empty]' );
16		var reset   = root.querySelector( '[data-sip-reset]' );
17		var inputs  = Array.prototype.slice.call( root.querySelectorAll( '[data-sip-filter]' ) );
18
19		if ( ! list || ! items.length ) {
20			return;
21		}
22
23		var singular = ( count && count.dataset.singular ) || 'story';
24		var plural   = ( count && count.dataset.plural ) || 'stories';
25
26		function currentFilters() {
27			var filters = { q: '', issue: '', section: '', author: '' };
28
29			inputs.forEach( function ( input ) {
30				var key = input.getAttribute( 'data-sip-filter' );
31				if ( key in filters ) {
32					filters[ key ] = ( input.value || '' ).trim();
33				}
34			} );
35
36			return filters;
37		}
38
39		function matches( item, filters ) {
40
41			if ( filters.issue && item.getAttribute( 'data-issue' ) !== filters.issue ) {
42				return false;
43			}
44
45			if ( filters.section && item.getAttribute( 'data-section' ) !== filters.section ) {
46				return false;
47			}
48
49			if ( filters.author && item.getAttribute( 'data-author' ) !== filters.author ) {
50				return false;
51			}
52
53			if ( filters.q ) {
54				var haystack = item.getAttribute( 'data-search' ) || '';
55				var needles  = filters.q.toLowerCase().split( /\s+/ );
56
57				for ( var i = 0; i < needles.length; i++ ) {
58					if ( haystack.indexOf( needles[ i ] ) === -1 ) {
59						return false;
60					}
61				}
62			}
63
64			return true;
65		}
66
67		function apply() {
68
69			var filters = currentFilters();
70			var shown   = 0;
71			var active  = !! ( filters.q || filters.issue || filters.section || filters.author );
72
73			items.forEach( function ( item ) {
74				if ( matches( item, filters ) ) {
75					item.hidden = false;
76					shown++;
77				} else {
78					item.hidden = true;
79				}
80			} );
81
82			if ( count ) {
83				count.textContent = shown.toLocaleString() + ' ' + ( 1 === shown ? singular : plural );
84			}
85
86			if ( empty ) {
87				empty.hidden = shown !== 0;
88			}
89
90			if ( reset ) {
91				reset.hidden = ! active;
92			}
93		}
94
95		inputs.forEach( function ( input ) {
96			var event = 'search' === input.type || 'text' === input.type ? 'input' : 'change';
97			input.addEventListener( event, apply );
98		} );
99
100		if ( reset ) {
101			reset.addEventListener( 'click', function () {
102				inputs.forEach( function ( input ) {
103					input.value = '';
104				} );
105				apply();
106				var search = root.querySelector( '[data-sip-filter="q"]' );
107				if ( search ) {
108					search.focus();
109				}
110			} );
111		}
112
113		apply();
114	}
115
116	function init() {
117		var roots = document.querySelectorAll( '[data-sip-browser]' );
118		Array.prototype.forEach.call( roots, initBrowser );
119	}
120
121	if ( 'loading' === document.readyState ) {
122		document.addEventListener( 'DOMContentLoaded', init );
123	} else {
124		init();
125	}
126}() );

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.