PageSourceSearch

https://cdnn.1prime.ru//js/pages/article.js

js 1prime.ru collected 2026-10-01 08:35:55 UTC 31,405 bytes, 601 lines download raw bytes

1"use strict";
2
3$(function() {
4
5
6    startArticleJS( $('.endless__item'), 'first' );
7
8
9
10    window.endlessScroll = {
11        init : function(){
12            var _this = this;
13
14            _this.firstId = window.endlessScrollFirst;              // id первой статьи
15            _this.uploadUrl = window.endlessScrollUrl;              // урл откуда догружать
16            _this.autofillAlgorithm = window.endlessScrollAlgorithm;// алгоритм с помощью которого был составлен лист автозаполнния
17            _this.uploadQueue = window.endlessScrollQueue;          // массив / очередь статей для догрузки
18
19            _this.$endless = $( '#endless' );                       // основной элемент
20
21            if ( $( 'body' ).data( 'endless-off' ) == 1 ) {
22                console.log( "EndlessScroll id disabled in settings");
23                return false;
24            } else  if ( !_this.uploadUrl || !_this.uploadQueue.length > 0 || !_this.$endless.length > 0 ) {
25                console.log( "Can't start endlessScroll: UploadUrl = ",_this.uploadUrl," QueueLength = ",_this.uploadQueue," EndlessLength = ",_this.$endless);
26                return false;
27            }
28
29            if ( !window.EVENTSTACK ) window.EVENTSTACK = [];
30
31            // классы элементов
32            _this.class = {
33                endlessItem :           '.endless__item',           // класс блоков оберток статей
34                endlessItemContent :    '.endless__item-content',   // класс блоков для позиционирования контента статьи
35                endlessItemHide :       '.endless__item-hide',      // класс блоков затемнения
36                articleAhchor :         '.article__anchor',         // класс якорей для отслеживания прокрутки статьи
37                modFollow :             'm-follow',                 // класс модификатор что статья следующая (без точки!!!)
38                modActive :             'm-active',                 // класс модификатор активного элемента (без точки!!!)
39                modFollowFixed :        'm-follow-fixed'            // класс модификатор последующие элементы фиксированны (без точки!!!)
40            };
41
42            _this.metaAnalyticsRemove = [ 'title_ver', 'title_alg', 'rcmd_alg', 'rcmd_id' ];    // массив для идентификации мет под удаление при переходе между статьями
43
44            _this.uploadActive = 0;                                 // номер активного элемента для догрузки из массива
45            _this.uploadCount = _this.uploadQueue.length;           // общее кол-во элементов для догрузки
46            _this.upload = false;                                   // флаг что идет догрузка
47            _this.uploadErrorCount = 0;                             // счетчик ошибочных попыток загрузки статьи
48
49            // sets
50            _this.$items = false;                                   // набор активных элементов
51            _this.$activeItem = false;                              // активный элемент
52            _this.$followItems = false;                             // набор следующих за активным элементов
53            _this.$followItemsContent = false;                      // набор контентов следующих за активным элементов
54            _this.updateSets();
55
56            _this.urlParams = ( _this.$endless.data( 'scroll-params' ) && _this.$endless.data( 'scroll-params' ) != '' ) ? _this.$endless.data( 'scroll-params' ) : '';
57
58            // switching position
59            _this.switchTop = 0;
60            _this.updateSwitchTop();                                // вычисляем _this.switchTop
61
62            // viewport
63            _this.clientHeight = this.getClientHeigth();
64
65            // support IntersectionObserver
66            _this.supportObserver = !!window.IntersectionObserver ? true : false;
67
68            // События при скроле, если есть обсервер, то срабатывает только при пересечении области экрана элементом статьи
69            if ( _this.supportObserver ) {
70                _this.endlessObserver = new IntersectionObserver(
71                    //console.log('------- observerCallback onScroll -------');
72                    function( entries ){
73                        _this.onScroll()
74                    },{
75                        'rootMargin': '-46px 0px 0px 0px'
76                    }
77                );
78                $.each( $( _this.class.endlessItem, _this.$endless ), function( i, v ){
79                    _this.endlessObserver.observe( v );
80                } )
81            } else {
82                $( window ).scroll(function(){
83                    //console.log('------- onScroll -------');
84                    _this.onScroll();
85                });
86            }
87
88            $( window ).resize(function(){
89                _this.onResize();
90            });
91
92            $( window ).resize();
93
94            /* догрузка второй статьи при прокрутке более чем на 50px */
95            $( window ).bind( 'scroll.article_first_upload', function(){
96                if ( $( window ).scrollTop() > 50 ){
97                    _this.checkUploadItem();  // догружаем следующую статью
98                    $( window ).unbind( 'scroll.article_first_upload' );
99                }
100            });
101
102        },
103
104        onScroll: function(){
105            //console.log( "=== endlessScroll ===  onScroll  ===")
106            this.checkChangeItem();                                 // проверка смены элемента
107            this.updateSwitchTop();
108        },
109
110        onResize: function(){
111            this.clientHeight = this.getClientHeigth();
112            this.updateSwitchTop();
113        },
114
115        checkChangeItem : function(){
116
117            var _this = this,
118                activeTop = _this.$activeItem.offset().top - $( window ).scrollTop(),
119                activeBottom = activeTop + _this.$activeItem.outerHeight() - 40;
120
121            // console.log('>>>>>>> activeTop = '+activeTop+' - activeBottom = '+activeBottom+'>>> _this.switchTop = '+_this.switchTop+'>>> _this.$followItems.length = '+_this.$followItems.length);
122
123            /* переключение на следующую статью */
124            if ( activeBottom <= _this.switchTop && _this.$followItems.length ) {
125
126                $( _this.$followItems[0] ).removeClass( _this.class.modFollow )          // переводим в активный первый из follow
127                _this.changeItemEvents( true );
128
129                // console.log('>>>>>>> _this.$items.length = '+_this.$items.length+' _this.uploadActive = '+_this.uploadActive);
130
131                // догружаем слудующую статью если кол-во не follow больше чем индекс загружаемой
132                if ( _this.$items.length > _this.uploadActive ) _this.checkUploadItem();
133
134                // Работа с эвентами
135                var adFoxEventUrl = ( _this.$activeItem.data( 'event-url' ) && _this.$activeItem.data( 'event-url' ) != '' ) ? _this.$activeItem.data( 'event-url' ) : false;
136                // console.log( 'adFoxEventUrl = '+adFoxEventUrl);
137                // вставка ивента для adFox
138                if ( adFoxEventUrl !== false ){
139                    // console.log( '>>> counter >>> event-url ', adFoxEventUrl  );
140                    _this.$activeItem
141                        .removeAttr( 'data-event-url' )
142                        .data( 'event-url', '' )
143                        .find( '.article' )
144                        .append( '<img class="article__event-img" data-event="adFoxEvent" src="' + adFoxEventUrl + '" alt=""/>' );
145                }
146
147            }
148
149            /* переключение на предыдущую статью */
150            if ( activeTop > _this.switchTop && _this.$items.length > 1 ){
151                _this.$activeItem.addClass( _this.class.modFollow );                    // помечаем последний активный в follow
152                _this.changeItemEvents();
153                // _this.updateArticleData( _this.$activeItem );
154            }
155
156        },
157
158        changeItemEvents: function( stepForward ){
159            var _this = this;
160
161            _this.updateSets();                                             // обновляем наборы
162            _this.changeProject( _this.$activeItem.data( 'project' ) );     // обновляем проект
163            _this.changeHeader( _this.$activeItem );                        // меняем header
164
165            // подменяем данные о статье на странице
166            history.replaceState( null, _this.$activeItem.data( 'title' ), location.origin + _this.$activeItem.data( 'url' ) + ( ( _this.urlParam
166s && _this.urlParams != '' ) ? ( '?' + _this.urlParams ) : '' ) );
167
168            // отправляем аналитику, подменяем meta и т.п.
169            // второй параметр true проверка на отправку аналитики при первом переходе на следующий материал
170            _this.updateArticleData( _this.$activeItem, stepForward )
171
172        },
173
174        changeProject: function( project ){
175
176        },
177
178        changeHeader: function( item ) {
179            $( 'body' ).removeClass( 'm-header-short m-header-share' );
180            if ( item.data( 'header-type' ) ) {
181                $( 'body' ).addClass( 'm-header-' + item.data( 'header-type' ) );
182                $( '.share.m-header' ).attr({
183                    'data-url': item.data('full-url'),
184                    'data-title': item.data('title'),
185                    'data-id': item.data('id')
186                });
187            }
188        },
189
190        updateArticleData: function( $item, stepForward ){
191
192            var _this = this;
193
194            document.title = $item.data('head-title');
195
196            $('meta[property="og:title"]').attr('content', $item.data('og-title'));
197            $('meta[property="og:description"]').attr('content', $item.data('og-description'));
198            $('meta[property="og:image"]').attr('content', $item.data('og-image'));
199            $('meta[property="og:url"]').attr('content', $item.data('full-url'));
200
201            let $publishedTime = $('meta[property="article:published_time"]'),
202                publishedTime = $item.data('published-time'),
203                $modifiedTime = $('meta[property="article:modified_time"]'),
204                modifiedTime = $item.data('modified-time');
205            $publishedTime.attr( 'content', publishedTime );
206            if ( modifiedTime > publishedTime ) {
207                if ( $modifiedTime.length ){
208                    $modifiedTime.attr('content', modifiedTime )
209                } else {
210                    $publishedTime.after('<meta property="article:modified_time" content="' + modifiedTime + '"/>')
211                }
212            } else {
213                $modifiedTime.remove();
214            }
215
216            $('meta[name="keywords"]').attr('content', $item.data('keywords'));
217
218            $('meta[property="article:author"]').attr('content', $item.data('author'));
219
220            $('meta[name="analytics:title"]').attr('content', $item.data('title'));
221            $('meta[name="analytics:keyw"]').attr('content', $item.data('analytics-keyw'));
222            $('meta[name="analytics:rubric"]').attr('content', $item.data('analytics-rubric'));
223            $('meta[name="analytics:tags"]').attr('content', $item.data('analytics-tags'));
224            $('meta[name="analytics:site_domain"]').attr('content', $item.data('domain') );
225            $('meta[name="analytics:article_id"]').attr('content', $item.data('id'));
226            $('meta[name="analytics:url"]').attr('content', $item.data('full-url'));
227            $('meta[name="analytics:p_ts"]').attr('content', $item.data('pts'));
228            $('meta[name="analytics:author"]').attr('content', ( ($item.data('author')).trim() != '' ? $item.data('author') : $item.data('author-korr') ) );
229            $('meta[name="analytics:isscroll"]').attr('content', $item.data('is-scroll'));
230
231            /* удаляем мета аналитики т.к. они нужны только для первой статьи при первой загрузке страницы */
232            $.each( this.metaAnalyticsRemove, function( i, v ){
233                $('meta[name="analytics:'+v+'"]').remove();
234            });
235
236            if ( GLOBAL && GLOBAL.article ) {
237                GLOBAL.article.id = $item.data('id');
238                GLOBAL.article.show = !!$item.data('article-show');
239            }
240
241            window.dataLayer = window.dataLayer || [];
242            dataLayer.push(
243                {
244                    'event' : 'infinite_pageview',
245                    'page_title' : $item.data('title'),
246                    'page_path' : $item.data('url'),
247                    'page_domain' : $item.data('domain'),
248                    'page_url' : $item.data('full-url'),
249                    'page_tags' :  $item.data('analytics-tags'),
250                    'page_rubric' : $item.data('analytics-rubric'),
251                    'page_number' :  $item.data('endless'),
252                    'article_id'  :  $item.data('id'),
253                    'article_length' : $item.data('text-length')
254                }
255            );
256
257            if ( stepForward && !$item.data( 'event-once' ) ){
258
259                // Событие piwil_log
260                piwik_log( $item.data( 'head-title' ), '1prime', 'https://a.ria.ru/counter' );
261
262                // Событие: Прокрутка до каждой статьи в инфинити-скролл
263                window.EVENTSTACK.push([ 'scroll', 'article_infinity', {
264                    article_id: $item.data( 'id' ),
265                    source_aid: _this.firstId,
266                    algorithm: _this.autofillAlgorithm,
267                    textlength: $item.data( 'text-length' )
268                }]);
269
270                this.countersStepForwardOnce( $item );
271
272                // добавление флага
273                $item.attr( 'data-event-once', true )
274
275            }
276
277        },
278
279        checkUploadItem: function(){
280            /* догрузка при смене статьи на последню являющуюся последней */
281            if ( this.uploadActive < this.uploadCount && !this.upload ) {
282                this.upload = true;
283                this.uploadItem();
284            }
285        },
286
287        uploadItem : function(){
288            var _this = this;
289            if ( _this.uploadQueue[ _this.uploadActive ] == 'banner' ) {
290                //console.log('_this.uploadActive = '+(_this.uploadActive+1));
291                var chooseId = $( '.endless__choose-position-' + ( _this.uploadActive + 1 ) + ' div[ data-endless-id ]' ).data('endless-id');
292                //console.log('chooseId = '+chooseId);
293                if ( typeof chooseId == 'number' && chooseId > 0 && $.inArray( chooseId, _this.uploadQueue ) < 0 && chooseId != _this.firstId ){
294                    _this.uploadQueue[ _this.uploadActive ] = chooseId;
295                } else {
296                    _this.uploadQueue.splice( _this.uploadActive, 1 );
297                    _this.uploadCount = _this.uploadQueue.length;
298                    $( '.endless__choose div[ data-endless-id="' + chooseId + '"]' ).remove();
299                }
300                _this.upload = false;
301                _this.checkUploadItem();
302            } else {
303                /* проверка что элемент массива число иначе переходим к следующему элементу */
304                if ( isNaN( Number( this.uploadQueue[ this.uploadActive ] ) ) ){
305                    this.uploadActive++;
306                    this.checkUploadItem();
307                }
308                $.ajax({
309                    url: _this.uploadUrl + _this.uploadQueue[ _this.uploadActive ] + '.html?endless=' + ( _this.uploadActive + 2 ) + ( ( _this.urlParams && _this.urlParams != '' ) ? ( '&' + _this.urlParams ) : '' ),
310                    dataType: 'html',
311                    type: 'GET',
312                    success: function ( data ) {
313                        var $endlessItem = $( data ),
314                            eventUrl = $( '.endless__choose div[ data-endless-id="'+_this.uploadQueue[_this.uploadActive]+'" ]' ).data( 'event-url' );
315                        if ( eventUrl ) $endlessItem.attr( 'data-event-url', eventUrl );
316                        $endlessItem.attr( 'data-endless', ( _this.uploadActive + 2 ) ); // подменяем атрибут из кеша на корректный
317                        _this.$endless.append( $endlessItem );                          // добавляем элемент
318                        _this.uploadActive++;                                           // увеличиваем счетчик элементов для догрузки
319                        _this.updateSets();                                             // обновляем наборы
320                        startArticleJS( $endlessItem.filter( _this.class.endlessItem )  ); // фильр нужен что бы переданный тег <script> не обрабатывался в наборе
321                        _this.upload = false;                                           // меняем флаг
322                        _this.uploadErrorCount = 0;                                     // обнуляем счетчик ошибочных загрузок
323                        //console.log('<<<<<<<<<<< ARTICLE LOADED >>>>>>>>>> next => '+_this.uploadActive+', '+_this.uploadQueue[ _this.uploadActive ]);
324                        /* добавляем отслеживание в observer */
325                        if ( _this.supportObserver ) {
326                            $.each( $endlessItem, function( i, v ){ _this.endlessObserver.observe( v ); })
327                        }
328
329                    },
330                    error: function () {
331                        if (_this.uploadErrorCount < 5) {
332                            _this.uploadErrorCount++;
333                            setTimeout(function () {
334                                _this.uploadItem();
335                            }, 2000);
336                        }
337                    }
338                    /* TODO Доделать - действия при ошибке */
339                });
340            }
341        },
342
343        // Обновление верхнего края для переключения (не работает с обсервером)
344        updateSwitchTop : function(){
345            this.switchTop = $( body ).hasClass( 'm-header-sticked' ) ? $( '#headerSticked' ).height() : 0;
346        },
347
348        // Аналитика вызов счетчиков
349        countersStepForwardOnce : function( $item ){
350
351            let project = $item.data( 'project' ),
352                page = $item.data( 'endless' ),
353                author = $item.data( 'author' ) || '',
354                tags = $item.data( 'analytics-tags' ),
355                referrer = document.referrer,
356                rubric = $item.data( 'analytics-rubric' ),
357                title = $item.data( 'head-title' ),
358                path = $item.data( 'url' ),
359                domain = $item.data( 'domain' );
360
361            let ymPageUrl = domain + path;
362            let ymData = { 'title': title, 'referer': referrer };
363
364            //console.log( ' === countersStepForwardOnce === ymPageUrl = ',ymPageUrl,' ymData = ',ymData)
365            //console.log( ' === countersStepForwardOnce === project = ',project,' page = ',page,' author = ',author,' tags = ',tags,' referrer = ',referrer,' rubric = ',rubric,' title = ',title,' path = ',path,' domain = ',domain)
366
367            if ( Ya && Ya.Metrika ) {
368                let yaCounter12602857 = new Ya.Metrika({id: 12602857});
369                yaCounter12602857.hit(ymPageUrl, ymData);
370            }
371
372            let gtagMain = {'page_path' : path, 'page_title' : title, 'dimension1' : author, 'dimension3' : tags, 'dimension12': referrer, 'dimension20' : page, 'dimension21' : rubric};
373            let gtagSeo = {'page_path': path, 'page_title': title, 'dimension1': author, 'dimension3': tags, 'dimension11': rubric, 'dimension12': referrer, 'dimension17': page};
374            let gtagRsport = {'page_path': path, 'page_title': title, 'dimension1': author, 'dimension4': referrer, 'dimension
3745': tags};
375            let gtagRealty = {'page_path': path, 'page_title': title, 'dimension3': tags, 'dimension12': referrer, 'dimension13': author};
376            let gtagTok = {'page_path': path, 'page_title': title};
377            let gtagRadiosputnik = {'page_path': path, 'page_title': title, 'dimension1': author, 'dimension2': tags, 'dimension3': referrer, 'dimension4': rubric};
378            let gtagOther = {'page_path': path, 'page_title': title, 'dimension1': author, 'dimension3': tags, 'dimension6': referrer};
379
380            // Google (общий):
381            // gtag('config', 'UA-29579933-1', gtagMain );
382            // Google (seo):
383            // gtag('config', 'UA-29579933-96', gtagSeo );
384        },
385
386        updateSets : function() {
387            this.$items = $( this.class.endlessItem + ':not(.' + this.class.modFollow + ')', this.$endless );   // набор не follow элементов
388            this.$followItems = $( this.class.endlessItem + '.' + this.class.modFollow, this.$endless );        // набор follow элементов
389            this.$activeItem = $( this.$items[ this.$items.length - 1 ] );                                      // последний / активный не follow элемент
390            this.$followItemsContent = $( this.class.endlessItemContent, this.$followItems );                   // набор контентов follow элементов
391            // выставляем класс на активный
392            this.$followItems.removeClass( this.class.modActive );
393            this.$items.removeClass( this.class.modActive );
394            this.$activeItem.addClass( this.class.modActive );
395        },
396
397        getClientHeigth : function(){
398            return  Math.max( window.innerHeight || 0, ( document.getElementsByTagName( 'html' )[ 0 ] || {} ).clientHeight || 0 )
399        }
400
401    };
402
403    endlessScroll.init();
404
405});
406
407// Лайк статьи
408$( function() {
409
410    var emoji_loading = false;
411
412    $( 'body' ).on( 'click', '.js-article-like', function( e ) {
413        e.preventDefault();
414        var btn = $( this );
415        $.ajax({
416            url: '/services/article/like/',
417            data: {
418                article_id: btn.data( 'id' )
419            },
420            dataType: 'json'
421        }).done( function( response ) {
422            if ( response.status === 'success' ) {
423                btn.find( 'span' ).text( response.likes );
424            }
425        })
426    });
427
428    // Лайк в статье
429    $( 'body' ).on( 'click', '.article__userbar-emoji .emoji-item', function( e ) {
430        e.preventDefault();
431        var that = $( this );
432        if ( emoji_loading ) {
433            return;
434        }
435        $.ajax({
436            url: '/services/article/add_emoji/',
437            data: {
438                article_id: GLOBAL.article.id,
439                emotion: that.data('type')
440            },
441            dataType: 'json',
442            beforeSend: function() {
443                emoji_loading = true;
444            }
445        }).done(function(response) {
446            if (response.status === 'success') {
447                var items = that.closest('.emoji').find('.emoji-item');
448                items.filter('.m-type-s1').find('.m-value').text(response.s1);
449                items.filter('.m-type-s2').find('.m-value').text(response.s2);
450                items.filter('.m-type-s3').find('.m-value').text(response.s3);
451                items.filter('.m-type-s4').find('.m-value').text(response.s4);
452                items.filter('.m-type-s5').find('.m-value').text(response.s5);
453                items.filter('.m-type-s6').find('.m-value').text(response.s6);
454
455                that.addClass('m-active').siblings().removeClass('m-active')
456            }
457        }).always(function() {
458            emoji_loading = false;
459        })
460    })
461
462    // Открыть попап с эмодзи
463    $('body').on('click', '.best-comments__item-like', function(e) {
464        e.stopPropagation();
465
466        var target = $(this),
467            popover,
468            is_desc = $(document).width() > 925,
469            container = target.closest('.best-comments__item');
470
471        // Закрыть другие
472        $('.best__popper-emoji').remove();
473
474        popover = container.find('.emoji-popper').clone(true);
475        popover.addClass('best__popper-emoji');
476
477        $('body').append(popover);
478
479        // Позиционирование
480        new Popper(target, popover, {
481            placement: is_desc ? 'bottom' : 'right',
482            modifiers: {
483                preventOverflow: {
484                    enabled: true,
485                    padding: 0,
486                    boundariesElement: is_desc ? target.closest('.best-comments__item') : 'window'
487                },
488            }
489        });
490
491        popover.fadeToggle();
492
493        // Клик на любое место закрывает попап
494        $('body').one('click.best__popper-emoji', function() {
495            $('.best__popper-emoji').remove();
496        })
497    });
498
499    var aggrVis  = true;
500    var aggrPush = function( el ){
501        var $elem         = $('.endless__item.m-active').find('.article__aggr[data-visiblepush="no"]');
502
503        if ( $elem.length ) {
504            var elementTop    = $elem.offset().top;
505            var elementBottom = elementTop + $elem.outerHeight();
506
507            var viewportTop = $(window).scrollTop();
508            var viewportBottom = viewportTop + $(window).height() - 105;
509
510            aggrVis = true;
511        }
512
513        if ( (elementBottom > viewportTop) && (elementTop < viewportBottom) && aggrVis ) {
514            aggrVis = false;
515            // ставим кнопкам метку, что их видимость запушена
516            $elem.attr({ 'data-visiblepush' : 'yes' });
517            window.dataLayer = window.dataLayer || [];
518            dataLayer.push({
519                'event'      : 'dl_block_visibility',
520                'block_name' : 'Читать в риа',
521                'page_path'  : window.location.pathname
522            });
523        }
524    };
525
526    if ( $('.endless__item.m-active').find('.article__aggr[data-visiblepush="no"]').length ) {
527        $(window).on('DOMContentLoaded load resize scroll', aggrPush );
528    }
529
530    var $aggrbtn = $('.article__aggr-item');
531    $aggrbtn.on('click', function(e){
532        window.dataLayer = window.dataLayer || [];
533        dataLayer.push({
534            'event'      : 'dl_block_click',
535            'block_name' : 'Читать в риа',
536            'page_path'  : window.location.pathname
537        });
538    });
539});
540
541// tooltip
542$( function() {
543    if (typeof tooltips_data !== 'undefined') {
544        function tooltipClose(el) {
545            el.classList.remove('m-active');
546            el.classList.remove('m-preactive');
547            el.querySelector('.article__tooltip').removeAttribute('style');
548        }
549        var template = '<div class="article__tooltip-bg"><div class="article__tooltip"><div class="article__tooltip-close">'+ria.getIcon('icon-close_small')+'</div><div class="article__tooltip-title"></div><div class="article__tooltip-description"></div></div></div>';
550        document.body.insertAdjacentHTML('beforeend', template);
551        var tooltip_bg = document.querySelector('.article__tooltip-bg');
552        var tooltip_popup = tooltip_bg.querySelector('.article__tooltip')
553        var tooltip_text = tooltip_bg.querySelector('.article__tooltip-description');
554        var window_width = window.innerWidth;
555        document.addEventListener('click', function(e) {
556            var el = e.target;
557            if (el.getAttribute('data-tooltip') == 'true') {
558                window_width = window.innerWidth;
559                var window_height = window.innerHeight;
560                var tooltip_position = el.getBoundingClientRect();
561                var tooltip_data = tooltips_data.find(tooltip => tooltip.id === el.dataset.tooltipId);
562                tooltip_popup.querySelector('.article__tooltip-title').innerHTML = tooltip_data.title;
563                tooltip_popup.querySelector('.article__tooltip-description').innerHTML = tooltip_data.body;
564                if (window_width < 925) {
565                    tooltip_text.setAttribute('style', 'max-height: '+(window_height/2)+'px;');
566                } else {
567                    tooltip_bg.classList.add('m-preactive');
568                    var tooltip_left = tooltip_position.left;
569                    var body_right = document.querySelector('.article__body').getBoundingClientRect().right;
570                    if (body_right - tooltip_left < 370) {
571                        tooltip_left = body_right - 369;
572                    }
573                    var tooltip_top = tooltip_position.top;
574                    var text_height = 400;
575                    var title_height = tooltip_popup.querySelector('.article__tooltip-title').offsetHeight;
576                    if (tooltip_top < window_height/2) {
577                        text_height = window_height - tooltip_position.top - tooltip_position.height - title_height - 64;
578                        tooltip_popup.classList.remove('m-top');
579                        tooltip_top = tooltip_position.top + tooltip_position.height + document.documentElement.scrollTop;
580                    } else {
581                        text_height = tooltip_position.top - title_height - 58;
582                        tooltip_popup.classList.add('m-top');
583                        tooltip_top = tooltip_position.top + document.documentElement.scrollTop;
584                    }
585                    tooltip_text.setAttribute('style', 'max-height: '+text_height+'px;');
586                    tooltip_popup.setAttribute('style', 'inset: '+tooltip_top+'px auto auto '+tooltip_left+'px;');
587                }
588                tooltip_bg.classList.add('m-active');
589            } else if (tooltip_popup.contains(el) && !tooltip_popup.querySelector('.article__tooltip-close').contains(el)) {
590                // do nothing
591            } else {
592                tooltipClose(tooltip_bg);
593            }
594        });
595        if (window_width > 924) {
596            window.addEventListener("resize", function() {
597                tooltipClose(tooltip_bg);
598            });
599        }
600    }
601});

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.