PageSourceSearch

https://aktobe.city/assets/components/xlike/js/web/default.js

js aktobe.city collected 2026-10-04 13:28:38 UTC 14,110 bytes, 328 lines download raw bytes

1(function () {
2    function xLike(options) {
3        //
4        [/*'assetsUrl', */'actionUrl'].forEach(function (val, i, arr) {
5            if (typeof(options[val]) == 'undefined' || options[val] == '') {
6                console.error('[xLike] Bad config.', arr);
7                return;
8            }
9        });
10
11        //
12        var self = this;
13        self.initialized = false;
14        self.running = false;
15
16        /**
17         * Инициализирует класс.
18         * @returns {boolean}
19         */
20        self.initialize = function (options) {
21            if (!self.initialized) {
22                //
23                self.config = {};
24                self.classes = {
25                    buttonActive: 'xlike__link_active',
26                };
27                self.selectors = {
28                    object: '.js-xlike-object',
29                    button: '.js-xlike-button',
30                    number: '.js-xlike-number',
31                    rating: '.js-xlike-rating',
32                    stripe: '.js-xlike-stripe',
33                };
34                self.sendDataTemplate = {
35                    $element: null,
36                    params: null,
37                };
38                self.sendData = $.extend({}, self['sendDataTemplate']);
39
40                //
41                Object.keys(options).forEach(function (key) {
42                    if (['selectors'].indexOf(key) !== -1) {
43                        return;
44                    }
45                    self.config[key] = options[key];
46                });
47
48                //
49                ['selectors'].forEach(function (key) {
50                    if (options[key]) {
51                        Object.keys(options[key]).forEach(function (i) {
52                            self.selectors[i] = options.selectors[i];
53                        });
54                    }
55                });
56            }
57            self['initialized'] = true;
58
59            return self.initialized;
60        };
61
62        /**
63         * Запускает основные действия.
64         * @returns {boolean}
65         */
66        self.run = function () {
67            if (self['initialized'] && !self['running']) {
68                /**
69                 * Клик по кнопке
70                 */
71                $(document).on('click', self.selectors['button'], function (e) {
72                    e.preventDefault();
73
74                    var $button = $(this);
75                    var $object = $button.closest(self.selectors['object']);
76                    if ($object['length']) {
77                        var propkey = $object.data('xlike-propkey');
78                        var parent = $object.data('xlike-parent');
79                        var value = $button.data('xlike-value');
80                        var sendData = $.extend({}, self['sendDataTemplate']);
81
82                        // Готовим параметры запроса
83                        sendData['$element'] = $button;
84                        sendData['params'] = {
85                            action: 'vote',
86                            propkey: propkey,
87                            parent: parent,
88                            value: value,
89                        };
90
91                        // Если уже есть активная кнопка - запомним в параметры
92                        var $last = $object.find(self.selectors['button']).filter('.' + self.classes['buttonActive']);
93                        if ($last['length'] && !$last.data('xlike-tmp')) {
94                            // console.log('[xLike] on(click) $last', $last);
95                            sendData['$last'] = $last;
96                        }
97
98                        // console.log(sendData);
99
100                        // Шлём запрос
101                        self['sendData'] = $.extend({}, sendData);
102                        self.Submit.post();
103                    }
104                });
105            }
106            self.running = true;
107
108            return self.running;
109        };
110
111        /**
112         * Отсылает запрос на сервер.
113         * @type {object}
114         */
115        self.Submit = {
116            // status: false,
117            before: function () {
118                if (self.sendData.params['action'] == 'vote') {
119                    // Реализуем оптимистичный интерфейс
120                    var $last = self.sendData['$last'];
121                    var $button = self.sendData['$element'];
122                    var $object = $button.closest(self.selectors['object']);
123                    var $number = $button.find(self.selectors['number']);
124                    var number = parseInt(($number.text()).replace(' ', '').replace(',', ''));
125                    // var number = $number.text();
126                    // number = parseInt(number.replace(' ', '').replace(',', ''));
127
128                    $object.find(self.selectors['button']).each(function (idx, el) {
129                        var $btn = $(el);
130                        if ($button.get(0) != $btn.get(0)) {
131                            if ($btn.hasClass(self.classes['buttonActive'])) {
132                                $btn.removeClass(self.classes['buttonActive']); // .removeAttr('data-xlike-tmp')
133                                var $num = $btn.find(self.selectors['number']);
134                                var num = parseInt(($num.text()).replace(' ', '').replace(',', ''));
135                                // var num = $num.text();
136                                // num = parseInt(num.replace(' ', '').replace(',', ''));
137                                $num.text(self.Tools.number_format((num - 1), 0, '.', ' '));
138                            }
139                        }
140                    });
141                    $button.toggleClass(self.classes['buttonActive']).data('xlike-tmp', 1);
142                    if ($button.hasClass(self.classes['buttonActive'])) {
143                        $number.text(self.Tools.number_format((number + 1), 0, '.', ' '));
144                    } else {
145                        $number.text(self.Tools.number_format((number - 1), 0, '.', ' '));
146                    }
147                }
148            },
149            after: function (response) {
150                if (self.sendData.params['action'] == 'vote') {
151                    var $last = self.sendData['$last'];
152                    var $button = self.sendData['$element'];
153                    var $object = $button.closest(self.selectors['object']);
154                    var $number = $button.find(self.selectors['number']);
155                    var number = parseInt(($number.text()).replace(' ', '').replace(',', ''));
156
157                    // При безуспешном запросе
158                    if (!response['success']) {
159                        // 1) Переключаем класс активной кнопки
160                        $button.toggleClass(self.classes['buttonActive']).removeAttr('data-xlike-tmp').removeData('xlike-tmp');
161
162                        // 2) Возвращаем предыдущее значение голосов
163                        if ($button.hasClass(self.classes['buttonActive'])) {
164                            $number.text(self.Tools.number_format((number + 1), 0, '.', ' '));
165                        } else {
166                            $number.text(self.Tools.number_format((number - 1), 0, '.', ' '));
167                        }
168
169                        // 3) Возвращаем класс активной кнопки последнему элементу
170                        if (!!$last && $last['length'] && $last[0] != $button[0]) {
171                            var $last_number = $last.find(self.selectors['number']);
172                            var last_number = parseInt(($last_number.text()).replace(' ', '').replace(',', ''));
173
174                            // 3.1) Переключаем класс активной кнопки на последний активный
175                            $last.toggleClass(self.classes['buttonActive']).removeAttr('data-xlike-tmp').removeData('xlike-tmp');
176
177                            // 3.2) Возвращаем предыдущее значение голосов последней активной
178                            if ($last.hasClass(self.classes['buttonActive'])) {
179                                $last_number.text(self.Tools.number_format((last_number + 1), 0, '.', ' '));
180                            } else {
181                                $last_number.text(self.Tools.number_format((last_number - 1), 0, '.', ' '));
182                            }
183                        }
184                    }
185                    // При успешном запросе
186                    else {
187                        var $rating = $object.find(self.selectors['rating']);
188                        var $stripe = $object.find(self.selectors['stripe']);
189
190                        // 1) Удаляем обозначение временного наÐ
190·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ класса
191                        $button.removeAttr('data-xlike-tmp');
192
193                        // 2) Ставим новое значение рейтинга
194                        if (typeof(response.data['rating']) != 'undefined') {
195                            var rating_old = $rating.text().replace(' ', ''); // parseFloat($rating.text().replace(' ', ''));
196                            var rating_new = response.data['rating']; // parseFloat(response.data['rating']);
197                            console.log('[xLike] self.Submit.post() after rating_old', rating_old);
198                            console.log('[xLike] self.Submit.post() after rating_new', rating_new);
199
200                            // $rating.text(rating_new);
201
202                            self.Tools.animateNumbers($rating, rating_old, rating_new, 700);
203                        }
204
205                        // 3) Ставим новую длину полосы
206                        if (typeof(response.data['rating']) != 'undefined') {
207                            $stripe.css({minWidth: response.data['rating'] + '%'});
208                        }
209                    }
210                }
211            },
212            post: function (callback) {
213                if (!self.sendData['params'] || !self.sendData.params['action']) {
214                    return;
215                }
216                self.Submit.before();
217
218                $.post(self.config['actionUrl'], self.sendData['params'], function (response) {
219                    console.log('xLike self.Submit.post() response', response);
220
221                    self.Submit.after(response);
222
223                    if (response['success']) {
224                        self.Message.success(response['message']);
225
226                        // Запускаем колбек
227                        if (callback && $.isFunction(callback)) {
228                            callback.call(this, response, self.sendData['params']);
229                        }
230                    } else {
231                        self.Message.error(response['message']);
232                    }
233                }, 'json')
234                    .fail(function () {
235                        console.error('[xLike] Bad request.', self['sendData']);
236                    })
237                    .done(function () {
238                    });
239            },
240        };
241
242        /**
243         * Сообщения.
244         * @type {object}
245         */
246        self.Message = {
247            success: function (message) {
248            },
249            error: function (message) {
250                alert(message);
251            }
252        };
253
254        /**
255         * Инструменты.
256         * @type {object}
257         */
258        self.Tools = {
259            /**
260             * Аналог number_format из PHP
261             *
262             * @param number
263             * @param decimals
264             * @param dec_point
265             * @param thousands_sep
266             */
267            number_format: function (number, decimals, dec_point, thousands_sep) {
268                var i, j, kw, kd, km;
269
270                if (isNaN(decimals = Math.abs(decimals))) {
271                    decimals = 2;
272                }
273                if (dec_point == undefined) {
274                    dec_point = ',';
275                }
276                if (thousands_sep == undefined) {
277                    thousands_sep = '.';
278                }
279
280                i = parseInt(number = (+number || 0).toFixed(decimals)) + '';
281                if ((j = i.length) > 3) {
282                    j = j % 3;
283                } else {
284                    j = 0;
285                }
286                km = j ? (i.substr(0, j) + thousands_sep) : '';
287                kw = i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousands_sep);
288                kd = (decimals ? (dec_point + Math.abs(number - i).toFixed(decimals).replace(/-/, '0').slice(2)) : '');
289
290                return (km + kw + kd);
291            },
292
293            /**
294             * Анимированные числа
295             *
296             * @param element
297             * @param start
298             * @param stop
299             * @param duration
300             * @param easing
301             */
302            animateNumbers: function (element, start, stop, duration, easing) {
303                if (start != stop) {
304                    var $element = element;
305                    $({value: start}).animate({value: stop}, {
306                        duration: (duration == undefined) ? 1000 : duration,
307                        easing: (easing == undefined) ? 'swing' : easing,
308                        step: function () {
309                            $element.text(self.Tools.number_format(this['value'], 2, '.', ''));
310                        },
311                        complete: function () {
312                            $element.text(stop);
313                        }
314                    });
315                }
316            },
317        };
318
319        /**
320         * Initialize && Run!
321         */
322        if (self.initialize(options)) {
323            self.run();
324        }
325    }
326
327    window.xLike = xLike;
328})();

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.