PageSourceSearch

https://atwitch.ru/catalog/view/javascript/ocfilter/ocfilter.js

js atwitch.ru collected 2026-10-07 12:01:01 UTC 15,789 bytes, 514 lines download raw bytes

1// https://codepen.io/martinAnsty/pen/BCotE
2Math.easeIn = function (val, min, max, strength) {
3	val /= max;
4
5	return (max - 1) * Math.pow(val, strength) + min;
6};
7
8(function($) {
9  function setSlider(_, target) {
10    var
11      that = this,
12      $element = $(target),
13      min = parseFloat($element.data().rangeMin),
14      max = parseFloat($element.data().rangeMax),
15      decimals = 0,
16      elementMin,
17      elementMax,
18      controlMin,
19      controlMax,
20      _options = {
21        behaviour: 'drag-tap',
22        connect: true,
23        range: {
24          'min': min,
25          'max': max
26        }
27      };
28
29    // Logarithmic scale
30    if ($element.data().optionId == 'p' && (max - min) > 100) {
31      _options['pips'] = {
32        mode: 'range',
33    		density: 4
34    	};
35
36      var _i = 25, _strength = 3.5;
37
38      if ((max - min) < 100) {
39        _strength = 2;
40      }
41
42      for (; _i < 100; _i += 25) {
43        _options['range'][_i + '%'] = Math.ceil(Math.easeIn(((max - min) / 100 * _i), min, max, _strength));
44      }
45    } else {
46      _options['pips'] = {
47        mode: 'count',
48        values: 3,
49    		density: 4
50    	};
51    }
52
53    if (max && min != max) {
54      _options['start'] = [ parseFloat($element.data().startMin), parseFloat($element.data().startMax) ];
55    } else {
56      _options['start'] = parseFloat($element.data().startMin);
57    }
58
59    // Decimal
60    if (/\./.test($element.data().rangeMin) || /\./.test($element.data().rangeMax)) {
61      decimals = Math.max(
62        $element.data().rangeMin.toString().replace(/^\d+?\./, '').length,
63        $element.data().rangeMax.toString().replace(/^\d+?\./, '').length
64      );
65    }
66
67    _options['format'] = {
68  	  to: function (value) {
69  		  return parseFloat(value).toFixed(decimals);
70  	  },
71  	  from: function (value) {
72  		  return parseFloat(value).toFixed(decimals);
73  	  }
74  	};
75
76  	noUiSlider.create($element.get(0), _options);
77
78    if ($element.data().elementMin && $($element.data().elementMin).length) {
79      elementMin = $($element.data().elementMin);
80    }
81
82    if ($element.data().elementMax && $($element.data().elementMax).length) {
83      elementMax = $($element.data().elementMax);
84    }
85
86    $element.get(0).noUiSlider.on('slide', function(values, handle, noformat) {
87      if (typeof values[0] != 'undefined') {
88        if (elementMin) {
89          elementMin.html(values[0]);
90        }
91
92        if ($element.data().controlMin && $($element.data().controlMin).length) {
93          $($element.data().controlMin).val(noformat[0].toFixed(decimals));
94        }
95      }
96
97      if (typeof values[1] != 'undefined') {
98        if (elementMax) {
99          elementMax.html(values[1]);
100        }
101
102        if ($element.data().controlMax && $($element.data().controlMax).length) {
103          $($element.data().controlMax).val(noformat[1].toFixed(decimals));
104        }
105      }
106    });
107
108    $element.get(0).noUiSlider.on('change', function(_, __, values, tap, positions) {
109      that.params.remove.call(that, $element.data().optionId);
110
111      if ((positions[1] - positions[0]) < 100) {
112        that.params.set.call(that, $element.data().optionId, values[0].toFixed(decimals) + '-' + values[1].toFixed(decimals));
113      }
114
115      that.update($element);
116    });
117
118    if ($element.data().controlMin) {
119      that.$element.on('change', $element.data().controlMin, function(e) {
120        if (this.value == '') {
121          return false;
122        }
123
124        if (this.value < min || this.value > max) {
125          this.value = min;
126        }
127
128        $element.get(0).noUiSlider.set([this.value, null]);
129      });
130    }
131
132    if ($element.data().controlMax) {
133      that.$element.on('change', $element.data().controlMax, function(e) {
134        if (this.value == '') {
135          return false;
136        }
137
138        if (this.value < min || this.value > max) {
139          this.value = max;
140        }
141
142        $element.get(0).noUiSlider.set([null, this.value]);
143      });
144    }
145  };
146
147  var ocfilter = {
148    timers: {},
149    values: {},
150    options: {},
151    init: function(options) {
152      this.options = $.extend({}, options);
153
154      this.$element = $('#ocfilter');
155
156      this.$fields = $('.option-values input', this.$element);
157
158      this.$target = $('.ocf-target', this.$element);
159      this.$values = $('label', this.$element);
160
161      var that = this;
162
163      this.$values.each(function() {
164        that.values[$(this).attr('id')] = this;
165      });
166
167      this.$target.on('change', function(e) {
168        e.preventDefault();
169
170        var
171          $element = $(this),
172          $buttonTarget = $element.closest('label'),
173          $dropdown = $element.closest('.dropdown');
174
175        that.options.php.params = $element.val();
176
177        if ($element.is(':radio')) {
178          $element.closest('.ocf-option-values').find('label.ocf-selected').removeClass('ocf-selected');
179        }
180
181        $buttonTarget.toggleClass('ocf-selected', $element.prop('checked'));
182
183        that.update($buttonTarget);
184      });
185
186      this.$element.on('click.ocf', '.dropdown-menu', function(e) {
187        $(this).closest('.dropdown').one('hide.bs.dropdown', function(e) {
188          return false;
189        });
190      });
191
192      this.$element.on('click.ocf', '.disabled, [disabled]', function(e) {
193        e.stopPropagation();
194        e.preventDefault();
195      });
196
197      var hovered = false;
198
199      this.$element.on({
200        'mouseenter': function(e) {
201          hovered = true;
202        },
203        'mouseleave': function(e) {
204          hovered = false;
205
206          $('[aria-describedby="' + $(this).attr('id') + '"]').popover('toggle');
207        }
208      }, '.popover').on('hide.bs.popover', '[aria-describedby^="popover"]', function(e) {
209        setTimeout(function(element) {
210          $(element).show();
211        }, 0, e.target);
212
213        if (hovered) {
214          e.preventDefault();
215        }
216      });
217
218      this.$element.find('.dropdown').on('hide.bs.dropdown', function(e) {
219        that.$element.find('[aria-describedby^="popover"]').popover('hide');
220      });
221
222      if (this.options.php.manualPrice) {
223        $('[data-toggle=\'popover-price\']').popover({
224          content: function() {
225            return '' +
226              '<div class="form-inline">' +
227                '<div class="form-group">' +
228                  '<input name="price[min]" value="' + $('#price-from').text() + '" type="text" class="form-control input-sm" id="min-price-value" />' +
229                '</div>' +
230                '<div class="form-group">-</div>' +
231                '<div class="form-group">' +
232                  '<input name="price[max]" value="' + $('#price-to').text() + '" type="text" class="form-control input-sm" id="max-price-value" />' +
233                '</div>' +
234              '</div>';
235          },
236          html: true,
237          delay: { 'show': 700, 'hide': 500 },
238          placement: 'top',
239          container: '#ocfilter',
240          title: 'Указать цену',
241          trigger: 'hover'
242        });
243      }
244
245      // Set sliders
246      $('#ocfilter .scale').each($.proxy(setSlider, this));
247    },
248
249    update: function(scrollTarget) {
250      var
251        that = this,
252        isSlider = scrollTarget.hasClass('scale'),
253        data = {
254          path: this.options.php.path,
255          option_id: scrollTarget.data().optionId
256        };
257
258      if (this.options.php.params) {
259        data[this.options.php.index] = this.options.php.params;
260      }
261
262      this.preload();
263
264      $.get('index.php?route=extension/module/ocfilter/callback', data, function(json) {
265        /* Start update */
266        for (var i in json.values) {
267          var value = json.values[i],
268            target = $(that.values['v-' + i]),
269            total = value.t,
270            selected = value.s,
271            params = value.p;
272
273          if (target.length > 0) {
274            if (target.is('label')) {
275              if (total === 0 && !selected) {
276                target.addClass('disabled').removeClass('ocf-selected').find('input').attr('disabled', true).prop('checked', false);
277              } else {
278                target.removeClass('disabled').find('input').removeAttr('disabled');
279              }
280
281              $('input', target).val(params);
282
283              if (that.options.php.showCounter) {
284                $('small', target).text(total);
285              }
286            } else {
287              target.prop('disabled', (total === 0)).val(params);
288            }
289          }
290        }
291
292        if (json.total === 0) {
293          $('#ocfilter-button button').removeAttr('onclick').addClass('disabled').text(that.options.text.select);
294
295          if (typeof scrollTarget != 'undefined' && scrollTarget.hasClass('scale')) {
296            $('#ocfilter .scale').removeAttr('disabled');
297          }
298        } else {
299          if (that.options.php.searchButton || isSlider) {
300            $('#ocfilter-button button').attr('onclick', 'location = \'' + json.href + '\'').removeClass('disabled').text(json.text_total);
301
302            //$('#ocfilter .scale').removeAttr('disabled');
303          } else {
304            window.location = json.href;
305
306            return;
307          }
308        }
309
310        that.$fields.filter('.enabled').removeAttr('disabled');
311
312        if (typeof scrollTarget != 'undefined') {
313          that.scroll(scrollTarget);
314        }
315
316        if (isSlider) {
317          scrollTarget.removeAttr('disabled');
318        }
319
320        if (!$.isPlainObject(json.sliders) || $.isEmptyObject(json.sliders)) {
321          return;
322        }
323
324        for (var option_id in json.sliders) {
325          var
326            $element = $('.scale[data-option-id="' + option_id + '"]').removeAttr('disabled'),
327            slider = $element.get(0).noUiSlider,
328            hasParam = that.params.has.call(that, option_id),
329            min = parseFloat(json.sliders[option_id]['min']),
330            max = parseFloat(json.sliders[option_id]['max']),
331            min_value = min,
332            max_value = max,
333            set = slider.get();
334
335          if (!$.isArray(set)) {
336            set = [set, set];
337          }
338
339          if (hasParam) {
340            if (set[1] <= max) {
341              max_value = set[1];
342            }
343
344            if (set[0] >= min) {
345              min_value = set[0];
346            }
347          }
348
349          if (min != max) {
350            slider.destroy();
351
352            $element.data({
353              startMin: min_value,
354              startMax: max_value,
355              rangeMin: min,
356              rangeMax: max
357            });
358
359            if ($element.data().controlMin && $($element.data().controlMin).length) {
360              $($element.data().controlMin).val(min_value);
361            }
362
363            if ($element.data().controlMax && $($element.data().controlMax).length) {
364              $($element.data().controlMax).val(max_value);
365            }
366
367            if ($element.data().elementMin && $($element.data().elementMin).length) {
368              $($element.data().elementMin).html(min_value);
369            }
370
371            if ($element.data().elementMax && $($element.data().elementMax).length) {
372              $($element.data().elementMax).html(max_value);
373            }
374
375            setSlider.call(that, 0, $element.get(0));
376          } else {
377            $element.attr('disabled', 'disabled');
378          }
379        }
380        /* End update */
381      }, 'json');
382    },
383
384    params: {
385      decode: function() {
386        var params = {};
387        if (this.options.php.params) {
388          var matches = this.options.php.params.split(';');
389          for (var i = 0; i < matches.length; i++) {
390            var parts = matches[i].split(':');
391            params[parts[0]] = typeof parts[1] != 'undefined' ? parts[1].split(',') : [];
392          }
393        }
394        this.options.php.params = params;
395      },
396
397      encode: function() {
398        var params = [];
399        if (this.options.php.params) {
400          for (i in this.options.php.params) {
401            params.push(i + ':' + (typeof this.options.php.params[i] == 'object' ? this.options.php.params[i].join(',') : this.options.php.params[i]));
402          }
403        }
404        this.options.php.params = params.join(';');
405      },
406
407      set: function(option_id, value_id) {
408        this.params.decode.call(this);
409        if (typeof this.options.php.params[option_id] != 'undefined') {
410          this.options.php.params[option_id].push(value_id);
411        } else {
412          this.options.php.params[option_id] = [value_id];
413        }
414        this.params.encode.call(this);
415      },
416
417      has: function(option_id) {
418        this.params.decode.call(this);
419
420        var has = (typeof this.options.php.params[option_id] != 'undefined');
421
422        this.params.encode.call(this);
423
424        return has;
425      },
426
427      remove: function(option_id, value_id) {
428        this.params.decode.call(this);
429        if (typeof this.options.php.params[option_id] != 'undefined') {
430          if (this.options.php.params[option_id].length === 1 || !value_id) {
431            delete this.options.php.params[option_id];
432          } else {
433            this.options.php.params[option_id].splice(ocfilter.options.php.params[option_id].indexOf(value_id), 1);
434          }
435        }
436        this.params.encode.call(this);
437      }
438    },
439
440    preload: function() {
441      if ($('.ocfilter-option-popover').length) {
442        $('.ocfilter-option-popover button').button('loading');
443      }
444
445      this.$element.find('.scale').attr('disabled', 'disabled');
446      setTimeout(function(that) {
447        that.$values.addClass('disabled').find('small').text('0');
448      }, 10, this);
449    },
450
451    scroll: function(target) {
452      var that = this;
453
454      if (target.find('input:checked').length < 1 && target.parent().find('input:checked').length > 0) {
455        target = target.parent().find('input:checked:first').parent();
456      }
457
458      if (that.options.mobile && target.is('label')) {
459        target = target.find('input');
460      }
461
462      if (target.is(':hidden')) {
463        target = target.parents(':visible:first');
464      }
465
466      this.$element
467        .find('[aria-describedby^="popover"]')
468        .not('[data-toggle="popover-price"]')
469        .not(target)
470        .popover('destroy');
471
472      if (!target.attr('aria-describedby')) {
473        var options = {
474          placement: that.options.mobile ? 'bottom' : 'right',
475          selector: that.options.mobile ? '> input' : false,
476          delay: { 'show': 400, 'hide': 600 },
477          content: function() {
478            return $('#ocfilter-button').html();
479          },
480          container: that.$element,
481          trigger: 'hover',
482          html: true
483        };
484
485        target.popover(options).popover('show');
486
487        $('#' + target.attr('aria-describedby')).addClass('ocfilter-option-popover');
488      } else {
489        $('#' + target.attr('aria-describedby') + ' button').replaceWith($('#ocfilter-button').html());
490      }
491    }
492  };
493
494  /* IE6+ */
495  if (Object.create === undefined) {
496    Object.create = function(object) {
497      function f() {};
498      f.prototype = object;
499      return new f();
500    };
501  }
502
503  $.fn.ocfilter = function(options) {
504    return this.each(function() {
505      var $element = $(this);
506
507      if ($element.data('ocfilter')) {
508        return $element.data('ocfilter');
509      }
510
511      $element.data('ocfilter', Object.create(ocfilter).init(options, $element));
512    });
513  };
514})(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.