PageSourceSearch

https://www.lesprom.com/assets/modules/news_main/script.js?t=1790212825

js lesprom.com collected 2026-09-24 21:39:28 UTC 31,536 bytes, 942 lines download raw bytes

1var timer_search = null;
2var is_loading = false;
3var is_loading_content = false;
4var id_content = 0;
5var fullView_mode = '';
6window.url_self = window.url_self || (window.location.pathname + window.location.search);
7window.url_prefix = (typeof window.url_prefix === 'string') ? window.url_prefix : (function () {
8  var match = window.location.pathname.match(/^\/(en|de|zh|ru)(?=\/|$)/);
9  return match ? '/' + match[1] : '';
10})();
11
12var url_self = window.url_self;
13var url_prefix = window.url_prefix;
14var last_url = '';
15
16var suggest_markets = [];
17var suggest_themes = [];
18var suggest_countries = [];
19const newslettersEmail = $('#newsletters_email');
20const newslettersMess = $('.newsletters__mess');
21
22
23function send_request(is_append) {
24
25    if (is_append == undefined) {is_append = 0;}
26
27    if (timer_search!=null) {
28        clearTimeout(timer_search);
29    }
30    if (!is_loading) {
31        $.post(url_prefix+'/news/', $('#frm_news_search').serialize(), function(text) {
32            is_loading = false;
33            if (is_append) {
34                $('.page-search .load_more').remove();
35                $('.page-search .news-list').append(text);
36            } else {
37                $('.page-search .news-list').html(text);
38            }
39
40        });
41        is_loading = true;
42        timer_loading = setTimeout(function(){
43            is_loading = false;
44        }, 5000);
45    }
46}
47
48var popover_close_handler = function(e) {
49    var t = $(e.target);
50
51    var p = t.parents(".popover");
52    //t.is(".popover")
53
54    if (!p.length) {
55        lnk_firm_info.popover('hide');
56        $("body").unbind("click", popover_close_handler);
57    }
58};
59
60// function isScrolledIntoView(elem) {
61//    var docViewTop = $(window).scrollTop()+120;
62//    var docViewBottom = docViewTop + $(window).height();
63
64//    var elemTop = $(elem).offset().top;
65//    var elemBottom = elemTop + $(elem).height();
66//    return (elemTop >= docViewTop && elemTop <= docViewBottom) || (elemBottom >= docViewTop && elemBottom <= docViewBottom) || (elemTop < docViewTop && elemBottom > docViewBottom);
67// }
68
69function isScrolledIntoView(elem) {
70  if (!elem || elem.length === 0) return false;
71  var docViewTop    = $(window).scrollTop();
72  var offset        = elem.offset();
73  if (!offset) return false;
74  var elemTop       = offset.top;
75  var docViewBottom = docViewTop + $(window).height();
76  var elemBottom    = elemTop + elem.outerHeight();
77  return elemBottom <= docViewBottom && elemTop >= docViewTop;
78}
79
80function NewAfterLoad() {
81    $('time.full-time').each(function(index) {
82        var d = new Date( $(this).attr('datetime') );
83
84        var date = d.toLocaleString('default', {day: 'numeric', month: 'long', year: 'numeric' });
85        var time = d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
86
87        $(this).find('.time').html( time );
88        $(this).find('.date').html( date );
89    });
90
91    //https://clipboardjs.com/
92    if (typeof window.ClipboardJS === 'function' && $('.share-news').length) {
93        var clipboard = new window.ClipboardJS('.share-news');
94
95        clipboard.on('success', function(e) {
96            /*
97            console.info('Action:', e.action);
98            console.info('Text:', e.text);
99            console.info('Trigger:', e.trigger);
100            */
101
102            var popover = $(e.trigger).popover({
103                placement: "bottom",
104                html: true,
105                content: 'Ссылка скопирована в буфер обмена'
106            }).popover('show');
107
108            setTimeout(function() {
109                popover.popover("hide");
110            },3000);
111
112            e.clearSelection();
113        });
114
115        clipboard.on('error', function(e) {
116            /*
117            console.error('Action:', e.action);
118            console.error('Trigger:', e.trigger);
119            */
120            var popover = $(e.trigger).popover({
121                placement: "bottom",
122                html: true,
123                content: 'Ссылку скопировать не удалось'
124            }).popover('show');
125
126            setTimeout(function() {
127                popover.popover("hide");
128            },3000);
129        });
130    }
131}
132
133var fn_scroll = function(){
134
135    if (!fullView_mode) {return;}
136
137    var dv = fullView_mode=='top' ? $('#dv_view_top') : $('#dv_view_bottom');
138
139    if (isScrolledIntoView(dv)) {
140        var url = dv.find('h1.news-title').attr('data-link');
141    } else {
142        var url = url_self;
143    }
144    if (url!=last_url && window.history) {
145        last_url = url;
146        window.history.pushState("", "", url);
147    }
148}
149
150function init_suggest_markets() {
151
152    for (var i = 0; i < 3; i++) {
153
154        var params = {
155            url:url_prefix+"/xml/news.php",
156            obj_name:'fld_market_'+(i+1),
157            sch_type:'sch_market',
158            width:200,
159            pad_t:2,
160            pad_l:0,
161            hone:22,
162            hmax:8,
163            def_list: markets_default,
164            auto_select:0,
165            notf_text:''
166        };
167
168        suggest_markets[i] = new AjaxSuggest(params);
169        suggest_markets[i].show_results = function(opts) {
170            var out='';
171            for (var i=0; i<opts.length; i++) {
172                var id = opts[i].getAttribute('id');
173                var link = opts[i].getAttribute('link');
174                var text = opts[i].firstChild.data;
175                this.options[i]={id:id, text:text, link:link};
176                out+='<div class="out link"><div>'+text+'</div></div>';
177            }
178            this.build(out);
179        }
180        suggest_markets[i].select = function(n) {
181            var info=this.options[n-1];
182            var text=info.text;
183            var id=info.id;
184            var link=info.link;
185
186            this.lastcheck = text; //this.obj.val();
187            this.obj.val(text);
188
189            this.obj.attr('data-id', id);
190            this.obj.attr('data-link', link);
191
192            this.hide();
193        }
194        suggest_markets[i].notfound = function(n) {
195            this.obj.attr('data-id', 0);
196        }
197        suggest_markets[i].onSend = function() {
198            var ids = '';
199            $('.product-edit input').not( this.obj ).each(function(index) {
200                var id = $(this).attr('data-id');
201                if (id!='0') {
202                    if (ids) {ids += ',';}
203                    ids += id;
204                }
205            });
206            this.url_params = '&ids='+ids;
207        }
208        suggest_markets[i].obj.blur(function() {
209            if ($(this).attr('data-id')=='0') {
210                var key = $(this).attr('data-def-id');
211                var val = $(this).attr('data-def-val');
212                var lnk = $(this).attr('data-def-link');
213
214                $(this).attr('data-id', key);
215                $(this).attr('data-link', lnk);
216                $(this).val(val);
217            }
218        });
219        suggest_markets[i].obj.focus(function() {
220            var id = $(this).attr('id');
221            var ar = id.split('_');
222            var i = ar[2]-1;
223            for (var n = 0; n < 3; n++) {
224                if (n!=i && suggest_markets[n].opened) {
225                    suggest_markets[n].hide();
226                }
227            }
228        });
229    }
230}
231
232function init_suggest_themes() {
233
234    for (var i = 0; i < 3; i++) {
235
236        var params = {
237            url:url_prefix+"/xml/news.php",
238            obj_name:'fld_theme_'+(i+1),
239            sch_type:'sch_theme',
240            width:200,
241            pad_t:2,
242            pad_l:0,
243            hone:22,
244            hmax:8,
245            auto_select:0,
246            def_list: themes_default,
247            notf_text:''
248        };
249
250        suggest_themes[i] = new AjaxSuggest(params);
251        suggest_themes[i].show_results = function(opts) {
252            var out='';
253            for (var i=0; i<opts.length; i++) {
254                var id = opts[i].getAttribute('id');
255                var link = opts[i].getAttribute('link');
256                var text = opts[i].firstChild.data;
257                this.options[i]={id:id, text:text, link:link};
258                out+='<div class="out link"><div>'+text+'</div></div>';
259            }
260            this.build(out);
261        }
262        suggest_themes[i].select = function(n) {
263            var info=this.options[n-1];
264            var text=info.text;
265            var id=info.id;
266            var link=info.link;
267
268            this.lastcheck = text; //this.obj.val();
269            this.obj.val(text);
270
271            this.obj.attr('data-id', id);
272            this.obj.attr('data-link', link);
273
274            this.hide();
275        }
276        suggest_themes[i].notfound = function(n) {
277            this.obj.attr('data-id', 0);
278        }
279        suggest_themes[i].onSend = function() {
280            var ids = '';
281            $('.theme-edit input').not( this.obj ).each(function(index) {
282                var id = $(this).attr('data-id');
283                if (id!='0') {
284                    if (ids) {ids += ',';}
285                    ids += id;
286                }
287            });
288            this.url_params = '&ids='+ids;
289        }
290        suggest_themes[i].obj.blur(function() {
291            if ($(this).attr('data-id')=='0') {
292                var key = $(this).attr('data-def-id');
293                var val = $(this).attr('data-def-val');
294                var lnk = $(this).attr('data-def-link');
295
296                $(this).attr('data-id', key);
297                $(this).attr('data-link', lnk);
298                $(this).val(val);
299            }
300        });
301        suggest_themes[i].obj.focus(function() {
302            var id = $(this).attr('id');
303            var ar = id.split('_');
304            var i = ar[2]-1;
305            for (var n = 0; n < 3; n++) {
306                if (n!=i && suggest_themes[n].opened) {
307                    suggest_themes[n].hide();
308                }
309            }
310        });
311    }
312}
313
314function init_suggest_countries() {
315
316    for (var i = 0; i < 3; i++) {
317
318        var params = {
319            url:url_prefix+"/xml/news.php",
320            obj_name:'fld_country_'+(i+1),
321            sch_type:'sch_country',
322            width:200,
323            pad_t:2,
324            pad_l:0,
325            hone:22,
326            hmax:8,
327            auto_select:0,
328            def_list: countries_default,
329            notf_text:''
330        };
331
332        suggest_countries[i] = new AjaxSuggest(params);
333        suggest_countries[i].show_results = function(opts) {
334            var out='';
335            for (var i=0; i<opts.length; i++) {
336                var id = opts[i].getAttribute('id');
337                var link = opts[i].getAttribute('link');
338                var text = opts[i].firstChild.data;
339                this.options[i]={id:id, text:text, link:link};
340                out+='<div class="out link"><div>'+text+'</div></div>';
341            }
342            this.build(out);
343        }
344        suggest_countries[i].select = function(n) {
345            var info=this.options[n-1];
346            var text=info.text;
347            var id=info.id;
348            var link=info.link;
349
350            this.lastcheck = text;
351            this.obj.val(text);
352
353            this.obj.attr('data-id', id);
354            this.obj.attr('data-link', link);
355
356            this.hide();
357        }
358        suggest_countries[i].notfound = function(n) {
359            this.obj.attr('data-id', 0);
360        }
361        suggest_countries[i].onSend = function() {
362            var ids = '';
363            $('.country-edit input').not( this.obj ).each(function(index) {
364                var id = $(this).attr('data-id');
365                if (id!='0') {
366                    if (ids) {ids += ',';}
367                    ids += id;
368                }
369            });
370            this.url_params = '&ids='+ids;
371        }
372        suggest_countries[i].obj.blur(function() {
373            if ($(this).attr('data-id')=='0') {
374                var key = $(this).attr('data-def-id');
375                var val = $(this).attr('data-def-val');
376                var lnk = $(this).attr('data-def-link');
377
378                $(this).attr('data-id', key);
379                $(this).attr('data-link', lnk);
380                $(this).val(val);
381            }
382        });
383        suggest_countries[i].obj.focus(function() {
384            var id = $(this).attr('id');
385            var ar = id.split('_');
386            var i = ar[2]-1;
387            for (var n = 0; n < 3; n++) {
388                if (n!=i && suggest_countries[n].opened) {
389                    suggest_countries[n].hide();
390                }
391            }
392        });
393    }
394}
395
396function movingBanners() {
397    if ($(window).width() < 1200) {
398        $('#list-banner-1').addClass('no-empty').append($('#news-banner-1').children());
399        $('#list-banner-2').addClass('no-empty').append($('#news-banner-2').children());
400    } else if($('#news-banner-1 a').length === 0) {
401        $('#news-banner-1').append($('#list-banner-1').removeClass('no-empty').children());
402        $('#news-banner-2').append($('#list-banner-2').removeClass('no-empty').children());
403    }
404}
405
406$(function () {
407    last_url = url_self;
408    $(window).on('scroll', fn_scroll);
409
410    //$('body').addClass('news-themes');
411
412    $('#lnk_news_search').click(function(event) {
413
414        event.preventDefault();
415
416        $('body').addClass('news-search');
417
418        //$('#fld_news_search').focus();
419
420    });
421
422    $('#lnk_news_themes').click(function(event) {
423
424        event.preventDefault();
425
426        // без оверлея на странице режим не включаем - иначе CSS прячет
427        // контент и остаётся пустая страница
428        if ($('#dv_page_themes').length) {
429            $('body').addClass('news-themes');
430            $(window).scrollTop(0);
431        }
432
433    });
434
435    $('#btn_search_close').click(function(event) {
436
437        event.preventDefault();
438
439        $('body').removeClass('news-search');
440    });
441
442    $('#btn_themes_close').click(function(event) {
443
444        event.preventDefault();
445
446        $('body').removeClass('news-themes');
447    });
448
449    $('#fld_news_search').keyup(function() {
450        var fld = $(this);
451        var val = fld.val();
452        //console.log(val.length);
453        if (timer_search!=null) {
454            clearTimeout(timer_search);
455        }
456        if (val.length >= 3) {
457            document.form_news_search.page.value = 1;
458            timer_search = setTimeout(send_request,500);
459        } else if (!val.length) {
460            $('.page-search .news-list').html('');
461        }
462    });
463
464    $('.page-search').on( "click", ".load_more a", function() {
465
466        event.preventDefault();
467
468        document.form_news_search.page.value = $(this).attr('data-page');
469
470        send_request(1);
471    });
472
473    $('#dv_news_list').on( "click", ".load_more a", function() {
474
475        event.preventDefault();
476
477        document.form_content.page.value = $(this).attr('data-page');
478
479        if (!is_loading_content) {
480            $.post(url_self, $('#frm_content').serialize(), function(text) {
481                is_loading_content = false;
482                $('#dv_news_list .load_more').remove();
483                $('#dv_news_list').append(text);
484
485            });
486            is_loading_content = true;
487
488            timer_loading = setTimeout(function(){
489                is_loading_content = false;
490            }, 5000);
491        }
492    });
493
494    $('.news-link-dynamic').click(function(event) {
495        event.preventDefault();
496        var lnk = $(this);
497        var place = lnk.hasClass('feature-title-link') || lnk.hasClass('feature-side-link') ? 'top' : 'bottom';
498        var nid = lnk.attr('data-id');
499
500        var url = url_self+'?action=loadNewInfo&nid='+nid;
501        responseFunc = function(text) {
502
503            hide_dv(AjaxRequest_timer_dv);
504            if (AjaxRequest_timer!= null) {clearTimeout(AjaxRequest_timer);}
505
506            fullView_mode = place;
507
508            if (place=='top') {
509                $('#dv_view_bottom').html('');
510                var dv = $('#dv_view_top');
511            } else {
512                var dv = $('#dv_view_bottom');
513                if (id_content) {
514                    $('#news_'+id_content).show();
515                    dv.html('');
516                }
517                $('#dv_view_top').html('');
518
519                var article = lnk.parents('article');
520                dv.insertAfter(article);
521                article.hide();
522            }
523            dv.html(text);
524            $(document).scrollTo(dv,150,{offset:-100});
525
526            NewAfterLoad();
527
528            id_content = nid;
529        }
530        hide_confirm_bubble();
531        AjaxRequest(url,responseFunc,'html',1);
532    });
533
534    $('.main-menu-block').on( "click", ".fa-pencil", function() {
535
536        event.preventDefault();
537        event.stopPropagation();
538
539        var p = $(this).parents('li');
540        if (p.hasClass('editable')) {
541            if (p.hasClass('product-header')) {
542                $('.main-menu-block .product-item').hide();
543                $('.main-menu-block .product-edit').show();
544                init_suggest_markets();
545            } else if (p.hasClass('country-header')) {
546                $('.main-menu-block .country-item').hide();
547                $('.main-menu-block .country-edit').show();
548                init_suggest_countries();
549            } else {
550                $('.main-menu-block .theme-item').hide();
551                $('.main-menu-block .theme-edit').show();
552                init_suggest_themes();
553            }
554        }
555    }).on( "click", "#btn_product_close", function() {
556        $('.main-menu-block .product-item').show();
557        $('.main-menu-block .product-edit').hide();
558
559        $('.product-edit input').each(function(index) {
560            var key = $(this).attr('data-def-id');
561            var val = $(this).attr('data-def-val');
562            var lnk = $(this).attr('data-def-link');
563
564            $(this).attr('data-id', key);
565            $(this).attr('data-link', lnk);
566            $(this).val(val);
567        });
568
569    }).on( "click", "#btn_product_save", function() {
570        $('.main-menu-block .product-item').show();
571        $('.main-menu-block .product-edit').hide();
572
573        var ids = '';
574        $('.product-edit input').each(function(index) {
575            var key = $(this).attr('data-id');
576            var lnk = $(this).attr('data-link');
577            var val = $(this).val();
578
579            if (ids) {ids+=',';}
580            ids+=key;
581
582            $(this).attr('data-def-id', key);
583            $(this).attr('data-def-val', val);
584            $(this).attr('data-def-link', lnk);
585
586            var item = $('.product-item').eq(index);
587
588            item.find('a').attr('href', lnk).text(val);
589        });
590
591        var url = url_prefix+'/news/?action=save&code=products&value='+ids;
592        responseFunc = function(text) {
593
594        }
595        AjaxRequest(url,responseFunc);
596
597    }).on( "click", "#btn_theme_close", function() {
598        $('.main-menu-block .theme-item').show();
599        $('.main-menu-block .theme-edit').hide();
600
601        $('.theme-edit input').each(function(index) {
602            var key = $(this).attr('data-def-id');
603            var val = $(this).attr('data-def-val');
604            var lnk = $(this).attr('data-def-link');
605
606            $(this).attr('data-id', key);
607            $(this).attr('data-link', lnk);
608            $(this).val(val);
609        });
610
611    }).on( "click", "#btn_theme_save", function() {
612        $('.main-menu-block .theme-item').show();
613        $('.main-menu-block .theme-edit').hide();
614
615        var ids = '';
616        $('.theme-edit input').each(function(index) {
617            var key = $(this).attr('data-id');
618            var lnk = $(this).attr('data-link');
619            var val = $(this).val();
620
621            if (ids) {ids+=',';}
622            ids+=key;
623
624            $(this).attr('data-def-id', key);
625            $(this).attr('data-def-val', val);
626            $(this).attr('data-def-link', lnk);
627
628            var item = $('.theme-item').eq(index);
629
630            item.find('a').attr('href', lnk).text(val);
631        });
632
633        var url = url_prefix+'/news/?action=save&code=themes&value='+ids;
634        responseFunc = function(text) {
635
636        };
637        AjaxRequest(url,responseFunc);
638    }).on( "click", "#btn_country_close", function() {
639        $('.main-menu-block .country-item').show();
640        $('.main-menu-block .country-edit').hide();
641
642        $('.country-edit input').each(function(index) {
643            var key = $(this).attr('data-def-id');
644            var val = $(this).attr('data-def-val');
645            var lnk = $(this).attr('data-def-link');
646
647            $(this).attr('data-id', key);
648            $(this).attr('data-link', lnk);
649            $(this).val(val);
650        });
651
652    }).on( "click", "#btn_country_save", function() {
653        $('.main-menu-block .country-item').show();
654        $('.main-menu-block .country-edit').hide();
655
656        var ids = '';
657        $('.country-edit input').each(function(index) {
658            var key = $(this).attr('data-id');
659            var lnk = $(this).attr('data-link');
660            var val = $(this).val();
661
662            if (ids) {ids+=',';}
663            ids+=key;
664
665            $(this).attr('data-def-id', key);
666            $(this).attr('data-def-val', val);
667            $(this).attr('data-def-link', lnk);
668
669            var item = $('.country-item').eq(index);
670
671            item.find('a').attr('href', lnk).text(val);
672        });
673
674        var url = url_prefix+'/news/?action=save&code=countries&value='+ids;
675        responseFunc = function(text) {
676
677        };
678        AjaxRequest(url,responseFunc);
679    });
680
681
682    if (localStorage.getItem('search') === 'true') {
683        $('#lnk_news_search').trigger('click');
684        localStorage.removeItem('search');
685    }
686
687    if (localStorage.getItem('theme') === 'true') {
688        $('#lnk_news_themes').trigger('click');
689        localStorage.removeItem('theme');
690    }
691
692    if (localStorage.getItem('support') === 'true') {
693        $("html, body").animate({scrollTop: $(document).outerHeight(true)}, 0);
694        localStorage.removeItem('support');
695        open_dlg_support();return false;
696    }
697
698    movingBanners();
699
700    $(window).resize(function () {
701        movingBanners();
702    });
703
704    $('#newsletters').keydown(function (e) {
705        if(e.keyCode == 13) {
706            e.preventDefault();
707            return false;
708        }
709    });
710
711    $('#newsletters_submit').click(function (e) {
712        e.preventDefault();
713        AjaxRequest_loading();
714
715        const email = '&' + newslettersEmail.serialize();
716        let newsletters = '&newsletters=';
717        const id = 'id=' + sys_uid;
718        $('.newsletters__checkbox:checked').each(function (index, item) {
719            newsletters += (index > 0 ? ',' : '') + $(item).val();
720        });
721
722        $.post(url_self + '?action=newsletters', `${id}${email}${newsletters}`)
723            .done(function (data) {
724                hide_dv(AjaxRequest_timer_dv);
725                if (AjaxRequest_timer != null) {
726                    clearTimeout(AjaxRequest_timer);
727                }
728
729                let res = data.split('<!>');
730
731                if (res[0] === '0') {
732                    newslettersMess.addClass('ok');
733                } else {
734                    newslettersMess.addClass('error');
735                }
736
737                newslettersMess.text(res[1]);
738            })
739            .fail(function () {
740                alert('Something goes wrong. Try again later.');
741                hide_dv(AjaxRequest_timer_dv);
742                if (AjaxRequest_timer != null) {
743                    clearTimeout(AjaxRequest_timer);
744                }
745            });
746    });
747
748    newslettersEmail.on('input', function (e) {
749        $(this).attr('value', $(this).val());
750
751        if(validateEmail(newslettersEmail.val())) {
752            newslettersMess.removeClass('error ok');
753            newslettersEmail.removeClass('error').addClass('ok');
754        } else {
755            newslettersMess.removeClass('ok').addClass('error').text(unCorrectEmail);
756            newslettersEmail.removeClass('ok').addClass('error');
757            $('#newsletters_submit').addClass('disabled');
758        }
759
760        formCheck();
761    });
762
763    $('.newsletters__checkbox').change(function () {
764        if (!$('.newsletters__checkbox:checked').length) {
765            $('#newsletters_submit').addClass('disabled');
766        }
767
768        formCheck();
769    });
770});
771
772function formCheck() {
773    if(validateEmail(newslettersEmail.val()) && $('.newsletters__checkbox:checked').length) {
774        $('#newsletters_submit').removeClass('disabled');
775        newslettersMess.removeClass('error ok');
776        newslettersEmail.removeClass('error').addClass('ok');
777    }
778}
779
780function validateEmail(email) {
781    let reg = /^[\w]{1}[\w-\.]*@[\w-]+\.[a-z]{2,4}$/i;
782
783    return reg.test(email)
784}
785
786$(function () {
787    function newsletterSignupEmailValid(email) {
788        return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
789    }
790
791    function newsletterSignupHeaderOffset() {
792        var header = $('header:visible').first();
793        return (header.length ? header.outerHeight() : 0) + 8;
794    }
795
796    function newsletterSignupScrollTo(animate) {
797        var target = $('#newsletter-signup');
798        if (!target.length) {
799            target = $('.newsletter-tc').first();
800        }
801        if (!target.length) {
802            return false;
803        }
804
805        var top = Math.max(0, target.offset().top - newsletterSignupHeaderOffset());
806        $('html, body').stop(true).animate({scrollTop: top}, animate ? 250 : 0);
807        return true;
808    }
809
810    function newsletterSignupUpdate(root) {
811        var checked = root.find('.newsletter-tc__checkbox:checked');
812        root.find('.newsletter-tc__card').removeClass('is-selected');
813        checked.each(function () {
814            $(this).closest('.newsletter-tc__card').addClass('is-selected');
815        });
816        var total = checked.length;
817        var label = total === 1 ? root.data('count-one') : root.data('count-many');
818        if (!label) {
819            label = total + ' newsletter' + (total === 1 ? '' : 's') + ' selected.';
820        }
821        root.find('.newsletter-tc__count').text(String(label).replace('#count', total));
822        return total;
823    }
824
825    // Окно «проверьте почту» после успешной подписки. Ничего не проверяет на
826    // сервере: кнопка просто закрывает его, но нажать «Уже подтвердил», не
827    // подтвердив, психологически труднее, чем не заметить строку под формой.
828    function newsletterConfirmModal(root, email) {
829        var esc = function (v) {return $('<i>').text(v == null ? '' : String(v)).html();};
830        var title = root.data('modal-title') || 'Check your email';
831        var text = (root.data('modal-text') || 'We sent a confirmation link to #email.').replace('#email', esc(email));
832        var hint = root.data('modal-hint') || '';
833        var btn = root.data('modal-button') || 'I have confirmed';
834
835        $('#nl-modal').remove();
836        var html = '<div class="nl-modal" id="nl-modal" role="dialog" aria-modal="true" aria-labelledby="nl-modal-title">'
837            + '<div class="nl-modal__box">'
838            + '<button type="button" class="nl-modal__close" aria-label="Close">&times;</button>'
839            + '<h2 class="nl-modal__title" id="nl-modal-title">' + esc(title) + '</h2>'
840            + '<p class="nl-modal__text">' + text + '</p>'
841            + (hint ? '<p class="nl-modal__hint">' + esc(hint) + '</p>' : '')
842            + '<button type="button" class="nl-modal__btn">' + esc(btn) + '</button>'
843            + '</div></div>';
844        $('body').append(html);
845
846        var close = function () {$('#nl-modal').remove(); $(document).off('keydown.nlmodal');};
847        $('#nl-modal').on('click', function (e) {if (e.target === this) {close();}});
848        $('#nl-modal .nl-modal__btn, #nl-modal .nl-modal__close').on('click', close);
849        $(document).on('keydown.nlmodal', function (e) {if (e.key === 'Escape') {close();}});
850        $('#nl-modal .nl-modal__btn').focus();
851    }
852
853    $(document).on('change', '.newsletter-tc__checkbox', function () {
854        var root = $(this).closest('.newsletter-tc');
855        newsletterSignupUpdate(root);
856        root.find('.newsletter-tc__message').removeClass('ok error').text('');
857    });
858
859    $(document).on('submit', '.newsletter-tc__signup-form', function (e) {
860        e.preventDefault();
861
862        var form = $(this);
863        var root = form.closest('.newsletter-tc');
864        var email = $.trim(form.find('.newsletter-tc__input').val());
865        var message = root.find('.newsletter-tc__message');
866        var button = form.find('.newsletter-tc__button');
867        var selected = newsletterSignupUpdate(root);
868
869        message.removeClass('ok error').text('');
870
871        if (!selected) {
872            message.addClass('error').text(root.data('label-choose') || 'Choose at least one newsletter.');
873            return;
874        }
875        if (!newsletterSignupEmailValid(email)) {
876            message.addClass('error').text(root.data('label-invalid-email') || 'Enter a valid email address.');
877            form.find('.newsletter-tc__input').focus();
878            return;
879        }
880
881        button.prop('disabled', true);
882
883        $.ajax({
884            type: 'POST',
885            url: url_prefix + '/news/?action=newsletterSignup',
886            data: form.serialize(),
887            dataType: 'json'
888        }).done(function (data) {
889            var ok = data && data.ok;
890            message.addClass(ok ? 'ok' : 'error').text(data && data.message ? data.message : (root.data('label-error') || 'Something goes wrong. Try again later.'));
891            if (ok) {
892                // Строку под формой почти не замечают, поэтому просьбу открыть
893                // письмо показываем окном: шаг подтверждения виден и требует
894                // осознанного действия (владелец, 23.09.2026).
895                newsletterConfirmModal(root, email);
896                form.find('.newsletter-tc__input').val('');
897            }
898        }).fail(function () {
899            message.addClass('error').text(root.data('label-error') || 'Something goes wrong. Try again later.');
900        }).always(function () {
901            button.prop('disabled', false);
902        });
903    });
904
905    $(document).on('click', 'a[href="#newsletter-signup"], .js-newsletter-anchor', function (e) {
906        if (!newsletterSignupScrollTo(true)) {
907            return;
908        }
909
910        e.preventDefault();
911        if (window.history && window.history.pushState) {
912            window.history.pushState(null, '', '#newsletter-signup');
913        } else {
914            window.location.hash = 'newsletter-signup';
915        }
916    });
917
918    if (window.location.hash === '#newsletter-signup') {
919        setTimeout(function () {
920            newsletterSignupScrollTo(false);
921        }, 0);
922    }
923
924    $(document).on('click', function (event) {
925        $('.news-pagination-picker[open]').each(function () {
926            if (!this.contains(event.target)) {
927                this.removeAttribute('open');
928            }
929        });
930    });
931
932    $(document).on('keydown', function (event) {
933        if (event.key !== 'Escape') {
934            return;
935        }
936
937        $('.news-pagination-picker[open]').each(function () {
938            this.removeAttribute('open');
939            $(this).find('.news-pagination-select').trigger('focus');
940        });
941    });
942});

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.