PageSourceSearch

https://cargo.sale/js/tygh/product_filters.js?ver=1789552927

js cargo.sale collected 2026-09-25 20:16:56 UTC 17,332 bytes, 449 lines download raw bytes

1(function (_, $) {
2  var base_url;
3  var ajax_ids;
4  var no_trigger = false;
5  var changed_objects = [];
6  var filtered_tables_state = {};
7  var dropdowns_state = {};
8  var cursorState = {};
9  var ajax_promise;
10  var timer;
11  var timerStatusBox;
12  var lastSelectedElms = {};
13  var HASH_SEPARATOR = '_';
14  var HASH_FEATURE_SEPARATOR = '-';
15  var REQUEST_DELAY = 1000;
16  var HIDE_DELAY = 5000;
17  (function ($) {
18    function generateHash(container) {
19      var features = {};
20      var hash = [];
21      container.find('input.cm-product-filters-checkbox:checked').each(function () {
22        var elm = $(this);
23        if (!features[elm.data('caFilterId')]) {
24          features[elm.data('caFilterId')] = [];
25        }
26        features[elm.data('caFilterId')].push(elm.val());
27      });
28      for (var k in features) {
29        hash.push(k + HASH_FEATURE_SEPARATOR + features[k].join(HASH_FEATURE_SEPARATOR));
30      }
31      return hash.join(HASH_SEPARATOR);
32    }
33    function resetFilters(obj) {
34      obj.prop('checked', !obj.prop('checked'));
35      if (obj.data('prevVal')) {
36        no_trigger = true;
37        var vals = obj.data('prevVal').split('-');
38        var sli = obj.parent().find('.cm-range-slider');
39        if (sli.length) {
40          sli.slider('values', [vals[0], vals[1]]);
41          sli.slider('option', 'slide').call(sli, {}, {
42            values: [vals[0], vals[1]]
43          }); // that's so dirty, but it works
44        }
45        var da = obj.parent().find('.cm-date-range');
46        if (da.length) {
47          da.daterangepicker({
48            startDate: vals[0],
49            endDate: vals[1]
50          });
51        }
52        no_trigger = false;
53      }
54    }
55    function getProducts(url, obj, objs, container) {
56      if (ajax_ids) {
57        loadProducts(url, obj, objs, container);
58      } else {
59        $.redirect(url);
60      }
61      return false;
62    }
63    function loadProducts(url, obj, objs, container) {
64      saveFilteredTablesState(container);
65      saveDropdownsState(container);
66      saveCursorState();
67      ajax_promise = $.ceAjax('request', url, {
68        result_ids: ajax_ids,
69        full_render: true,
70        save_history: true,
71        get_promise: true,
72        hidden: true,
73        caching: false,
74        obj: obj
75      });
76      ajax_promise.done(function (response) {
77        moveScrollToLastPosition(container);
78        if (response.products_found_message) {
79          var $checkboxContainer = $('#' + obj.attr('id')).closest('.cm-product-filters-checkbox-container');
80          showTooltip($checkboxContainer, response.products_found_message);
81        }
82        changed_objects = [];
83        setVisibilityResetFilters(container);
84      });
85    }
86    function moveScrollToLastPosition($container) {
87      if ($container && $container.hasClass('cm-filter-table-no-scroll')) {
88        return;
89      }
90      for (const [key, scrollTop] of Object.entries(lastSelectedElms)) {
91        let $variantList = $('#' + key);
92        if (!$variantList.length || $variantList.get(0).scrollHeight <= $variantList.get(0).clientHeight) {
93          continue;
94        }
95        $variantList.scrollTop(scrollTop);
96      }
97    }
98    function saveDropdownsState($container) {
99      dropdowns_state = {};
100      $container.find('.cm-horizontal-filters-content').each(function () {
101        var $elem = $(this);
102        dropdowns_state[$elem.attr('id')] = {
103          open: $elem.is(':visible')
104        };
105      });
106    }
107    function restoreDropdownsState($container) {
108      $container.find('.cm-horizontal-filters-content').each(function () {
109        var $elem = $(this),
110          id = $elem.attr('id');
111        if (dropdowns_state[id] && dropdowns_state[id].open) {
112          $elem.removeClass('hidden');
113          $('#sw_' + id).addClass('open');
114          delete dropdowns_state[id];
115        }
116      });
117    }
118    function restoreVariantsState($productFilters) {
119      $('.cm-save-state', $productFilters).each(function () {
120        var $elem = $(this);
121        var id = $elem.attr('id');
122        var prefix = 'sw_';
123        if (!id.startsWith(prefix)) {
124          return;
125        }
126        var combination_id = id.substr(prefix.length);
127        if (!$.cookie.get(combination_id) || $elem.hasClass('cm-ss-reverse') && !$elem.hasClass('open')) {
128          return;
129        }
130        $.toggleCombination($elem);
131      });
132    }
133    function saveFilteredTablesState($container) {
134      filtered_tables_state = {};
135      $container.find('.cm-filter-table').each(function () {
136        var $elem = $(this),
137          $input = $('#' + $elem.data('caInputId'));
138        filtered_tables_state[$elem.attr('id')] = {
139          top: $elem.scrollTop(),
140          input_value: $input.val()
141        };
142      });
143    }
144    function restoreFilteredTablesState($container) {
145      $container.find('.cm-filter-table').each(function () {
146        var $elem = $(this),
147          id = $elem.attr('id');
148        if (filtered_tables_state[id]) {
149          $elem.scrollTop(filtered_tables_state[id].top);
150          $elem.data('caInputValue', filtered_tables_state[id].input_value);
151          $elem.data('caScrollTop', filtered_tables_state[id].top);
152          delete filtered_tables_state[id];
153        }
154      });
155    }
156    function saveCursorState() {
157      cursorState = {};
158      var $focused = $(':focus');
159      if (!$focused.length) {
160        return;
161      }
162      cursorState.id = $focused.attr('id');
163      cursorState.type = $focused.attr('type');
164      if (cursorState.type === 'text') {
165        cursorState.val = $focused.val();
166        cursorState.selectionStart = $focused[0].selectionStart;
167        cursorState.selectionEnd = $focused[0].selectionEnd;
168      }
169    }
170    function restoreCursorState() {
171      if (!cursorState.id) {
172        return;
173      }
174      var $activeElem = $('#' + cursorState.id);
175      $activeElem.focus();
176      if (cursorState.type !== 'text') {
177        return;
178      }
179      var activeElem = $activeElem[0];
180      if ($activeElem.val() === cursorState.val) {
181        activeElem.setSelectionRange(cursorState.selectionStart, cursorState.selectionEnd);
182      } else {
183        activeElem.selectionStart = activeElem.selectionEnd = activeElem.value.length;
184      }
185    }
186    function setVisibilityResetFilters($filters) {
187      var $wrapperFilter = $filters.find('[data-ca-product-filters="wrapper"]');
188      var $toolsFilter = $filters.find('[data-ca-product-filters="tools"]');
189      if ($wrapperFilter.data('caProductFiltersStatus') === 'active') {
190        $toolsFilter.removeClass('hidden');
191      } else {
192        $toolsFilter.addClass('hidden');
193      }
194    }
195    function abortRequest() {
196      if (ajax_promise) {
197        ajax_promise.abort();
198      }
199      clearTimeout(timer);
200      clearTimeout(timerStatusBox);
201      $.toggleStatusBox('hide');
202    }
203    function setHandler() {
204      $(_.doc).on('click', '.ty-product-filters__reset-button', function () {
205        lastSelectedElms = {};
206      });
207      $(_.doc).on('click', '.ty-product-filters__block--variants .ty-reset-filters', function () {
208        let $parent = $(this).closest('.ty-product-filters__block'),
209          $variantsList = $parent.find('.ty-product-filters__variants');
210        if ($variantsList.length) {
211          let idVariantList = $variantsList.attr('id');
212          delete lastSelectedElms[idVariantList];
213        }
214      });
215      $(_.doc).on('change', '.cm-product-filters-checkbox:enabled', function () {
216        if (no_trigger) {
217          return;
218        }
219        if (ajax_promise) {
220          ajax_promise.abort();
221        }
222        var $self = $(this),
223          $parent = $self.closest('.cm-filter-table'),
224          variantListId = $parent.attr('id');
225        changed_objects.push($self);
226        lastSelectedElms[variantListId] = $parent.scrollTop();
227        clearTimeout(timer);
228        $.toggleStatusBox('show', {
229          show_overlay: false
230        });
231        timer = setTimeout(function () {
232          prepareGetProducts.apply($self);
233        }, REQUEST_DELAY);
234      });
235      $(_.doc).on('ce:combination:switch', '.cm-product-filters .cm-combination', function (event, container, flag) {
236        if (!flag) {
237          return;
238        }
239        var $tooltip = $(container).find('[data-ce-tooltip="true"]');
240        if ($tooltip.data('tooltip')) {
241          $tooltip.data('tooltip').getTip().remove();
242          $tooltip.remove();
243          ;
244        }
245      });
246    }
247    function prepareGetProducts() {
248      var self = $(this);
249      var container = self.parents('.cm-product-filters');
250      return getProducts($.attachToUrl(base_url, 'features_hash=' + generateHash(container)), self, changed_objects, container);
251    }
252    function showTooltip($container, message) {
253      if (!$container.is(':visible')) {
254        return;
255      }
256      var $filters = $container.closest('.cm-product-filters');
257      var tooltipClass = $filters.data('caTooltipClass');
258      var tooltipRightClass = $filters.data('caTooltipRightClass');
259      var tooltipMobileClass = $filters.data('caTooltipMobileClass');
260      var tooltipLayoutSelector = $filters.data('caTooltipLayoutSelector');
261      var tooltipEventsTooltip = $filters.data('ceTooltipEventsTooltip');
262      var containerFirstChild = $container.children(':first-child');
263      var tooltipPosition = 'centerRight';
264      var isRightOffsetCheckboxContainer = $(window).width() - ($container.offset().left + $container.outerWidth()) < $container.offset().left;
265      if (Tygh.language_direction !== 'rtl' && isRightOffsetCheckboxContainer || Tygh.language_direction === 'rtl' && !isRightOffsetCheckboxContainer) {
266        tooltipPosition = 'centerLeft';
267        tooltipClass += ' ' + tooltipRightClass;
268      }
269      var $tooltip = $('<div/>', {
270        title: message,
271        'data-ce-tooltip': true,
272        'data-ce-tooltip-position': tooltipPosition,
273        'data-ca-tooltip-layout-selector': tooltipLayoutSelector,
274        'data-ce-tooltip-events-tooltip': tooltipEventsTooltip,
275        'class': tooltipClass,
276        html: '&#8203;',
277        height: containerFirstChild ? containerFirstChild.outerHeight() : ''
278      });
279      $tooltip.prependTo($container).ceTooltip({
280        onShow: function () {
281          var $trigger = this.getTrigger();
282          var triggerRect = $trigger[0].getBoundingClientRect();
283          var $tip = this.getTip();
284          if (Tygh.language_direction === 'rtl') {
285            var checkboxContainer = $tooltip.closest('.ty-product-filters').length > 0 ? $tooltip.closest('.ty-product-filters') : $tooltip;
286            $tip.css({
287              left: isRightOffsetCheckboxContainer ? checkboxContainer.offset().left - $tip.outerWidth(true) + 'px' : checkboxContainer.offset().left + checkboxContainer.outerWidth(true) + 'px'
288            });
289          }
290
291          // Set tooltip position when scrolling.
292          var $filterBlock = $trigger.closest('.cm-filter-table');
293          if ($filterBlock.length > 0) {
294            var topFilterBlockPosition = $filterBlock.position().top;
295            var bottomFilterBlockPosition = $filterBlock.position().top + $filterBlock.outerHeight();
296            if ($tip.position().top > bottomFilterBlockPosition) {
297              $tip.css({
298                top: bottomFilterBlockPosition - $tip.outerHeight() + 'px'
299              });
300            } else if ($tip.position().top < topFilterBlockPosition) {
301              $tip.css({
302                top: $filterBlock.position().top + 'px'
303              });
304            }
305          }
306        }
307      }).ceTooltip('show').on('onHide', function () {
308        $tooltip.data('tooltip').getTip().remove();
309        $tooltip.remove();
310      });
311      var isMobile = $('body').hasClass('screen--xs') || $('body').hasClass('screen--xs-large') || $('body').hasClass('screen--sm');
312      if (isMobile) {
313        $('.tooltip').addClass(tooltipMobileClass);
314      }
315      setTimeout(function () {
316        $tooltip.ceTooltip('hide').remove();
317      }, HIDE_DELAY);
318    }
319    function setCallback() {
320      // re-init filters
321      $.ceEvent('on', 'ce.commoninit', function (context) {
322        var $productFilters = $('.cm-product-filters', context);
323        if (context.is('.cm-product-filters')) {
324          $productFilters = $productFilters.add(context);
325        }
326        initSlider(context);
327        if (context && (context.is(document) || context.hasClass('cm-product-filters'))) {
328          $('.cm-filter-table').on('scroll', $.debounce(function (e) {
329            let $self = $(this),
330              variantListId = $self.attr('id');
331            lastSelectedElms[variantListId] = $self.scrollTop();
332          }, 100));
333          moveScrollToLastPosition();
334        }
335        if (!$productFilters.length) {
336          return;
337        }
338        $productFilters.each(function () {
339          var self = $(this);
340          if (self.data('caBaseUrl')) {
341            base_url = self.data('caBaseUrl');
342            ajax_ids = self.data('caTargetId');
343          }
344          setVisibilityResetFilters(self);
345        });
346        restoreDropdownsState(context);
347        restoreFilteredTablesState(context);
348        restoreCursorState();
349        restoreVariantsState($productFilters);
350        var $color_filter_selectors = context.find('[data-cm-product-color-filter="true"]:has(.cm-product-filters-checkbox:enabled)');
351        if ($color_filter_selectors.length) {
352          $color_filter_selectors.on('click touch', function (e) {
353            var $color_filter_selector = $(this),
354              dependent_checkbox_id = $color_filter_selector.data('caProductColorFilterCheckboxId'),
355              $dependent_checkbox = $('#' + dependent_checkbox_id);
356            $color_filter_selector.toggleClass('selected');
357            $dependent_checkbox.prop('checked', !$dependent_checkbox.prop('checked'));
358            $dependent_checkbox.trigger('change');
359          });
360        }
361      });
362      $.ceEvent('on', 'ce.filterdate', function (elm, time_from, time_to) {
363        var cb = $('#elm_checkbox_' + elm.prop('id'));
364        cb.data('prevVal', cb.val());
365        cb.val(time_from + '-' + time_to).prop('checked', true).trigger('change');
366      });
367    }
368    function initSlider(parent) {
369      parent.find('.cm-range-slider').each(function () {
370        var $el = $(this);
371        var id = $el.prop('id');
372        var json_data = $('#' + id + '_json').val();
373        if ($el.data('uiSlider') || !json_data) {
374          return false;
375        }
376        var data = $.parseJSON(json_data) || null;
377        if (!data) {
378          return false;
379        }
380        $el.slider({
381          disabled: data.disabled,
382          range: true,
383          min: data.min,
384          max: data.max,
385          step: data.step,
386          values: [data.left, data.right],
387          slide: function (event, ui) {
388            abortRequest();
389            $('#' + id + '_left').val(ui.values[0]);
390            $('#' + id + '_right').val(ui.values[1]);
391          },
392          change: function (event, ui) {
393            abortRequest();
394            var statusBoxDelay = REQUEST_DELAY;
395            var loadDelay = REQUEST_DELAY * 3;
396
397            // If the slider is dragged, remove the delay.
398            if (event.handleObj) {
399              loadDelay = statusBoxDelay = REQUEST_DELAY / 3;
400            }
401            timerStatusBox = setTimeout(function () {
402              $.toggleStatusBox('show', {
403                show_overlay: false
404              });
405            }, statusBoxDelay);
406            var replacement = ui.values[0] + '-' + ui.values[1];
407            if (data.extra) {
408              replacement = replacement + '-' + data.extra;
409            }
410            var $checkbox = $('#elm_checkbox_' + id);
411            timer = setTimeout(function () {
412              $checkbox.data('prevVal', $checkbox.val());
413              $checkbox.val(replacement).prop('checked', true).trigger('change');
414            }, loadDelay);
415          },
416          start: function (event, ui) {
417            abortRequest();
418          }
419        });
420        if (data.left != data.min || data.right != data.max) {
421          var replacement = data.left + '-' + data.right;
422          if (data.extra) {
423            replacement = replacement + '-' + data.extra;
424          }
425          $('#elm_checkbox_' + id).val(replacement).prop('checked', true);
426        }
427        $('#' + id + '_left, #' + id + '_right').off('change input focus').on('change input focus', function () {
428          var $inputsContainer = $(this).closest('.cm-product-filters-checkbox-container');
429          var $inputLeft = $inputsContainer.find('#' + id + '_left');
430          var $inputRight = $inputsContainer.find('#' + id + '_right');
431          var inputLeftValue = _.toNumeric($inputLeft.val());
432          var inputRightValue = _.toNumeric($inputRight.val());
433          if (inputLeftValue === $inputLeft.data('caPreviousValue') && inputRightValue === $inputRight.data('caPreviousValue')) {
434            abortRequest();
435            return;
436          }
437          $inputLeft.data('previousValue', inputLeftValue);
438          $inputRight.data('previousValue', inputRightValue);
439          $el.slider('values', [inputLeftValue, inputRightValue]);
440        });
441        if ($el.parents('.filter-wrap').hasClass('open')) {
442          $el.parent('.price-slider').show();
443        }
444      });
445    }
446    setCallback();
447    setHandler();
448  })($);
449})(Tygh, Tygh.$);

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.