PageSourceSearch

https://mperspektiva.ru/local/templates/mp/s/js/components/js-sidebar-poll.js?v=7

js mperspektiva.ru collected 2026-10-02 03:36:10 UTC 6,685 bytes, 175 lines download raw bytes

1$(function () {
2    var $root = $('.js-sidebar-poll');
3    if (!$root.length) {
4        return;
5    }
6
7    $root.each(function () {
8        var $poll = $(this);
9        var pollId = $poll.data('poll-id');
10        var ajaxUrl = $poll.data('ajax-url');
11        var maxChoices = parseInt($poll.data('max-choices'), 10) || 3;
12        var $form = $poll.find('.js-sidebar-poll-form');
13        var $message = $poll.find('.js-sidebar-poll-message');
14        var $resultsPanel = $poll.find('.js-sidebar-poll-results-panel');
15
16        function showMessage(text, isError) {
17            if (!text) {
18                $message.attr('hidden', true).text('');
19                return;
20            }
21            $message
22                .attr('hidden', false)
23                .toggleClass('c-left-poll__message--error', !!isError)
24                .text(text);
25        }
26
27        function getSelectedChoices() {
28            var values = [];
29            $form.find('.js-sidebar-poll-choice:checked').each(function () {
30                values.push($(this).val());
31            });
32            return values;
33        }
34
35        function enforceMaxChoices($changed) {
36            var $checked = $form.find('.js-sidebar-poll-choice:checked');
37            if ($checked.length <= maxChoices) {
38                showMessage('');
39                return;
40            }
41            if ($changed && $changed.length) {
42                $changed.prop('checked', false);
43            }
44            showMessage('Можно выбрать не более ' + maxChoices + ' вариантов.', true);
45        }
46
47        $form.on('change', '.js-sidebar-poll-choice', function () {
48            enforceMaxChoices($(this));
49        });
50
51        function renderResultsHtml(results) {
52            if (!results || !results.rows) {
53                return;
54            }
55            var colors = ['#bd1f26', '#3d3d3d', '#9a9a9a', '#c47a4a', '#6b8e23', '#4a7fc4', '#7b5ea7', '#2f9e9e'];
56            var html = '<ul class="c-left-poll__results h-reset-list">';
57
58            if (!results.rows.length) {
59                html += '<li class="c-left-poll__result c-left-poll__result--empty">Пока нет голосов.</li>';
60            } else {
61                results.rows.forEach(function (row, index) {
62                    var percent = parseFloat(row.percent) || 0;
63                    var percentText = percent.toFixed(2).replace(/\.?0+$/, '');
64                    var color = colors[index % colors.length];
65                    html += '<li class="c-left-poll__result">';
66                    html += '<div class="c-left-poll__result-head">';
67                    html += '<span class="c-left-poll__result-label">' + $('<div>').text(row.label).html() + '</span>';
68                    html += '<span class="c-left-poll__result-percent">(' + percentText + '%)</span>';
69                    html += '</div>';
70                    html += '<div class="c-left-poll__result-bar" style="--poll-bar-color:' + color + ';--poll-bar-width:' + Math.min(100, percent) + '%;"></div>';
71                    html += '</li>';
72                });
73            }
74            html += '</ul>';
75            return html;
76        }
77
78        function updateVotersLabel(label) {
79            var $voters = $poll.find('.js-sidebar-poll-voters');
80            if (!$voters.length || !label) {
81                return;
82            }
83            $voters.text(label);
84        }
85
86        function showResultsPanel(results, withThanks) {
87            var $thanks = $resultsPanel.find('.c-left-poll__thanks');
88            if (withThanks && !$thanks.length) {
89                $resultsPanel.prepend('<p class="c-left-poll__thanks">Спасибо за участие в опросе.</p>');
90            }
91            var $list = $resultsPanel.find('.c-left-poll__results');
92            if ($list.length) {
93                $list.replaceWith(renderResultsHtml(results));
94            } else {
95                $resultsPanel.append(renderResultsHtml(results));
96            }
97            updateVotersLabel(results && results.voters_label ? results.voters_label : '');
98            $resultsPanel.removeAttr('hidden');
99        }
100
101        function parsePollResponse(xhr) {
102            if (!xhr || !xhr.responseText) {
103                return null;
104            }
105            try {
106                return JSON.parse(xhr.responseText);
107            } catch (e) {
108                return null;
109            }
110        }
111
112        function getPollErrorMessage(xhr, fallback) {
113            var data = parsePollResponse(xhr);
114            if (data && data.message) {
115                return data.message;
116            }
117            return fallback;
118        }
119
120        function requestPoll(action, payload, onSuccess, onError) {
121            return $.ajax({
122                url: ajaxUrl,
123                type: 'POST',
124                dataType: 'json',
125                data: $.extend({
126                    action: action,
127                    poll_id: pollId
128                }, payload || {})
129            }).done(function (data) {
130                if (data && data.success) {
131                    onSuccess(data);
132                    return;
133                }
134                onError((data && data.message) ? data.message : 'Ошибка запроса.');
135            }).fail(function (xhr) {
136                onError(getPollErrorMessage(xhr, 'Не удалось связаться с сервером.'));
137            });
138        }
139
140        function loadResults(withThanks) {
141            requestPoll('results', {}, function (data) {
142                showResultsPanel(data.results, withThanks);
143            }, function (message) {
144                showMessage(message, true);
145            });
146        }
147
148        $poll.on('click', '.js-sidebar-poll-vote', function () {
149            var choices = getSelectedChoices();
150            if (!choices.length) {
151                showMessage('Выберите хотя бы один вариант.', true);
152                return;
153            }
154            if (choices.length > maxChoices) {
155                showMessage('Можно выбрать не более ' + maxChoices + ' вариантов.', true);
156                return;
157            }
158
159            var $btn = $(this).prop('disabled', true);
160            showMessage('');
161
162            requestPoll('vote', {choices: choices}, function (data) {
163                $form.remove();
164                showResultsPanel(data.results, true);
165            }, function (message) {
166                showMessage(message, true);
167                $btn.prop('disabled', false);
168            });
169        });
170
171        $poll.on('click', '.js-sidebar-poll-results', function () {
172            loadResults(false);
173        });
174    });
175});

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.