PageSourceSearch

https://litcult.ru/rating/rating.js

js litcult.ru collected 2026-10-02 10:34:17 UTC 9,256 bytes, 249 lines download raw bytes

1/**
2 * jQuery Star Rating Plugin with Fixed Tooltip
3 * Подсказка поднята выше
4 */
5
6;(function($){
7    
8    class StarRatingInstance {
9        constructor(container, callback) {
10            this.container = container;
11            this.callback = callback || function(){};
12            this.currentHoverIndex = -1;
13            this.init();
14        }
15        
16        init() {
17            var el = this.container;
18            var list = '';
19            var isChecked = null;
20            var childs = el.children();
21            var i = 0;
22            var l = childs.length;
23            
24            // Определяем тип рейтинга
25            this.isNegative = false;
26            
27            for (; i < l; i++) {
28                var cl = "";
29                var value = $(childs[i]).val();
30                var is = Number(value);
31                if (is < 0) {
32                    cl = "gray";
33                    this.isNegative = true;
34                }
35                
36                list = list + '<a class="star ' + cl + '" data-value="' + value + '" data-index="' + i + '" title="' + value + '"></a>';
37                if ($(childs[i]).is(':checked')) {
38                    isChecked = value;
39                }
40            }
41            
42            // Скрываем оригинальные input'ы
43            childs.hide();
44            
45            // Добавляем звезды
46            var starsDiv = $('<div class="stars">' + list + '</div>');
47            el.append(starsDiv);
48            
49            // Сохраняем ссылки
50            this.stars = $('a', el);
51            this.inputs = childs;
52            
53            // Устанавливаем начальное значение
54            if (isChecked) {
55                this.setValue(isChecked);
56            }
57            
58            // Создаем фиксированный тултип
59            this.createFixedTooltip();
60            
61            // Привязываем события
62            this.attachEvents();
63        }
64        
65        createFixedTooltip() {
66            // Создаем тултип если его еще нет
67            if ($('#ratingTooltip').length === 0) {
68                this.tooltip = $('<div id="ratingTooltip" class="rating-tooltip-fixed" style="display:none;"></div>');
69                $('body').append(this.tooltip);
70            } else {
71                this.tooltip = $('#ratingTooltip');
72            }
73        }
74        
75        positionTooltip(value, isNegative) {
76            var leftBlock = $('#leftVoice');
77            var rightBlock = $('#rightVoice');
78            
79            // Показываем тултип
80            this.tooltip.html(value);
81            this.tooltip.removeClass('positive negative');
82            
83            if (isNegative) {
84                this.tooltip.addClass('negative');
85            } else {
86                this.tooltip.addClass('positive');
87            }
88            
89            // Позиционируем между блоками
90            if (leftBlock.length && rightBlock.length) {
91                var leftOffset = leftBlock.offset().left;
92                var leftWidth = leftBlock.outerWidth();
93                var rightOffset = rightBlock.offset().left;
94                
95                // Центр между блоками
96                var centerX = (leftOffset + leftWidth + rightOffset) / 2;
97                // Поднимаем выше - можно регулировать это значение
98                var topY = leftBlock.offset().top - 75; // Поднято на 75px выше блоков
99                
100                this.tooltip.css({
101                    left: centerX - (this.tooltip.outerWidth() / 2),
102                    top: topY,
103                    display: 'block'
104                });
105            } else if (this.container.length) {
106                var containerOffset = this.container.offset();
107                var containerWidth = this.container.outerWidth();
108                
109                this.tooltip.css({
110                    left: containerOffset.left + (containerWidth / 2) - (this.tooltip.outerWidth() / 2),
111                    top: containerOffset.top - 75,
112                    display: 'block'
113                });
114            }
115        }
116        
117        hideTooltip() {
118            if (this.tooltip) {
119                this.tooltip.css('display', 'none');
120            }
121        }
122        
123        attachEvents() {
124            var self = this;
125            
126            // Клик по звездам
127            this.stars.on('click', function(e) {
128                if ($("#isMe").val() == 1) return;
129                e.preventDefault();
130                
131                var rate = $(this).attr('title');
132                self.setValue(rate);
133                self.callback(rate, e);
134                self.hideTooltip();
135            });
136            
137            // Наведение на звезды
138            this.stars.on('mouseenter', function() {
139                if ($("#isMe").val() == 1) return;
140                
141                var value = $(this).attr('title');
142                var isNegative = $(this).hasClass('gray');
143                var index = parseInt($(this).data('index'));
144                
145                // Показываем тултип
146                self.positionTooltip(value, isNegative);
147                
148                // Подсветка звезд
149                self.clearTempClasses();
150                
151                if (isNegative) {
152                    // НЕГАТИВНЫЙ РЕЙТИНГ - зажигаем с конца
153                    var starsArray = self.stars.toArray();
154                    for (var i = starsArray.length - 1; i >= 0; i--) {
155                        if (i >= index) {
156                            $(starsArray[i]).addClass('tmp_fs');
157                        } else {
158                            $(starsArray[i]).addClass('tmp_es');
159                        }
160                    }
161                } else {
162                    // ПОЗИТИВНЫЙ РЕЙТИНГ - зажигаем с начала
163                    for (var i = 0; i <= index; i++) {
164                        $(self.stars[i]).addClass('tmp_os');
165                    }
166                    for (var i = index + 1; i < self.stars.length; i++) {
167                        $(self.stars[i]).addClass('tmp_es');
168                    }
169                }
170            });
171            
172            // Убираем подсветку при уходе с контейнера
173            this.container.on('mouseleave', function() {
174                if ($("#isMe").val() == 1) return;
175                self.clearTempClasses();
176                self.hideTooltip();
177            });
178            
179            // Обновляем позицию при ресайзе
180            $(window).on('resize', function() {
181                if (self.tooltip && self.tooltip.is(':visible')) {
182                    var value = self.tooltip.html();
183                    var isNegative = self.tooltip.hasClass('negative');
184                    self.positionTooltip(value, isNegative);
185                }
186            });
187        }
188        
189        clearTempClasses() {
190            this.stars.removeClass('tmp_fs tmp_os tmp_es');
191        }
192        
193        setValue(rate) {
194            var item = this.stars;
195            
196            if (rate) {
197                item.removeClass('fullStar');
198                
199                var targetStar = item.filter(function() {
200                    return $(this).attr('title') == rate;
201                });
202                
203                if (this.isNegative) {
204                    // НЕГАТИВ: закрашиваем от конца до выбранной звезды
205                    targetStar.addClass('fullStar');
206                    targetStar.nextAll().addClass('fullStar');
207                } else {
208                    // ПОЗИТИВ: закрашиваем от начала до выбранной звезды
209                    targetStar.addClass('fullStar');
210                    targetStar.prevAll().addClass('fullStar');
211                }
212            }
213            
214            // Обновляем состояние input'ов
215            this.inputs.each(function() {
216                $(this).prop('checked', $(this).val() == rate);
217            });
218        }
219        
220        destroy() {
221            this.container.off('mouseleave');
222            this.stars.off();
223            this.container.find('.stars').remove();
224            this.inputs.show();
225            if (this.tooltip && this.tooltip.length) {
226                this.tooltip.remove();
227            }
228        }
229    }
230    
231    // jQuery плагин
232    $.fn.rating = function(callback){
233        callback = callback || function(){};
234        
235        this.each(function(i, v){
236            var $this = $(v);
237            
238            if ($this.data('ratingInstance')) {
239                $this.data('ratingInstance').destroy();
240            }
241            
242            var instance = new StarRatingInstance($this, callback);
243            $this.data('ratingInstance', instance);
244        });
245        
246        return this;
247    };
248    
249})(jQuery);

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.