PageSourceSearch

https://aqua-plast.net/assets/components/msearch2/js/web/default.js

js aqua-plast.net collected 2026-10-08 03:18:28 UTC 44,100 bytes, 1,158 lines download raw bytes

1var mSearch2 = {
2    initialized: false,
3    loading: false,
4    reached: false,
5    options: {
6        wrapper: '#mse2_mfilter',
7
8        results: '#mse2_results',
9        total: '#mse2_total',
10        limit: '#mse2_limit',
11        slider: '.mse2_number_slider',
12
13        filters: '#mse2_filters',
14        filter_title: '.filter_title',
15        filter_wrapper: 'fieldset',
16
17        pagination: '.mse2_pagination',
18        pagination_link: '.mse2_pagination a',
19
20        sort: '#mse2_sort',
21        sort_link: '#mse2_sort a',
22
23        tpl: '#mse2_tpl',
24        tpl_link: '#mse2_tpl a',
25
26        selected: '#mse2_selected',
27        selected_tpl: '<a href="#" data-id="_id_" class="mse2_selected_link"><em>_title_</em><sup>x</sup></a>',
28        selected_wrapper_tpl: '<strong>_title_:</strong>',
29        selected_filters_delimeter: '; ',
30        selected_values_delimeter: ' ',
31
32        more: '.btn_more',
33        more_tpl: '<button class="btn btn-default btn_more">' + mse2Config['moreText'] + '</button>',
34
35        active_class: 'active',
36        disabled_class: 'disabled',
37        disabled_class_fieldsets: 'disabled_fieldsets',
38        loading_class: 'loading',
39        prefix: 'mse2_',
40        suggestion: 'sup', // inside filter item, e.g. #mse2_filters
41        autoLoad: true,
42    },
43    sliders: {},
44    selections: {},
45    elements: ['filters', 'results', 'pagination', 'total', 'sort', 'selected', 'limit', 'tpl'],
46    initialize: function (selector) {
47        if (this.initialized) {
48            return false;
49        }
50        var i;
51        if (mse2Config['filterOptions'] != undefined && Object.keys(mse2Config['filterOptions']).length > 0) {
52            for (i in mse2Config['filterOptions']) {
53                if (mse2Config['filterOptions'].hasOwnProperty(i)) {
54                    this.options[i] = mse2Config['filterOptions'][i];
55                }
56            }
57        }
58        for (i in this.elements) {
59            if (this.elements.hasOwnProperty(i)) {
60                var elem = this.elements[i];
61                this[elem] = $(selector).find(this.options[elem]);
62                if (!this[elem].length) {
63                    //console.log('Error: could not initialize element "' + elem + '" with selector "' + this.options[elem] + '".');
64                }
65            }
66        }
67        // Get ready for old chunk
68        if (this['pagination'].length == 0) {
69            this.options['pagination'] = '#mse2_pagination';
70            this.options['pagination_link'] = '#mse2_pagination a';
71            this['pagination'] = $(selector).find(this.options['pagination']);
72        }
73        this.handlePagination();
74        this.handleSort();
75        this.handleTpl();
76        this.handleSlider();
77        this.handleLimit();
78
79        var action = $(this.options.filters).attr('action');
80        var re = new RegExp(action + '$');
81
82        var submit = $(this.options.filters + ' [type="submit"]');
83        if (this.options.autoLoad) {
84            $(document).on('change', this.options.filters, function () {
85                return mSearch2.submit();
86            });
87            submit.addClass('hidden');
88        }
89        else {
90            submit.removeClass('hidden');
91        }
92
93        $(document).on('submit', this.options.filters, function () {
94            return mSearch2.submit();
95        });
96
97        this.btn_reset = $(this.options.filters + ' [type="reset"]');
98        $(document).on('reset', this.options.filters, function () {
99            return mSearch2.reset();
100        });
101        if (Object.keys(this.startParams).length) {
102            this.btn_reset.removeClass('hidden');
103        }
104
105        $(window).on('popstate', function (e) {
106            if (e.originalEvent.state && e.originalEvent.state['mSearch2']) {
107                var params = {};
108                var tmp = e.originalEvent.state['mSearch2'].split('?');
109                if (tmp[1]) {
110                    tmp = tmp[1].split('&');
111                    for (var i in tmp) {
112                        if (!tmp.hasOwnProperty(i)) {
113                            continue;
114                        }
115                        var tmp2 = tmp[i].split('=');
116                        params[tmp2[0]] = tmp2[1];
117                    }
118                }
119                mSearch2.setFilters(params);
120                mSearch2.load(params);
121            }
122        });
123        if (!mSearch2.Hash.oldbrowser()) {
124            history.replaceState({mSearch2: window.location.href}, '');
125        }
126
127        if (this.selected) {
128            this.selections[this.selected.text().replace(/\s+$/, '').replace(/:$/, '')] = [];
129            var selectors = [
130                this.options.filters + ' input[type="checkbox"]',
131                this.options.filters + ' input[type="radio"]',
132                this.options.filters + ' select'
133            ];
134            $(document).on('change', selectors.join(', '), function () {
135                mSearch2.handleSelected($(this));
136            });
137
138            selectors = [
139                'input[type="checkbox"]:checked',
140                'input[type="radio"]:checked',
141                'select'
142            ];
143            this.filters.find(selectors.join(', ')).each(function () {
144                mSearch2.handleSelected($(this));
145            });
146
147            $(document).on('click', this.options.selected + ' a', function () {
148                var id = $(this).data('id').replace(mse2Config.filter_delimeter, "\\" + mse2Config.filter_delimeter);
149                var elem = $('#' + id);
150                if (elem[0]) {
151                    switch (elem[0].tagName) {
152                        case 'INPUT':
153                            elem.attr('checked', false).trigger('change');
154                            break;
155                        case 'SELECT':
156                            elem.val(elem.find('option:first').prop('value')).trigger('change');
157                            break;
158                    }
159                }
160                return false;
161            });
162        }
163        mSearch2.setEmptyFieldsets();
164        mSearch2.setTotal(this.total.text());
165
166        this.initialized = true;
167    },
168
169    handlePagination: function () {
170        var pcre = new RegExp(mse2Config['pageVar'] + '[=|\/](\\d+)');
171        switch (mse2Config['mode']) {
172            case 'button':
173                this.pagination.hide();
174                // Add more button
175                this.results.after(this.options['more_tpl']);
176                var more = $(this.options['more']);
177
178                var has_results = false;
179                $(this.options['pagination_link']).each(function () {
180                    var href = $(this).prop('href');
181                    var match = href.match(pcre);
182                    var page = !match ? 1 : match[1];
183                    if (page > mse2Config['page']) {
184                        has_results = true;
185                        return false;
186                    }
187                });
188                if (!has_results) {
189                    more.hide();
190                }
191                if (mse2Config['page'] > 1) {
192                    mse2Config['page'] = '';
193                    mSearch2.Hash.remove('page');
194                    mSearch2.load();
195                }
196
197                $(document).on('click', this.options['wrapper'] + ' ' + this.options['more'], function (e) {
198                    e.preventDefault();
199                    mSearch2.addPage();
200                });
201                break;
202
203            case 'scroll':
204                this.pagination.hide();
205                var wrapper = $(this.options['wrapper']);
206                var $window = $(window);
207                $window.on('scroll', function () {
208                    if (!mSearch2.reached && $window.scrollTop() > wrapper.height() - $window.height()) {
209                        mSearch2.reached = true;
210                        mSearch2.addPage();
211                    }
212                });
213
214                if (mse2Config['page'] > 1) {
215                    mse2Config['page'] = '';
216                    mSearch2.Hash.remove('page');
217                    mSearch2.load();
218                }
219                break;
220
221            default:
222                $(document).on('click', this.options.pagination_link, function () {
223                    if (!$(this).hasClass(mSearch2.options.active_class)) {
224                        $(mSearch2.options.pagination).removeClass(mSearch2.options.active_class);
225                        $(this).addClass(mSearch2.options.active_class);
226
227                        var tmp = $(this).prop('href').match(pcre);
228                        var page = tmp && tmp[1] ? Number(tmp[1]) : 1;
229                        mse2Config.page = (page != mse2Config.start_page) ? page : '';
230
231                        var params = mSearch2.getFilters();
232                        mSearch2.Hash.set(params);
233                        mSearch2.load(params, function () {
234                            $('html, body').animate({
235                                scrollTop: $(mSearch2.options.wrapper).position().top || 0
236                            }, 0);
237                        });
238                    }
239
240                    return false;
241                });
242        }
243    },
244
245    handleSort: function () {
246        var params = this.Hash.get();
247        if (params.sort) {
248            var sorts = params.sort.split(mse2Config.values_delimeter);
249            for (var i = 0; i < sorts.length; i++) {
250                var tmp = sorts[i].split(mse2Config.method_delimeter);
251                if (tmp[0] && tmp[1]) {
252                    $(this.options.sort_link + '[data-sort="' + tmp[0] + '"]').data('dir', tmp[1]).attr('data-dir', tmp[1]).addClass(this.options.active_class);
253                }
254            }
255        }
256
257        $(document).on('click', this.options.sort_link, function () {
258            if ($(this).hasClass(mSearch2.options.active_class) && $(this).data('dir') == '') {
259                return false;
260            }
261            $(mSearch2.options.sort_link).removeClass(mSearch2.options.active_class);
262            $(this).addClass(mSearch2.options.active_class);
263            var dir;
264            if ($(this).data('dir') == '') {
265                dir = $(this).data('default');
266            }
267            else {
268                dir = $(this).data('dir') == 'desc'
269                    ? 'asc'
270                    : 'desc';
271            }
272            $(mSearch2.options.sort_link).data('dir', '').attr('data-dir', '');
273            $(this).data('dir', dir).attr('data-dir', dir);
274
275            var sort = $(this).data('sort');
276            if (dir) {
277                sort += mse2Config.method_delimeter + dir;
278            }
279            mse2Config.sort = (sort != mse2Config.start_sort) ? sort : '';
280            var params = mSearch2.getFilters();
281            if (mse2Config['page'] > 1 && (mse2Config['mode'] == 'scroll' || mse2Config['mode'] == 'button')) {
282                mse2Config['page'] = '';
283                delete(params['page']);
284            }
285            mSearch2.Hash.set(params);
286            mSearch2.load(params);
287
288            return false;
289        });
290    },
291
292    handleTpl: function () {
293        $(document).on('click', this.options.tpl_link, function () {
294            if (!$(this).hasClass(mSearch2.options.active_class)) {
295                $(mSearch2.options.tpl_link).removeClass(mSearch2.options.active_class);
296                $(this).addClass(mSearch2.options.active_class);
297
298                var tpl = $(this).data('tpl');
299                mse2Config.tpl = (tpl != mse2Config.start_tpl && tpl != 0) ? tpl : '';
300
301                var params = mSearch2.getFilters();
302                if (mse2Config['page'] > 1 && (mse2Config['mode'] == 'scroll' || mse2Config['mode'] == 'button')) {
303                    mse2Config['page'] = '';
304                    delete(params['page']);
305                }
306                mSearch2.Hash.set(params);
307                mSearch2.load(params);
308            }
309
310            return false;
311        });
312    },
313
314    handleSlider: function () {
315        if (!$(mSearch2.options.slider).length) {
316            return false;
317        }
318        else if (!$.ui || !$.ui.slider) {
319            return mSearch2.loadJQUI(mSearch2.handleSlider);
320        }
321        $(mSearch2.options.slider).each(function () {
322            var fieldset = $(this).parents('fieldset');
323            var imin = fieldset.find('input:first');
324            var imax = fieldset.find('input:last');
325            var vmin = Number(imin.val());
326            var vmax = Number(imax.val());
327            var $this = $(this);
328
329            $this.slider({
330                min: vmin,
331                max: vmax,
332                values: [vmin, vmax],
333                range: true,
334                //step: 0.1,
335                stop: function () {
336                    imin.val($this.slider('values', 0)/*.toFixed(2)*/);
337                    imax.val($this.slider('values', 1)/*.toFixed(2)*/);
338                    imin.trigger('change');
339                },
340                slide: function () {
341                    imin.val($this.slider('values', 0)/*.toFixed(2)*/);
342                    imax.val($this.slider('values', 1)/*.toFixed(2)*/);
343                }
344            });
345
346            var name = imin.prop('name');
347            var values = mSearch2.Hash.get();
348            if (values[name]) {
349                var tmp = values[name].split(mse2Config.values_delimeter);
350                if (tmp[0].match(/(?!^-)[^0-9\.]/g)) {
351                    tmp[0] = tmp[0].replace(/(?!^-)[^0-9\.]/g, '');
352                }
353                if (tmp.length > 1) {
354                    if (tmp[1].match(/(?!^-)[^0-9\.]/g)) {
355                        tmp[1] = tmp[1].replace(/(?!^-)[^0-9\.]/g, '');
356                    }
357                }
358                imin.val(tmp[0]);
359                imax.val(tmp.length > 1 ? tmp[1] : tmp[0]);
360            }
361
362            //imin.attr('readonly', true);
363            imin.on('change keyup input click', function (e) {
364                if (this.value.match(/(?!^-)[^0-9\.]/g)) {
365                    this.value = this.value.replace(/(?!^-)[^0-9\.]/g, '');
366                }
367                if (e.type != 'keyup' && e.type != 'input') {
368                    if (this.value > vmax) {
369                        this.value = vmax;
370                    }
371                    else if (this.value < vmin) {
372                        this.value = vmin;
373                    }
374                }
375                $this.slider('values', 0, this.value);
376            });
377            //imax.attr('readonly', true);
378            imax.on('change keyup input click', function (e) {
379                if (this.value.match(/(?!^-)[^0-9\.]/g)) {
380                    this.value = this.value.replace(/(?!^-)[^0-9\.]/g, '');
381                }
382                if (e.type != 'keyup' && e.type != 'input') {
383                    if (this.value > vmax) {
384                        this.value = vmax;
385                    }
386                    else if (this.value < vmin) {
387                        this.value = vmin;
388                    }
389                }
390                $this.slider('values', 1, this.value);
391            });
392
393            if (values[name]) {
394                imin.add(imax).trigger('click');
395            }
396
397            mSearch2.sliders[name] = [vmin, vmax];
398        });
399        return true;
400    },
401
402    handleLimit: function () {
403        $(document).on('change', this.options.limit, function () {
404            var limit = $(this).val();
405            mse2Config.page = '';
406            if (limit == mse2Config.start_limit) {
407                mse2Config.limit = '';
408            }
409            else {
410                mse2Config.limit = limit;
411            }
412            var params = mSearch2.getFilters();
413            if (mse2Config['page'] > 1 && (mse2Config['mode'] == 'scroll' || mse2Config['mode'] == 'button')) {
414                mse2Config['page'] = '';
415                delete(params['page']);
416            }
417            mSearch2.Hash.set(params);
418            mSearch2.load(params);
419        });
420    },
421
422    handleSelected: function (input) {
423        if (!input[0]) {
424            return;
425        }
426        var id = input.prop('id');
427        var title = '';
428        var elem;
429
430        var filter = input.parents(this.options['filter_wrapper']);
431        var filter_title = '';
432        var tmp;
433        if (filter.length) {
434            tmp = filter.find(this.options['filter_title']);
435            if (tmp.length > 0) {
436                filter_title = tmp.text();
437            }
438        }
439        if (filter_title == '') {
440            //noinspection LoopStatementThatDoesntLoopJS
441            for (filter_title in this.selections) {
442                break;
443            }
444        }
445
446        switch (input[0].tagName) {
447            case 'INPUT':
448                var label = mSearch2.filters.find('label[for="' + input.prop('id') + '"]');
449                var match = label.html().match(/>(.*?)</);
450                if (match && match[1]) {
451                    title = match[1].replace(/(\s+$)/, '');
452                }
453                $('[data-id="' + id + '"]', this.selected).remove();
454                if (input.is(':checked')) {
455                    elem = this.options['selected_tpl']
456                        .replace('[[+id]]', id).replace('[[+title]]', title)
457                        .replace('_id_', id).replace('_title_', title);
458                }
459                break;
460
461            case 'SELECT':
462                var option = input.find('option:selected');
463                $('[data-id="' + id + '"]', this.selected).remove();
464                if (input.val() != '') {
465                    title = ' ' + option.text().replace(/(\(.*\)$)/, '');
466                    elem = this.options['selected_tpl']
467                        .replace('[[+id]]', id).replace('[[+title]]', title)
468                        .replace('_id_', id).replace('_title_', title);
469                }
470                break;
471        }
472
473        if (elem != undefined) {
474            if (this.selections[filter_title] == undefined || input[0].type == 'radio') {
475                this.selections[filter_title] = {};
476            }
477            this.selections[filter_title][id] = elem;
478        }
479        else if (this.selections[filter_title] != undefined && this.selections[filter_title][id] != undefined) {
480            delete this.selections[filter_title][id];
481        }
482
483        this.selected.html('');
484        var count = 0;
485        var selected = [];
486        for (var i in this.selections) {
487            if (!this.selections.hasOwnProperty(i) || !Object.keys(this.selections).length) {
488                continue;
489            }
490            if (Object.keys(this.selections[i]).length) {
491                tmp = [];
492                for (var i2 in this.selections[i]) {
493                    if (!this.selections[i].hasOwnProperty(i2)) {
494                        continue;
495                    }
496                    tmp.push(this.selections[i][i2]);
497                    count++;
498                }
499                title = this.options['selected_wrapper_tpl']
500                    .replace('[[+title]]', i)
501                    .replace('_title_', i);
502                selected.push(title + tmp.join(this.options['selected_values_delimeter']));
503            }
504        }
505
506        if (count) {
507            this.selected.append(selected.join(this.options['selected_filters_delimeter'])).show();
508        }
509        else {
510            this.selected.hide();
511        }
512    },
513
514    load: function (params, callback, append) {
515        if (this.loading) {
516            return false;
517        } else {
518            this.loading = true;
519        }
520        if (Object.keys(params).length) {
521            this.btn_reset.removeClass('hidden');
522        } else {
523            this.btn_reset.addClass('hidden');
524        }
525        if (!params || !Object.keys(params).length) {
526            params = this.getFilters();
527        }
528        params.action = 'filter';
529        params.pageId = mse2Config.pageId;
530
531        this.beforeLoad();
532        params.key = mse2Config.key;
533        //noinspection JSUnresolvedFunction
534        $.post(mse2Config.actionUrl, params, function (response) {
535            mSearch2.loading = false;
536            mSearch2.afterLoad();
537            if (response.success) {
538                mSearch2.Message.success(response.message);
539                mSearch2.pagination.html(response.data['pagination']);
540                if (append) {
541                    mSearch2.results.append(response.data['results']);
542                }
543                else {
544                    mSearch2.results.html(response.data['results']);
545                }
546
547                if (mse2Config['mode'] == 'button') {
548                    if (response.data['pages'] == response.data['page']) {
549                        $(mSearch2.options['more']).hide();
550                    }
551                    else {
552                        $(mSearch2.options['more']).show();
553                    }
554                }
555                else if (mse2Config['mode'] == 'scroll') {
556                    mSearch2.reached = response.data['pages'] == response.data['page'];
557                }
558
559                mSearch2.setTotal(response.data.total);
560                if (callback && $.isFunction(callback)) {
561                    callback.call(this, response, params);
562                }
563                mSearch2.setSuggestions(response.data.suggestions);
564                mSearch2.setEmptyFieldsets();
565                if (response.data.log) {
566                    $('.mFilterLog').html(response.data.log);
567                }
568                mSearch2.updateTitle(response.data);
569                $(document).trigger('mse2_load', response);
570            }
571            else {
572                mSearch2.Message.error(response.message);
573            }
574        }, 'json');
575    },
576
577    getFilters: function () {
578        var params = {};
579        // Disabled friendly urls
580        var hash = this.Hash.get();
581        if (hash[mse2Config.idVar] != undefined) {
582            params[mse2Config.idVar] = hash[mse2Config.idVar];
583        }
584        // Other params
585        if (mse2Config[mse2Config.queryVar] != '') {
586            params[mse2Config.queryVar] = mse2Config[mse2Config.queryVar];
587        }
588        if (mse2Config[mse2Config.parentsVar] != '') {
589            params[mse2Config.parentsVar] = mse2Config[mse2Config.parentsVar];
590        }
591        if (mse2Config.sort != '') {
592            params.sort = mse2Config.sort;
593        }
594        if (mse2Config.tpl != '') {
595            params.tpl = mse2Config.tpl;
596        }
597        if (mse2Config.page > 0) {
598            params.page = mse2Config.page;
599        }
600        if (mse2Config.limit > 0) {
601            params.limit = mse2Config.limit;
602        }
603        // Filters
604        $.map(this.filters.serializeArray(), function (n) {
605            if (n['value'] === '') {
606                return;
607            }
608            if (params[n['name']]) {
609                params[n['name']] += mse2Config.values_delimeter + n['value'];
610            }
611            else {
612                params[n['name']] = n['value'];
613            }
614        });
615        for (var i in this.sliders) {
616            if (this.sliders.hasOwnProperty(i) && params[i]) {
617                if (this.sliders[i].join(mse2Config.values_delimeter) == params[i]) {
618                    delete params[i];
619                }
620            }
621        }
622
623        return params;
624    },
625
626    setFilters: function (params) {
627        if (!params) {
628            params = {};
629        }
630        for (var i in this.elements) {
631            if (!this.elements.hasOwnProperty(i)) {
632                continue;
633            }
634            var elem = this.elements[i];
635            if (typeof(this[elem]) == 'undefined') {
636                continue;
637            }
638            var item, name, values, val, type;
639            switch (elem) {
640                case 'limit':
641                    if (params['limit'] == undefined) {
642                        this.limit.val(mse2Config['start_limit']);
643                        mse2Config.limit = '';
644                    }
645                    else {
646                        this.limit.val(params['limit']);
647                    }
648                    break;
649                case 'pagination':
650                    mse2Config.page = params['page'] == undefined
651                        ? ''
652                        : params['page'];
653                    break;
654                case 'sort':
655                    var sorts = {};
656                    values = params['sort'];
657                    if (values == undefined) {
658                        values = mse2Config['start_sort'];
659                        mse2Config.sort = '';
660                    }
661                    if (typeof(values) != 'object' && values != '') {
662                        values = values.split(mse2Config['values_delimeter']);
663                        for (i in values) {
664                            if (!values.hasOwnProperty(i)) {
665                                continue;
666                            }
667                            name = values[i].split(mse2Config['method_delimeter']);
668                            if (name[0] && name[1]) {
669                                sorts[name[0]] = name[1];
670                            }
671                        }
672                    }
673                    $(document).find(this.options['sort_link']).each(function () {
674                        item = $(this);
675                        name = item.data('sort');
676                        if (sorts[name]) {
677                            item.data('dir', sorts[name]).attr('data-dir', sorts[name]);
678                            item.addClass(mSearch2.options['active_class']);
679                        }
680                        else {
681                            item.data('dir', '').attr('data-dir', '');
682                            item.removeClass(mSearch2.options['active_class']);
683                        }
684                    });
685                    break;
686                case 'tpl':
687                    values = params['tpl'] != undefined
688                        ? params['tpl']
689                        : 0;
690                    $(document).find(this.options['tpl_link']).each(function () {
691                        item = $(this);
692                        if (item.data('tpl') == values) {
693                            item.addClass(mSearch2.options['active_class']);
694                            mse2Config.tpl = values;
695                        }
696                        else {
697                            item.removeClass(mSearch2.options['active_class']);
698                        }
699                    });
700                    break;
701                case 'filters':
702                    this['filters'].find('input').each(function () {
703                        item = $(this);
704                        name = item.prop('name');
705                        type = item.prop('type');
706                        values = params[name];
707                        if (values != undefined && typeof(values) != 'object') {
708                            values = values.split(mse2Config['values_delimeter']);
709                        }
710                        switch (type) {
711                            case 'checkbox':
712                            case 'radio':
713                                var checked = item.is(':checked');
714                                if (params[name] != undefined) {
715                                    item.prop('checked', values.indexOf(String(item.val())) != -1);
716                                }
717                                else {
718                                    item.prop('checked', false);
719                                }
720                                if (item.is(':checked') != checked) {
721                                    mSearch2.handleSelected(item);
722                                }
723                                break;
724                            default:
725                                if (mSearch2.sliders[name]) {
726                                    if (item.prop('id').match(/.*?_0$/)) {
727                                        val = (values != undefined && values[0] != undefined)
728                                            ? values[0]
729                                            : mSearch2.sliders[name][0];
730                                    }
731                                    else {
732                                        val = (values != undefined && values[1] != undefined)
733                                            ? values[1]
734                                            : mSearch2.sliders[name][1];
735                                    }
736                                    if (val != item.val()) {
737                                        item.val(val).trigger('click');
738                                    }
739                                }
740                        }
741                    });
742                    this['filters'].find('select').each(function () {
743                        item = $(this);
744                        name = item.prop('name');
745                        type = item.prop('type');
746                        values = params[name];
747                        if (values != undefined) {
748                            if (typeof(values) != 'object') {
749                                values = values.split(mse2Config['values_delimeter']);
750                            }
751                            item.find('option').each(function () {
752                                var option = $(this);
753                                val = option.prop('value');
754                                var selected = option.is(':selected');
755                                $(this).prop('selected', values.indexOf(String(val)) != -1);
756                                if (option.is(':selected') != selected) {
757                                    mSearch2.handleSelected(item);
758                                }
759                            });
760                        }
761                        else {
762                            item.val('');
763                        }
764                        /*
765                         if (params[name] != undefined) {
766                         item.prop('checked', values.indexOf(String(item.val())) != -1);
767                         }
768                         else {
769                         item.prop('checked', false);
770                         }
771                         */
772                    });
773                    break;
774            }
775        }
776    },
777
778    setSuggestions: function (suggestions) {
779        var aliases = mse2Config.aliases || {};
780        for (var filter in suggestions) {
781            if (suggestions.hasOwnProperty(filter)) {
782                var arr = suggestions[filter];
783                if (typeof(aliases[filter]) != 'undefined') {
784                    filter = aliases[filter];
785                }
786                for (var value in arr) {
787                    if (arr.hasOwnProperty(value)) {
788                        var count = arr[value];
789                        var selector = filter.replace(mse2Config.filter_delimeter, "\\" + mse2Config.filter_delimeter);
790                        var input = $('#' + mSearch2.options.prefix + selector, mSearch2.filters).find('[value="' + value.replace(/&quot;/g, '\\"') + '"]');
791                        if (!input[0]) {
792                            continue;
793                        }
794
795                        switch (input[0].tagName) {
796                            case 'INPUT':
797                                var proptype = input.prop('type');
798                                if (proptype != 'checkbox' && proptype != 'radio') {
799                                    continue;
800                                }
801                                var label = $('#' + mSearch2.options.prefix + selector, mSearch2.filters).find('label[for="' + input.prop('id') + '"]');
802                                var elem = input.parent().find(mSearch2.options.suggestion);
803                                elem.text(count);
804
805                                if (count == 0) {
806                                    if (input.is(':not(:checked)')) {
807                                        input.prop('disabled', true);
808                                        label.addClass(mSearch2.options.disabled_class);
809                                        mSearch2.handleSelected(input);
810                                    }
811                                }
812                                else {
813                                    input.prop('disabled', false);
814                                    label.removeClass(mSearch2.options.disabled_class);
815                                }
816
817                                if (input.is(':checked')) {
818                                    elem.hide();
819                                }
820                                else {
821                                    elem.show();
822                                }
823                                break;
824
825                            case 'OPTION':
826                                var text = input.text();
827                                var matches = text.match(/\([^\)]+\)$/);
828                                var src = matches
829                                    ? matches[0]
830                                    : '';
831                                var dst = '';
832
833                                if (!count) {
834                                    input.prop('disabled', true).addClass(mSearch2.options.disabled_class);
835                                    /*
836                                     if (input.is(':selected')) {
837                                     input.prop('selected', false);
838                                     mSearch2.handleSelected(input);
839                                     }
840                                     */
841                                }
842                                else {
843                                    dst = ' (' + count + ')';
844                                    input.prop('disabled', false).removeClass(mSearch2.options.disabled_class);
845                                }
846
847                                if (input.is(':selected')) {
848                                    dst = '';
849                                }
850
851                                if (src) {
852                                    text = text.replace(src, dst);
853                                }
854                                else {
855                                    text += dst;
856                                }
857                                input.text(text);
858
859                                mSearch2.handleSelected(input.parent());
860                                break;
861                        }
862                    }
863                }
864            }
865        }
866    },
867
868    setEmptyFieldsets: function () {
869        this.filters.find('fieldset').each(function () {
870            var all_children_disabled = $(this).find('label:not(.' + mSearch2.options.disabled_class + ')').length == 0;
871            if (all_children_disabled) {
872                $(this).addClass(mSearch2.options.disabled_class_fieldsets);
873            }
874            if (!all_children_disabled && $(this).hasClass(mSearch2.options.disabled_class_fieldsets)) {
875                $(this).removeClass(mSearch2.options.disabled_class_fieldsets);
876            }
877        });
878    },
879
880    setTotal: function (total) {
881        if (this.total.length != 0) {
882            if (!total || total == 0) {
883                this.total.parent().hide();
884                this.limit.parent().hide();
885                this.sort.hide();
886                this.total.text(0);
887            }
888            else {
889                this.total.parent().show();
890                this.limit.parent().show();
891                this.sort.show();
892                this.total.text(total);
893            }
894        }
895    },
896
897    beforeLoad: function () {
898        $(this.options['wrapper']).addClass(this.options['loading_class']);
899        this.results.css('opacity', .5);
900        $(this.options.pagination_link).addClass(this.options.active_class);
901        this.filters.find('input, select').prop('disabled', true).addClass(this.options.disabled_class);
902    },
903
904    afterLoad: function () {
905        $(this.options['wrapper']).removeClass(this.options['loading_class']);
906        this.results.css('opacity', 1);
907        this.filters.find('.' + this.options.disabled_class).prop('disabled', false).removeClass(this.options.disabled_class);
908    },
909
910    loadJQUI: function (callback, parameters) {
911        $('<link/>', {
912            rel: 'stylesheet',
913            type: 'text/css',
914            href: mse2Config.cssUrl + 'redmond/jquery-ui-1.10.4.custom.min.css'
915        }).appendTo('head');
916
917        return $.getScript(mse2Config.jsUrl + 'lib/jquery-ui-1.10.4.custom.min.js', function () {
918            if (typeof callback == 'function') {
919                callback(parameters);
920            }
921        });
922    },
923
924    submit: function (params) {
925        if (this.loading) {
926            return false;
927        }
928        else if (!params || !Object.keys(params).length) {
929            params = this.getFilters();
930        }
931        else {
932            delete(params['action']);
933            delete(params['key']);
934            delete(params['pageId']);
935        }
936        delete(params['page']);
937
938        var action = $(this.options.filters).attr('action');
939        if (!mSearch2.options.autoLoad) {
940            var vars = '';
941            for (var i in params) {
942                if (params.hasOwnProperty(i)) {
943                    vars += '&' + i + '=' + params[i];
944                }
945            }
946            if (!action.match(/\?/)) {
947                document.location = action + vars.replace(/^&/, '?');
948            }
949            else {
950                document.location = action + vars;
951            }
952            return false;
953        }
954        else {
955            mse2Config.page = '';
956            mSearch2.Hash.set(params);
957            mSearch2.load(params);
958            return false;
959        }
960    },
961
962    reset: function () {
963        if (this.loading) {
964            return false;
965        }
966        this.Hash.clear();
967        this.setFilters();
968
969        return this.submit();
970    },
971
972    addPage: function () {
973        var pcre = new RegExp(mse2Config['pageVar'] + '[=|\/](\\d+)');
974        var current = mse2Config['page'] || 1;
975        $(this.options['pagination_link']).each(function () {
976            var href = $(this).prop('href');
977            var match = href.match(pcre);
978            var page = !match ? 1 : Number(match[1]);
979            if (page > current) {
980                mse2Config.page = (page != mse2Config.start_page) ? page : '';
981                var tmp = mSearch2.getFilters();
982                delete(tmp['page']);
983                mSearch2.Hash.set(tmp);
984
985                var params = mSearch2.getFilters();
986                mSearch2.load(params, null, true);
987                return false;
988            }
989        });
990    },
991
992    updateTitle: function (response) {
993        if (typeof(pdoTitle) == 'undefined') {
994            return;
995        }
996        var $title = $('title');
997        var separator = pdoTitle.separator || ' / ';
998        var tpl = pdoTitle.tpl;
999
1000        var title = [];
1001        var items = $title.text().split(separator);
1002        var pcre = new RegExp('^' + tpl.split(' ')[0] + ' ');
1003        for (var i = 0; i < items.length; i++) {
1004            if (i === 1 && response.page && response.page > 1) {
1005                title.push(tpl.replace('{page}', response.page).replace('{pageCount}', response.pages));
1006            }
1007            if (!items[i].match(pcre)) {
1008                title.push(items[i]);
1009            }
1010        }
1011        $title.text(title.join(separator));
1012    },
1013
1014};
1015
1016mSearch2.Form = {
1017    initialized: false,
1018    initialize: function (selector) {
1019        if (this.initialized || typeof(mse2FormConfig) == 'undefined') {
1020            return false;
1021        }
1022        $(selector).each(function () {
1023            var form = $(this);
1024            var config = mse2FormConfig[form.data('key')];
1025            var cache = {};
1026
1027            if (config.autocomplete == '0' || config.autocomplete == 'false') {
1028                return false;
1029            }
1030            else if (!$.ui || !$.ui.autocomplete) {
1031                return mSearch2.loadJQUI(mSearch2.Form.initialize, selector);
1032            }
1033
1034            form.find('input[name="' + config.queryVar + '"]').autocomplete({
1035                source: function (request, callback) {
1036                    if (request.term in cache) {
1037                        callback(cache[request.term]);
1038                        return;
1039                    }
1040                    var data = {
1041                        action: 'search',
1042                        key: form.data('key'),
1043                        pageId: config.pageId
1044                    };
1045                    data[config.queryVar] = request.term;
1046                    //noinspection JSUnresolvedFunction
1047                    $.post(mse2Config.actionUrl, data, function (response) {
1048                        if (response.data.log) {
1049                            $('.mSearchFormLog').html(response.data.log);
1050                        }
1051                        else {
1052                            $('.mSearchFormLog').html('');
1053                        }
1054                        cache[request.term] = response.data.results;
1055                        callback(response.data.results)
1056                    }, 'json');
1057                },
1058                minLength: config.minQuery || 3,
1059                select: function (event, ui) {
1060                    if (ui.item.url) {
1061                        document.location.href = ui.item.url;
1062                    }
1063                    else {
1064                        setTimeout(function () {
1065                            form.submit();
1066                        }, 100);
1067                    }
1068                }
1069            }).data("ui-autocomplete")._renderItem = function (ul, item) {
1070                return $("<li></li>")
1071                    .data("item.autocomplete", item)
1072                    .addClass("mse2-ac-wrapper")
1073                    .append("<a class=\"mse2-ac-link\">" + item.label + "</a>")
1074                    .appendTo(ul);
1075            };
1076            return true;
1077        });
1078        this.initialized = true;
1079    }
1080};
1081
1082mSearch2.Message = {
1083    success: function (message) {
1084    },
1085    error: function (message) {
1086        alert(message);
1087    }
1088};
1089
1090mSearch2.Hash = {
1091    get: function () {
1092        var vars = {}, hash, splitter, hashes;
1093        if (!this.oldbrowser()) {
1094            var pos = window.location.href.indexOf('?');
1095            hashes = (pos != -1) ? decodeURIComponent(window.location.href.substr(pos + 1)) : '';
1096            splitter = '&';
1097        }
1098        else {
1099            hashes = decodeURIComponent(window.location.hash.substr(1));
1100            splitter = '/';
1101        }
1102
1103        if (hashes.length == 0) {
1104            return vars;
1105        }
1106        else {
1107            hashes = hashes.split(splitter);
1108        }
1109
1110        for (var i in hashes) {
1111            if (hashes.hasOwnProperty(i)) {
1112                hash = hashes[i].split('=');
1113                if (typeof hash[1] == 'undefined') {
1114                    vars['anchor'] = hash[0];
1115                }
1116                else {
1117                    vars[hash[0]] = hash[1];
1118                }
1119            }
1120        }
1121        return vars;
1122    },
1123    set: function (vars) {
1124        var hash = '';
1125        for (var i in vars) {
1126            if (vars.hasOwnProperty(i)) {
1127                hash += '&' + i + '=' + vars[i];
1128            }
1129        }
1130        if (!this.oldbrowser()) {
1131            if (hash.length != 0) {
1132                hash = '?' + hash.substr(1);
1133            }
1134            window.history.pushState({mSearch2: document.location.pathname + hash}, '', document.location.pathname + hash);
1135        }
1136        else {
1137            window.location.hash = hash.substr(1);
1138        }
1139    },
1140    add: function (key, val) {
1141        var hash = this.get();
1142        hash[key] = val;
1143        this.set(hash);
1144    },
1145    remove: function (key) {
1146        var hash = this.get();
1147        delete hash[key];
1148        this.set(hash);
1149    },
1150    clear: function () {
1151        this.set({});
1152    },
1153    oldbrowser: function () {
1154        return !(window.history && history.pushState);
1155    }
1156};
1157
1158mSearch2.startParams = mSearch2.Hash.get();

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.