PageSourceSearch

https://digochoeu.gal/wp-content/plugins/stellar/js/stellar.min.js?ver=2.1.4

js digochoeu.gal collected 2026-09-26 13:03:08 UTC 25,655 bytes, 670 lines download raw bytes

1/**
2 * Stellar
3 * Stellar is star rating system helps you rate and like articles on a website and keep track of results.
4 * Exclusively on https://1.envato.market/stellar
5 *
6 * @encoding        UTF-8
7 * @version         2.1.4
8 * @copyright       (C) 2018 - 2021 Merkulove ( https://merkulov.design/ ). All rights reserved.
9 * @license         Envato License https://1.envato.market/KYbje
10 * @contributors    Nemirovskiy Vitaliy ([email protected]), Dmitry Merkulov ([email protected])
11 * @support         [email protected]
12 **/
13
14( function () {
15
16    "use strict";
17
18    document.addEventListener( "DOMContentLoaded", function() {
19
20        /** If there is no Stellar on this page then exit. */
21        if ( document.querySelectorAll( '.mdp-stellar-box' ).length < 1 ) { return; }
22
23        /** Get WordPress post ID */
24        const id = document.querySelector('.mdp-stellar-box').id.replace('mdp-stellar-', '' ); // Page/Post id
25
26        /** Flag to identify users voting for the first time. */
27        let fNew = 1;
28
29        /** Previous values of the user's stellar. */
30        let stellarData = prepareStellarData();
31
32        // noinspection JSUnresolvedVariable
33        /** Data from WP: ajax url and timestamp of last reset. */
34        let wpData = window.mdpStellar;
35
36        /** Remove all stellarData if they was created before last reset. */
37        // noinspection JSUnresolvedVariable
38        if ( wpData.reset_timestamp !== undefined) {
39
40            // noinspection JSUnresolvedVariable
41            if ( stellarData.timestamp < wpData.reset_timestamp ) {
42
43                /** Recreate stellarData, like for first visit. */
44                stellarData = {};
45                stellarData.guid = GetGUID(); // Mark User with GUID.
46                stellarData.timestamp = Math.floor( Date.now() / 1000 );
47
48                /** Remember stellarData in Local Storage. */
49                window.localStorage.setItem( 'mdpLocalStellarData', JSON.stringify( stellarData ) );
50                window.sessionStorage.setItem( 'mdpSessionStellarData', JSON.stringify( stellarData ) );
51            }
52
53        }
54
55        /** Find all Stellar boxes */
56        const stellarBox = document.querySelectorAll( '.mdp-stellar-box' );
57
58        /** Get data from the Local Storage and Session Storage */
59        let stellarDataLS = JSON.parse( window.localStorage.getItem( "mdpLocalStellarData" ) );
60        let stellarDataSS = JSON.parse( window.sessionStorage.getItem( "mdpSessionStellarData" ) );
61
62        /**
63         * Pseudo GUID. We use unique user id to identify previously voted users.
64         *
65         * @returns {String}
66         **/
67        function GetGUID() {
68
69            // noinspection SpellCheckingInspection
70            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
71
72                const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8); // jshint ignore:line
73                return v.toString(16);
74
75            } );
76
77        }
78
79        /**
80         * Prepare stellarData object
81         * @return {any}
82         */
83        function prepareStellarData() {
84
85            /**  Read stellarData from Local Storage. */
86            let mdpLocalStellarData = JSON.parse( window.localStorage.getItem( 'mdpLocalStellarData' ) );
87
88            /** Set LocalStorage and SessionStorage */
89            if ( mdpLocalStellarData === null ) {
90                /** We generate a key once for the entire session. */
91                mdpLocalStellarData = {};
92                mdpLocalStellarData.guid = GetGUID();
93
94                /** Remember stellarData in Local Storage. */
95                window.localStorage.setItem('mdpLocalStellarData', JSON.stringify( mdpLocalStellarData ) );
96                window.sessionStorage.setItem('mdpSessionStellarData', JSON.stringify( mdpLocalStellarData ) );
97            }
98
99            return mdpLocalStellarData;
100
101        }
102
103        /**
104         * Hover handler for each <i> element
105         *
106         * @param event
107         */
108        function stellarHover( event ) {
109
110            if ( event.target.closest( 'i' ) !== null ) {
111
112                const targetI = event.target.closest( 'i' ); //eventAR
113                const iconsBox = targetI.closest( '.mdp-box-icon' );
114                const icons = iconsBox.getElementsByTagName( 'i' ); //eventLinks
115                const count = targetI.getAttribute( 'data-id' );
116
117                // Add active class for each <i> element
118                if ( icons.length > 0 ) {
119                    for( let i = 0; i < count; i++ ){
120                        icons[ i ].classList.add( 'mdp-box-list-hover' );
121                    }
122                }
123
124                // Add hover class for target <i>
125                targetI.classList.remove( 'mdp-stellar-hover' );
126
127                // Update the rating valuation if it exist on the page
128                if ( iconsBox.querySelector( '.mdp-rating-res' ) !== null ) {
129                    iconsBox.querySelector( '.mdp-rating-res' ).innerText = count;
130                }
131
132                // Add and place the rating valuation tooltip to the hovered element if exist
133                if ( iconsBox.querySelector( '.mdp-stellar-tooltip' ) !== null ) {
134
135                    const ratingTooltip = iconsBox.querySelector( '.mdp-stellar-tooltip' );
136                    const targetRect = targetI.getBoundingClientRect();
137                    const parentRect = iconsBox.getBoundingClientRect();
138
139                    ratingTooltip.classList.add('mdp-stellar-tooltip-show');
140                    ratingTooltip.style.bottom = targetRect.top - parentRect.top + targetRect.height + 16 + 4 + 'px';
141                    ratingTooltip.style.left = targetRect.left - parentRect.left  + ( targetRect.width - ratingTooltip.getBoundingClientRect().width ) / 2 + 'px';
142
143                }
144
145            }
146
147        }
148
149        /**
150         * Ending Rating Bar Interaction Handler
151         * @param event - On mouseout event
152         * @return {boolean}
153         */
154        function endInteraction( event ) {
155
156            const leaveTo = event.toElement || event.relatedTarget;
157            const target = event.target;
158
159            // Set <i> to default state if interaction is ended
160            if ( event.target.closest( 'i' ) !== null ) {
161                const targetI = event.target.closest( 'i' ); //e.target;
162                const iconsBox = targetI.closest( '.mdp-box-icon' );
163                const icons = iconsBox.getElementsByTagName( 'i' );
164                const count = targetI.getAttribute( 'data-id' );
165
166                // Remove hover class for target <i>
167                targetI.classList.remove( 'mdp-stellar-hover' );
168
169                // Remove active class for each <i> element
170                if ( icons.length > 0 ) {
171                    for( let i = 0; i < icons.length; i++ ){
172                        icons[ i ].classList.remove( 'mdp-box-list-hover' );
173                    }
174                }
175
176                // Update the rating valuation if it exist on the page
177                if ( iconsBox.querySelector( '.mdp-rating-res' ) !== null ) {
178
179                    if ( iconsBox.querySelector( '.mdp-stellar-tooltip' ) !== null ) {
180                        // Sets the rating valuation data = data-id of leaved icon for tooltip
181                        iconsBox.querySelector( '.mdp-rating-res' ).innerText = count;
182                    } else {
183                        // Sets 0 in other cases
184                        iconsBox.querySelector( '.mdp-rating-res' ).innerText = 0;
185                    }
186
187                }
188
189            }
190
191            // Hide tooltip is interaction is completely finished
192            if ( leaveTo !== null ) { //Right click
193
194                if ( leaveTo.querySelector( '.mdp-box-icon' ) !== null || target.classList.contains( 'mdp-stellar-tooltip' ) || target.tagName === 'SPAN' ) {
195
196                    if ( document.querySelector( '.mdp-stellar-tooltip-show' ) !== null ) {
197                        document.querySelector( '.mdp-stellar-tooltip-show' ).classList.remove('mdp-stellar-tooltip-show');
198                    }
199
200                }
201
202            }
203
204        }
205
206        /**
207         * Rating clicking handler
208         * Add scalable bubbles effect for clicked <i>
209         *
210         * @param target - Click Event target
211         */
212        function ratingClickEffect( target ) {
213
214            // Create bubble svg
215            const clickBubbles = document.createElementNS("http://www.w3.org/2000/svg", 'svg');
216            clickBubbles.classList.add( 'mdp-stellar-bubbles' );
217            clickBubbles.innerHTML = '<g id="grp7" opacity="0" transform="translate(7 6)">\n    ' +
218            '<circle class="oval1" cx="2" cy="6" r="6"/><circle class="oval2" cx="5" cy="2" r="6"/>\n' +
219            '</g>\n<g id="grp6" opacity="0" transform="translate(0 28)">\n    ' +
220            '<circle class="oval1" cx="2" cy="7" r="5"/><circle class="oval2" cx="3" cy="2" r="7"/>\n' +
221            '</g>\n<g id="grp3" opacity="0" transform="translate(52 28)">\n    ' +
222            '<circle class="oval2" cx="2" cy="7" r="6"/><circle class="oval1" cx="4" cy="2" r="6"/>\n' +
223            '</g>\n<g id="grp2" opacity="0" transform="translate(44 6)">\n    ' +
224            '<circle class="oval2" cx="5" cy="6" r="5"/><circle class="oval1" cx="2" cy="2" r="7"/>\n' +
225            '</g>\n<g id="grp5" opacity="0" transform="translate(14 50)">\n    ' +
226            '<circle class="oval1" cx="6" cy="5" r="6"/><circle class="oval2" cx="2" cy="2" r="6"/>\n' +
227            '</g>\n<g id="grp4" opacity="0" transform="translate(35 50)">\n    ' +
228            '<circle class="oval1" cx="6" cy="5" r="5"/><circle class="oval2" cx="2" cy="2" r="7"/>\n' +
229            '</g>\n<g id="grp1" opacity="0" transform="translate(24 0)">\n    ' +
230            '<circle class="oval1" cx="2" cy="6" r="5"/><circle class="oval2" cx="5" cy="2" r="7"/>\n' +
231            '</g>';
232
233            // Set scale for click effect
234            if ( typeof getComputedStyle( target ) === 'object' ) {
235                if ( getComputedStyle( target )['font-size'].length > 0 ) {
236                    clickBubbles.style.top = '-' + (getComputedStyle( target ).paddingLeft.replace('px','') - 1) + 'px';
237                    clickBubbles.style.transform = 'scale(' + target.offsetWidth / 60 + ')';
238                }
239            }
240
241            // Append SVG bubble effects
242            target.appendChild( clickBubbles );
243
244            // Display click effects
245            setTimeout( function () {
246                target.classList.add( 'mdp-stellar-rated' );
247                clickBubbles.classList.add( 'mdp-stellar-click' );
248            }, 50 );
249
250            // Remove click effects
251            setTimeout( function () {
252                target.classList.remove( 'mdp-stellar-rated' );
253                clickBubbles.remove();
254            }, 1000 );
255
256        }
257
258        /**
259         * Create AJAX call
260         *
261         * @param {object} data
262         * @return
263         **/
264        function stellarRequest(data) {
265
266            /** AJAX call */
267            const xhttp = new XMLHttpRequest();
268            let stellarDataLS = JSON.parse( window.localStorage.getItem("mdpLocalStellarData") );
269
270            xhttp.open('POST', wpData.url + '?action=process_stellar', true);
271            xhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
272            xhttp.send(encodeURI('stellar_id=' + data.stellar_id + '&rating=' + data.rating  + '&length=' + data.length + '&guid=' + stellarDataLS.guid + '&new_stellar=' + data.new_stellar));
273
274            xhttp.onload = function () {
275
276                // Request failed
277                if ( ! xhttp.status ) {
278
279                    console.warn('Request failed! See below:');
280                    console.error( data );
281
282                }
283
284                // Request error
285                else if ( xhttp.status !== 200 ) {
286
287                    console.error('Request error.  Returned status of ' + xhttp.status);
288
289                }
290
291                // Request success
292                else if ( xhttp.status === 200 ) {
293
294                    fNew = 0;
295                    let answer = JSON.parse( xhttp.response );
296
297                    /** Message about the result of sending data. */
298                    if ( answer.message !== undefined ) {
299                        console.warn( answer.message );
300                    }
301
302                }
303
304            };
305
306        }
307
308        /**
309         * Request page rank
310         * @param data
311         */
312        function stellarPageRating(data) {
313
314            /** AJAX call */
315            const xhttp = new XMLHttpRequest();
316            xhttp.open('POST', wpData.url + '?action=stellar_page_rating', true);
317            xhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
318            xhttp.send(encodeURI('page_rating=1'+ '&stellar_id=' + data.stellar_id ));
319
320            xhttp.onload = function () {
321
322                // Request failed
323                if ( ! xhttp.status ) {
324                    console.warn('Request failed! See below:');
325                }
326
327                // Request error
328                else if ( xhttp.status !== 200 ) {
329                    console.error('Request error.  Returned status of ' + xhttp.status);
330                }
331
332                // Request success
333                else if ( xhttp.status === 200 ) {
334
335                    let answer = JSON.parse( xhttp.response );
336
337                    /** After first like, one time update counter. */
338                    if ( document.getElementsByClassName( 'mdp-stellar-results' ).length > 0 ) {
339
340                        const stellarResult = document.getElementsByClassName( 'mdp-stellar-results' );
341                        for ( let i = 0; i < stellarResult.length; i++ ) {
342                            stellarResult[ i ].innerText = answer.page_rating;
343                        }
344
345                    }
346
347                }
348            };
349        }
350
351        /**
352         * We call the function when you click on the icon.
353         * @param event
354         */
355        function stellarClick( event ) {
356
357            if ( event.target.closest( 'i' ) !== null ) {
358
359                const targetI = event.target.closest('i'); //eventTarget
360                const iconsBox = targetI.closest('.mdp-box-icon');
361                const icons = iconsBox.getElementsByTagName('i');
362                const rating = targetI.getAttribute('data-id');
363                const maxRating = iconsBox.getAttribute('data-rating'); //count_rating
364
365                // Send async request
366                const data = { 'stellar_id': id, 'rating': rating, 'length': wpData.length, 'new_stellar': fNew };
367                stellarRequest( data );
368
369                // Request Page Rank
370                setTimeout( () => { stellarPageRating(data); },200 );
371
372                // Save data to local storage
373                stellarData['rating_' + id] = rating;
374                stellarData.timestamp = Math.floor( Date.now() / 1000 );
375                stellarData.best_rating = maxRating;
376                window.localStorage.setItem( 'mdpLocalStellarData', JSON.stringify( stellarData ) );
377                window.sessionStorage.setItem( 'mdpSessionStellarData', JSON.stringify( stellarData ) );
378
379                // Remove and add mdp-stellar-active class for <i>.
380                if ( icons.length > 0 ) {
381
382                    // Remove old voting active class
383                    for( let i = 0; i < icons.length; i++ ){
384                        icons[ i ].classList.remove( 'mdp-stellar-active' );
385                        icons[ i ].querySelector( 'div' ).style.width = '0';
386                    }
387
388                    // Add new voting active class
389                    for( let i = 0; i < rating; i++ ){
390                        icons[ i ].classList.add( 'mdp-stellar-active' );
391                    }
392
393                }
394
395                // Update 'Your page rank' data
396                iconsBox.parentNode.querySelector( '.mdp-stellar-your-rating span' ).innerHTML = rating;
397
398                // Click effect
399                ratingClickEffect( targetI );
400
401                // Update the rating valuation if it exist on the page
402                if ( iconsBox.querySelector( '.mdp-rating-res' ) !== null ) {
403                    iconsBox.querySelector( '.mdp-rating-res' ).innerText = rating;
404                }
405
406        
406    }
407
408        }
409
410        /**
411         * Display results for already voted users.
412         *
413         * @param $wrapper - Stellar wrapper
414         */
415        function stellarResults( $wrapper ) {
416
417            if ( JSON.parse( window.localStorage.getItem( "mdpLocalStellarData" ) ) === null ){ return; }
418
419            let stellarDataLS = JSON.parse( window.localStorage.getItem( "mdpLocalStellarData" ) );
420            const icons = $wrapper.getElementsByTagName('i');
421            const maxRating = icons.length;
422            let rating = 0;
423
424            // Recalculate and determine the number of painted icons
425            if ( stellarData['rating_' + id] !== undefined ) {
426
427                if ( maxRating === stellarDataLS.best_rating ) {
428                    rating = stellarData['rating_' + id];
429                } else {
430                    rating = Math.round((stellarData['rating_' + id] / stellarDataLS.best_rating) * maxRating);
431                }
432
433            }
434
435            // Set rating data-attribute to User rating of
436            if ( rating !== 0 && $wrapper.getAttribute( 'data-secrecy' ) === 'off' ) {
437                $wrapper.setAttribute( 'data-rating', rating );
438            }
439
440            // Fill the icons
441            stellarRating( $wrapper );
442
443            // Update the rating valuation if it exist on the page
444            if ( $wrapper.querySelector( '.mdp-rating-res' ) !== null ) {
445                $wrapper.querySelector( '.mdp-rating-res' ).innerText = rating;
446            }
447
448
449        }
450
451        /**
452         * Run all Stellar events
453         *
454         * @param $wrapper - Stellar wrapper container
455         */
456        function stellarEvents( $wrapper ) {
457
458            const box = $wrapper.querySelector( '.mdp-box-icon' );
459
460            /** UnBind and Bind the End of interaction with the icons bar */
461            box.removeEventListener( 'mouseout', endInteraction );
462            box.addEventListener( 'mouseout', endInteraction );
463
464            /** Find all Stellar Icons in single Stellar Box */
465            const stellarIcon = box.getElementsByTagName( 'i' );
466            if ( stellarIcon.length > 0 ) {
467
468                for( let i = 0; i < stellarIcon.length; i++ ) {
469
470                    /** UnBind and Bind the hover event listener for each <i> */
471                    stellarIcon[i].removeEventListener( 'mouseover', stellarHover );
472                    stellarIcon[i].addEventListener( 'mouseover', stellarHover );
473
474                    /** UnBind and Bind the click event listener for each <i> */
475                    stellarIcon[i].removeEventListener( 'click', stellarClick );
476                    stellarIcon[i].addEventListener( 'click', stellarClick );
477
478                }
479
480            }
481
482        }
483
484        /**
485         * Display and hide message for unable voting
486         *
487         * @param event - Click event
488         */
489        function stellarMessage( event ) {
490
491            const box = event.target.closest( '.mdp-box-icon' );
492            const newMessage = document.createElement( 'span' );
493
494            /** Add message */
495            newMessage.classList.add( 'mdp-stellar-message' );
496            newMessage.innerText = wpData.limitText;
497            box.appendChild( newMessage );
498
499            /** Hide message */
500            setTimeout( function () {
501                newMessage.remove();
502            }, 2000 );
503
504        }
505
506        /**
507         * Returns rating value in rounded format
508         *
509         * @param $wrapper - Stellar parent element
510         * @return {number|*}
511         */
512        function getRoundRating( $wrapper ) {
513
514            const round = $wrapper.getAttribute( 'data-round' );
515            const rating = $wrapper.getAttribute( 'data-rating' );
516
517            if ( 'up' === round ) { return Math.ceil( rating ); }
518            if ( 'no' === round ) { return rating; }
519            if ( 'down' === round ) { return Math.floor( rating ); }
520
521        }
522
523        /**
524         * Fill the icons
525         *
526         * @param $wrapper - Stellar parent element
527         */
528        function stellarRating( $wrapper ) {
529
530            if ( $wrapper.getElementsByTagName( 'i' ).length < 1 ) { return; }
531
532            const secrecy = $wrapper.getAttribute( 'data-secrecy' ) !== 'on'; // true = hide voting results
533            const voted = stellarData['rating_' + id] !== undefined;
534
535            const icons = $wrapper.getElementsByTagName( 'i' );
536            for( let i = 0; i < icons.length; i++ ){
537
538                const activeSVG = icons[ i ].querySelector( 'div' );
539                const decimals = getRoundRating( $wrapper ) - Math.floor( $wrapper.getAttribute( 'data-rating' ) );
540
541                // Fill or empty stars
542                activeSVG.style.width = i < getRoundRating( $wrapper ) ? '100%' : '0';
543
544                // Half stars
545                if ( decimals !== 0 && i === Math.floor( $wrapper.getAttribute( 'data-rating' ) ) ) { activeSVG.style.width = 100 * decimals + '%'; }
546
547                // Hide Empty stars id secrecy activated and no rating value
548                if ( secrecy && !voted ) {
549                    activeSVG.style.width = '0';
550                }
551
552            }
553
554        }
555
556        /**
557         * Displays 'Your rating is' text message and rating
558         *
559         * @param $wrapper - Stellar parent element
560         */
561        function yourRatingMessage( $wrapper ) {
562
563            if ( $wrapper.getAttribute( 'data-your-rating' ) !== 'text' ) { return; } // Exit if message set to hide
564            if ( stellarDataLS['rating_' + id] === undefined ) { return; } // Exit if no votes in Local Storage
565
566            $wrapper.querySelector( '.mdp-stellar-your-rating' ).classList.remove( 'mdp-hidden' );
567            $wrapper.querySelector( '.mdp-stellar-your-rating span' ).innerHTML += ' ' + stellarDataLS[ 'rating_' + id ];
568
569        }
570
571        /**
572         * Behavior of Stellar regarding to Local Storage and Session Storage
573         *
574         * @param $wrapper - Stellar parent element
575         */
576        function stellarBehavior( $wrapper ) {
577
578            const stellarIconBoxes = $wrapper.querySelector( '.mdp-box-icon' );
579
580            /** Already has record in Local Storage */
581            if( stellarDataLS['rating_' + id] !== undefined ) {
582
583                if ( stellarDataSS === null ) {
584
585                    /** Add class and message for unable rating */
586                    stellarIconBoxes.classList.add( 'mdp-stellar-unable' );
587                    stellarIconBoxes.addEventListener( 'click', stellarMessage );
588
589                } else {
590
591                    /** Voted in this session */
592                    fNew = 0;
593                    stellarEvents( $wrapper );
594
595                }
596
597            } else {
598
599                /** No record in Local Storage */
600                stellarEvents( $wrapper );
601
602            }
603
604        }
605
606        /** Run for all Stellar Boxes */
607        for ( let i = 0; i < stellarBox.length; i++ ) {
608
609            const $stellarWrapper = stellarBox[ i ]; // Stellar Wrapper
610
611            if ( $stellarWrapper.getAttribute( 'data-your-rating' ) !== 'stars' ) { // Hide user voting result 'hide' and 'text'
612
613                stellarRating( $stellarWrapper );
614                yourRatingMessage( $stellarWrapper );
615                if ( wpData.session === 'on' ) { stellarBehavior( $stellarWrapper ); } else { stellarEvents( $stellarWrapper ); }
616
617            } else { // Show user voting result as stars
618
619                stellarResults( $stellarWrapper );
620                if ( wpData.session === 'on' ) { stellarBehavior( $stellarWrapper ); } else { stellarEvents( $stellarWrapper ); }
621
622            }
623
624        }
625
626        /** When you reload the page, the likes are not erased with the mouse. */
627        sessionStorage.setItem( "is_reloaded", true );
628
629        /** Check multiple browser tabs are open */
630        const watchTabs = function( event ) {
631
632            /** Identify the event that occurred. */
633            if ( event.key === 'mdpLocalStellarData' ) {
634
635                /** Get data from the Local Storage. */
636                let stellarDataLS = JSON.parse( window.localStorage.getItem( "mdpLocalStellarData" ) );
637
638                /** We remove the asset class from the icons. */
639                for ( let i = 0; i < stellarDataLS.best_rating; i++ ) {
640                    stellarBox[ 0 ].getElementsByTagName( 'i' )[i].classList.remove( 'mdp-stellar-active' );
641                }
642
643                /** Add an asset class to the icons that have been selected. */
644                for ( let i = 0; i < parseInt( stellarDataLS['rating_' + id] ); i++ ) {
645                    /** Set the flag of the current session. */
646                    fNew = 0;
647
648                    stellarBox[ 0 ].getElementsByTagName( 'i' )[i].classList.add( 'mdp-stellar-active' );
649                }
650
651                const data = {
652                    'stellar_id': id,
653                    'rating': stellarDataLS['rating_' + id],
654                    'length': wpData.length,
655                    'new_stellar': fNew
656                };
657
658                /** Request Page Rank. */
659                setTimeout( () => {
660                    stellarPageRating( data );
661                }, 200 );
662
663            }
664
665        };
666        window.addEventListener( 'storage', watchTabs );
667
668    } );
669
670} () );

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.