PageSourceSearch

https://valvesale.ru/catalog/view/javascript/mf/mega_filter.js?v2.0.4.4.5.1

js valvesale.ru collected 2026-10-07 22:26:00 UTC 86,037 bytes, 3,301 lines download raw bytes

1/**
2 * Mega Filter
3 */
4
5if( typeof Array.prototype.indexOf == 'undefined' ) {
6	Array.prototype.indexOf = function(obj, start) {
7		for( var i = ( start || 0 ), j = this.length; i < j; i++ ) {
8			if( this[i] === obj ) {return i;}
9		}
10		
11		return -1;
12   };
13};
14
15var MegaFilterINSTANCES = typeof MegaFilterINSTANCES == 'undefined' ? [] : MegaFilterINSTANCES;
16
17var MegaFilter = function(){ };
18
19MegaFilter.prototype = {
20	
21	/**
22	 * Kontener filtrów
23	 */
24	_box: null,
25			
26	/**
27	 * Opcje
28	 */
29	_options: null,
30			
31	/**
32	 * @var int
33	 */
34	_timeoutAjax: null,
35	
36	_timeoutSearchFiled: null,
37		
38	/**
39	* @var string
40	*/
41	_url			: null,
42	
43	/**
44	 * Separator URL
45	 * 
46	 * @var string
47	 */
48	_urlSep			: null,
49	
50	/**
51	 * Lista parametrów
52	 *
53	 * @var object
54	 */
55	_params			: null,
56	
57	/**
58	 * Lista scrolls
59	 * 
60	 * @var array
61	 */
62	_scrolls		: null,
63	
64	/**
65	 * Lista guzików
66	 * 
67	 * @var array
68	 */
69	_buttonsMore	: null,
70	
71	_liveFilters	: null,
72	
73	/**
74	 * Kontener główny
75	 *
76	 * @var jQuery
77	 */
78	_jqContent		: null,
79		
80	/**
81	 * Loader over results
82	 *
83	 * @var jQuery
84	 */
85	_jqLoader		: null,
86	
87	/**
88	 * Loader over filter
89	 * 
90	 * @var jQuery
91	 */
92	_jqLoaderFilter	: null,
93	
94	/**
95	 * Slidery
96	 * 
97	 * @type array
98	 */
99	_sliders		: null,
100		
101	/**
102	 * ID kontenera głównego
103	 *
104	 * @var string
105	 */
106	_contentId		: '#content',
107	
108	/**
109	 * Trwa oczekiwanie na odpowiedź serwera
110	 * 
111	 * @var bool
112	 */
113	_busy			: false,
114	
115	/**
116	 * W trakcie ładowania danych z serwra wprowadzono zmiany
117	 * 
118	 * @var bool
119	 */
120	_waitingChanges	: false,
121	
122	/**
123	 * Ostania odpowiedź serwera
124	 * 
125	 * @var string
126	 */
127	_lastResponse	: '',
128	
129	_refreshPrice : function(){},
130	
131	_inUrl : null,
132	
133	_isInit: false,
134	
135	_cache: null,
136	
137	_relativeScroll: null,
138	
139	_selectOptions: null,
140	
141	_lastUrl: null,
142	
143	_urlToFilters: null,
144	
145	_instanceIdx: 0,
146	
147	_inlineHorizontalUpdate: null,
148	
149	_lastEvent: null,
150	
151	_startUrl: null,
152	
153	_history: 1,
154	
155	_changed: false,
156	
157	_ajaxPagination: null,
158	
159	////////////////////////////////////////////////////////////////////////////
160	
161	/**
162	 * Inicjuj klasę
163	 */
164	init: function( box, options ) {
165		var self = this,
166			i;
167		
168		self._instanceIdx = MegaFilterINSTANCES.length;
169			
170		if( options.routeHome == options.route && options.homePageAJAX ) {
171			self._contentId = options.homePageContentSelector;
172		} else if( options.contentSelector ) {
173			self._contentId = options.contentSelector;
174		}
175		
176		self._jqContent	= jQuery(self._contentId);
177		self._options	= options;
178		
179		if( ! self._jqContent.length ) {
180			self._contentId = '#maincontent';
181			
182			self._jqContent	= jQuery(self._contentId);
183		}
184		
185		if( self._startUrl === null ) {
186			self._startUrl = self.location();
187		}
188		
189		self._scrolls					= [];
190		self._buttonsMore				= [];
191		self._liveFilters				= [];
192		self._sliders					= [];
193		self._inlineHorizontalUpdate	= [];
194		self._box						= box;
195		self._selectOptions				= {};
196		self._cache						= {
197			'lastResponse'	: {},
198			'mainContent'	: {}
199		};
200		
201		self.initResponsive();
202		
203		if( self._options.manualInit && ! self._isInit ) {
204			var items = self._box.find('> .mfilter-content').find('> ul,> div').hide(),
205				$init = jQuery('<a href="#" style="padding: 10px; text-align: center; display: block;">' + self._options.text.init_filter + '</a>').appendTo( self._box.find('> .mfilter-content') );
206			
207			$init.click(function(){
208				$init.text( self._options.text.initializing );
209				
210				setTimeout(function(){
211					items.show();
212					self.boot();
213					$init.remove();
214				},100);
215				
216				return false;
217			});
218		} else {
219			self.boot();
220		}
221		
222		return self;
223	},
224	
225	boot: function() {
226		var self = this,
227			i;
228		
229		self.initUrls();
230
231		for( i in self._options.params ) {
232			if( typeof self._options.params[i] == 'function' ) continue;
233
234			if( typeof self._params[i] == 'undefined' ) {
235				self._params[i] = self._options.params[i];
236			}
237		}
238
239		self.initSliders();
240
241		//var t = this.microtime(true);
242		for( i in self ) {
243			if( i.indexOf( '_init' ) === 0 ) {
244				self[i]();
245			}
246		}
247		//alert(this.microtime(true)-t);
248		self._isInit = true;
249	},
250	
251	microtime: function(get_as_float) {
252		var now = new Date()
253			.getTime() / 1000;
254		var s = parseInt(now, 10);
255
256		return (get_as_float) ? now : (Math.round((now - s) * 1000) / 1000) + ' ' + s;
257	},
258
259	keys: function( obj ) {
260		var keys = [];
261		
262		for( var i in obj ) {
263			keys.push( i );
264		}
265		
266		return keys;
267	},
268	
269	base64_decode: function(data) {
270		var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
270+/=';
271		var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
272		  ac = 0,
273		  dec = '',
274		  tmp_arr = [];
275
276		if (!data) {
277		  return data;
278		}
279
280		data += '';
281
282		do { // unpack four hexets into three octets using index points in b64
283		  h1 = b64.indexOf(data.charAt(i++));
284		  h2 = b64.indexOf(data.charAt(i++));
285		  h3 = b64.indexOf(data.charAt(i++));
286		  h4 = b64.indexOf(data.charAt(i++));
287
288		  bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
289
290		  o1 = bits >> 16 & 0xff;
291		  o2 = bits >> 8 & 0xff;
292		  o3 = bits & 0xff;
293
294		  if (h3 == 64) {
295			tmp_arr[ac++] = String.fromCharCode(o1);
296		  } else if (h4 == 64) {
297			tmp_arr[ac++] = String.fromCharCode(o1, o2);
298		  } else {
299			tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
300		  }
301		} while (i < data.length);
302
303		dec = tmp_arr.join('');
304
305		return dec.replace(/\0+$/, '');
306	},
307	
308	sortKeys: function( data ) {
309		var keys = [],
310			sortData = [],
311			i;
312			
313		for( i in data ) {
314			sortData.push( [ i, data[i] ] );
315		}
316		
317		sortData.sort(function(a,b){
318			var sa = typeof a[1].sort_order == 'undefined' ? 0 : a[1].sort_order,
319				sb = typeof b[1].sort_order == 'undefined' ? 0 : b[1].sort_order;
320			
321			if( sa > sb ) {
322				return 1;
323			} else if( sa < sb ) {
324				return -1;
325			}
326			
327			return 0;
328		});
329		
330		for( i = 0; i < sortData.length; i++ ) {
331			keys.push( sortData[i][0] );
332		}
333		
334		return keys;
335	},
336	
337	/**
338	 * Inicjuj slidery
339	 * 
340	 * @return void
341	 */
342	initSliders: function(){
343		var self = this,
344			_init = false;
345		
346		function d( txt ) {
347			var $i = jQuery('<div>').html( txt ),
348				txt2 = $i.text();
349			$i.remove();
350			return txt2;
351		}		
352		
353		self._box.find('li.mfilter-filter-item.mfilter-slider').each(function(i){
354			var _this		= jQuery(this).attr('data-slider-id', i),
355				seo_name	= _this.attr('data-seo-name'),
356				data		= jQuery.parseJSON(self.base64_decode(_this.find('.mfilter-slider-data').html())),
357				$min		= _this.find('.mfilter-opts-slider-min'),
358				$max		= _this.find('.mfilter-opts-slider-max'),
359				$slider		= _this.find('.mfilter-slider-slider'),
360				update		= false,
361				keys, values, map;
362			
363			function init( data, update ) {
364				if( update ) {
365					return;
366				}
367				
368				keys	= self.sortKeys( data );
369				
370				if( _init ) {
371					if( ! keys.length ) {
372						$slider.slider().slider('disable');
373
374						return;
375					} else {
376						$slider.slider().slider('enable');
377					}
378				}
379				
380				if( keys.length == 1 ) {
381					data['copy'] = data[keys[0]];
382					keys.push('copy');
383				}
384				
385				var filters = /*update ? self.filters() :*/ self.urlToFilters();
386				
387				values	= typeof filters[seo_name] != 'undefined' ? (function(){ 
388					var d = [];
389					
390					for( var i = 0; i < filters[seo_name].length; i++ ) {
391						d[i] = self.decode( decodeURIComponent( filters[seo_name][i] ) );
392					} 
393					
394					return d;
395				})() : [ data[keys[0]].key, data[keys[keys.length-1]].key ];
396				map		= (function(){
397					var m = [ keys.indexOf( values[0] ), keys.indexOf( values[values.length-1] ) ];
398
399					if( m[0] != -1 && m[1] != -1 ) {
400						return typeof filters[seo_name] == 'undefined' ? [ 0, keys.length-1 ] : m;
401					}
402
403					for( var i = 0; i < keys.length; i++ ) {
404						if( m[0] == -1 ) {
405							if( values[0] == d( data[keys[i]].value ) ) {
406								m[0] = i;
407							}
408						} else if( m[1] == -1 ) {
409							if( values[values.length-1] == d( data[keys[i]].value ) ) {
410								m[1] = typeof data['copy'] == 'undefined' ? i : ( typeof filters[seo_name] == 'undefined' ? 1 : m[0] );
411							}
412						} else {
413							break;
414						}
415					}
416					
417					if( m[0] == -1 ) {
418						m[0] = 0;
419					}
420
421					if( m[1] == -1 ) {
422						m[1] = m[0];//keys.length-1;
423					}
424
425					return m;
426				})();
427				
428				$min.attr('data-key',map[0]).attr('data-min',0).val( d( data[keys[map[0]]].name ) );
429				$max.attr('data-key',map[1]).attr('data-max',keys.length-1).val( d( data[keys[map[1]]].name ) );
430				
431				$slider.slider({
432					range	: true,
433					min		: 0,
434					max		: keys.length-1,
435					values	: map,
436					slide	: function( e, ui ) {
437						if( typeof keys[ui.values[0]] == 'undefined' || typeof data[keys[ui.values[0]]] == 'undefined' )
438							return;
439						
440						if( typeof keys[ui.values[1]] == 'undefined' || typeof data[keys[ui.values[1]]] == 'undefined' )
441							return;
442						
443						$min.attr('data-key',ui.values[0]).val( d( data[keys[ui.values[0]]].name ) );
444						$max.attr('data-key',ui.values[1]).val( d( data[keys[ui.values[1]]].name ) );
445					},
446					stop	: function( e, ui ) {
447						update = true;
448						
449						if( self._options['refreshResults'] != 'using_button' ) {
450							self.runAjax();
451						}
452					}
453				});
454				
455				if( _init ) {
456					$slider.slider( 'value', $slider.slider('value') );
457				}
458				
459				_init = true;
460			}
461			
462			init( data );
463			
464			var s_idx = self._sliders.length;
465			
466			self._sliders.push({
467				data: data,
468				init: function( data, update ) {
469					init( data, update );
470				},
471				resetValues: function(){					
472					data = self._sliders[s_idx].data;
473					keys = self.sortKeys( data );
474					
475					$min.attr('data-key',0).attr('data-min',0).val( d( data[keys[map[0]]].name ) );
476					$max.attr('data-key',keys.length-1).attr('data-max',keys.length-1).val( d( data[typeof keys[map[1]] != 'undefined' ? keys[map[1]] : keys[map[0]]].name ) );
477					
478					$slider.slider( 'option', 'min', parseInt( $min.attr('data-min') ) );
479					$slider.slider( 'option', 'max', parseInt( $max.attr('data-max') ) );
480					$slider.slider( 'option', 'values', [
481						$min.attr('data-min'),
482						$max.attr('data-max')
483					]);
484					$slider.slider( 'value', $slider.slider( 'value' ) );
485					
486					update = true;
487				},
488				setValues: function(){
489					var vals = $slider.slider('values');
490					
491					$min.attr('data-key',vals[0]).val( d( data[keys[vals[0]]].name ) );
492					$max.attr('data-key',vals[1]).val( d( data[typeof keys[map[1]] != 'undefined' ? keys[map[1]] : keys[map[0]]].name ) );
493				},
494				getValues: function(){
495					if( $min.attr('data-key') == $min.attr('data-min') && $max.attr('data-key') == $max.attr('data-max') && self.keys( data ).length == self.keys( self._sliders[s_idx].data ).length ) {
496						return [];
497					}
498					
499					var min		= parseInt( $min.attr('data-key') ),
500						max		= parseInt( $max.attr('data-key') ),
501						vals	= [];
502					
503					for( var i = min; i <= max; i++ ) {
504						var key = keys[i];
505						
506						if( ! key ) continue;
507						
508						if( typeof data[key] == 'undefined' ) {
509							key = keys[0];
510						}
511						
512						vals.push( encodeURIComponent( self.encode( d( data[key].value ) ) ) );
513					}
514					
515					return vals;
516				}
517			});
518		});
519	},
520	
521	initResponsive: function(){
522		var self	= this,
523			column	= null,
524			moved	= false,
525			hidden	= true;
526	
527		if( self._box.hasClass( 'mfilter-hide-container' ) ) {
528			column = self._box.parent();
529			self._box.removeClass( 'mfilter-content_top mfilter-modern-horizontal mfilter-hide' );
530		} else if( self._box.hasClass( 'mfilter-column_left' ) ) {
531			column = jQuery('#column-left');
532		} else if( self._box.hasClass( 'mfilter-column_right' ) ) {
533			column = jQuery('#column-right');
534		} else {
535			return;
536		}
537		
538		var id = 'mfilter-free-container-' + jQuery('[id^="mfilter-free-container"]').length,
539			cnt = jQuery('<div class="mfilter-free-container mfilter-free-container-closed mfilter-direction-' + self._options.direction + '">')
540				.prependTo( jQuery('body') ),
541			btn = jQuery('<div class="mfilter-free-button">')
542				.appendTo( cnt )
543				.click(function(){
544					if( hidden ) {
545						cnt.animate(self._options.direction == 'rtl' ? {
546							'marginRight' : 0
547						} : {
548							'marginLeft' : 0
549						}, 500, function(){
550							self._relativeScroll.refresh();
551							cnt.addClass('mfilter-free-container-opened').removeClass('mfilter-free-container-closed');
552						});
553					} else {
554						cnt.animate(self._options.direction == 'rtl' ? {
555							'marginRight' : - ( cnt.outerWidth(true)<cnt.outerWidth()?cnt.outerWidth():cnt.outerWidth(true) )
556						} : {
557							'marginLeft' : - cnt.outerWidth(true)
558						}, 500, function(){
559							cnt.addClass('mfilter-free-container-closed').removeClass('mfilter-free-container-opened');
560						});
561					}
562			
563					hidden = ! hidden;
564				}),
565			cnt2 = jQuery('<div>')
566				.css('overflow','hidden')
567				.attr('id', id)
568				.appendTo( cnt ),
569			cnt3 = jQuery('<div>')
570				.appendTo( cnt2 ),
571			src = jQuery('<span class="mfilter-before-box">');
572		
573		function reinit() {
574			var scroll = new IScroll( '#' + id, {
575				bounce: false,
576				scrollbars: true,
577				mouseWheel: true,
578				interactiveScrollbars: true,
579				mouseWheelSpeed: 120
580			});
581			
582			scroll.reinit = function(){
583				if( ! cnt.hasClass('mfilter-free-container-opened') ) return;
584				
585				var top = $('#' + id + ' > div:first').attr('style');
586						
587				if( typeof top != 'undefined' ) {
588					top = top.match(/translate\(([\-0-9]+)px, ([\-0-9]+)px\)/);
589				}
590				
591				self._relativeScroll.destroy();
592				
593				self._relativeScroll = reinit();
594				
595				if( top && typeof top[1] != 'undefined' && typeof top[2] != 'undefined' ) {
596					self._relativeScroll.scrollTo( parseInt( top[1] ), parseInt( top[2] ) );
597				}
598			};
599			
600			return scroll;
601		}
602	
603		self._relativeScroll = reinit();
604		
605		self._box.before( src );
606		
607		if( ! column.length )
608			column = self._box.parent();
609		
610		function isVisible() {
611			var visible = column.is(':visible'),
612				height	= jQuery(window).height() - 50;
613			
614			if( visible && moved ) {
615				cnt.hide();
616				
617				src.after( self._box );
618				
619				if( ! hidden )
620					btn.trigger('click');
621				
622				moved = false;
623			} else if( ! visible && ! moved ) {
624				cnt.show();
625				
626				cnt3.append( self._box );
627				
628				moved = true;
629			}
630			
631			if( moved ) {
632				cnt2.css( 'max-height', height + 'px' );
633				self._relativeScroll.refresh();
634			}
635		}
636		
637		jQuery(window).resize(function() {
638			isVisible();
639		});
640		
641		isVisible();
642	},
643	
644	location: function(){
645		var self = this,
646			url = document.location.href.toString();
647		
648		if( self._options.seo.alias != '' ) {
649			url = url.replace( '/' + encodeURIComponent( self._options.seo.alias ), '' );
650		}
651		
652		return url;
653	},
654	
655	locationPath: function(){
656		var self = this,
657			location = self.location();
658		
659		return decodeURIComponent( self.parse_url( location ).path ).replace( /\/mfp,([a-z0-9\-_]+\[[^\]]*\],?)+/g, '' );
660	},
661	
662	initUrls: function( url ) {
663		var self = this;
664
665		if( typeof url == 'undefined' ) {
666			url	 = self.location().split('#')[0];
667		}
668		
669		self._urlSep	= self._parseSep( url ).urlSep;
670		self._url		= self._parseSep( url ).url;
671		self._params	= self._parseUrl( url );
672		self._inUrl		= self._parseUrl( url );
673	},
674	
675	_initMfImage: function() {
676		var self = this;
677		
678		self._box.find('.mfilter-image input').change(function(){
679			var s = jQuery(this).is(':checked'),
680				t = jQuery(this).attr('type');
681				
682			if( t == 'radio' ) {
683				jQuery(this).parent().parent().find('.mfilter-image-checked').removeClass('mfilter-image-checked');
684			}
685			
686			jQuery(this).parent()[s?'addClass':'removeClass']('mfilter-image-checked');
687		});
688		
689		self._box.find('.mfilter-image input:checked').parent().addClass('mfilter-image-checked');
690	},
691	
692	__initTreeCategoryEvents: function() {
693		var self = this,
694			$path = self._box.find('input[name="path"]');
695		
696		self._box.find('li.mfilter-filter-item.mfilter-tree.mfilter-categories')[self._box.find('.mfilter-category-tree > ul > li').length?'show':'hide']();
697			
698		self._box.find('.mfilter-category-tree').each(function(){
699			var _this = jQuery(this),
700				ul = _this.find('> ul'),
701				top_url = ul.attr('data-top-url'),
702				top_path = ul.attr('data-top-path').split('_');
703		
704			_this.find('.mfilter-to-parent a').unbind('click').bind('click', function(){
705				var parts = (jQuery(this).attr('data-path')?jQuery(this).attr('data-path'):$path.val()).split('_');
706
707				parts.pop();
708
709				if( top_url != '' && parts.length <= top_path.length ) {
710					window.location.href = self.createUrl(top_url);
711				} else {
712					$path.val( parts.join('_') );
713
714					self.runAjax();
715				}
716
717				return false;
718			});
719				
720			_this.find('a[data-parent-id]').click(function(){
721				if( self._busy ) return false;
722
723				var id = jQuery(this).attr('data-id'),
724					path = $path.val(),
725					parts = path.split('_'),
726					last = parts[parts.length-1].split(',');
727					
728				self._cache['cat_'+id] = jQuery(this).text();
729				
730				if( last.indexOf( id ) == -1 ) {				
731					if( path != '' ) {
732						path += '_';
733					}
734
735					path += id;
736				
737					$path.val( path );
738				}
739				
740				self.runAjax();
741
742				return false;
743			});
744		});
745	},
746	
747	_initTreeCategory: function( force ) {
748		var self = this,
749			$path = self._box.find('input[name="path"]');
750		
751		if( self._isInit && force !== true ) {
752			self.__initTreeCategoryEvents();
753			
754			return;
755		}
756		
757		if( ! $path.val() && ! self._isInit ) {
758			if( typeof self._options.params.mfp_path != 'undefined' ) {
759				$path.val( self._options.params.mfp_path );
760			} else if( typeof self._options.params.mfp_org_path != 'undefined' ) {
761				$path.val( self._options.params.mfp_org_path );
762			} else if( typeof self._options.params.path != 'undefined' ) {
763				$path.val( self._options.params.path );
764			}
765		}
766		
767		self._box.find('.mfilter-category-tree').each(function(){
768			if( $path.val().indexOf( '_' ) > -1 || ( $path.val() && ! self._options.params.path ) || ( $path.val() && self._options.route != self._options.routeCategory ) ) {
769				jQuery(this).find('ul').prepend(jQuery('<li class="mfilter-to-parent">')
770					.append(jQuery('<a>')
771						.html((function(){
772							var parts = $path.val().split('_'),
773								cat = parts[parts.length-1];
774							
775							return typeof self._cache['cat_'+cat] != 'undefined' ? self._cache['cat_'+cat] : self._options.text.go_to_top;
776						}))
777					)
778				);
779			}
780		});
781		
782		self.__initTreeCategoryEvents();
783	},
784	
785	_initBox: function() {
786		var self = this;
787		
788		if( self._isInit ) return;
789		
790		if( self._box.hasClass( 'mfilter-content_top' ) ) {
791			self._box.find('.mfilter-content > ul > li').each(function(i){
792				if( i && i % 4 == 0 ) {
793					jQuery(this).before('<li style="clear:both; display:block;"></li>');
794				}
795			});
796		}
797	},
798	
799	_initTextFields: function() {
800		var self = this;
801		
802		self._box.find('.mfilter-filter-item.mfilter-text').each(function(){
803			var _this	= jQuery(this),
804				name	= _this.attr('data-seo-name'),
805				input	= _this.find('input[type=text]');
806				
807			function clear() {
808				if( self._cache['txt_field_'+name] ) {
809					clearTimeout( self._cache['txt_field_'+name] );
810				}
811				
812				self._cache['txt_field_'+name] = null;
813			}
814				
815			input.bind('keydown', function(e){
816				if( e.keyCode == 13 ) {
817					clear();
818					
819					self.ajax();
820					
821					return false;
822				}
823			}).bind('keyup.mf_shv', function(){
824				input[input.val()?'addClass':'removeClass']('mfilter-text-has-value');
825			}).bind('keyup', function(e){
826				clear();
827				
828				if( self._options['refreshResults'] != 'using_button' ) {
829					self._cache['txt_field_'+name] = setTimeout(function(){
830						self.ajax();
831
832						self._cache['txt_field_'+name] = null;
833					}, 1000);
834				}
835			}).trigger('keyup.mf_shv');
836		});
837	},
838	
839	_initSearchFiled: function() {
840		var self = this,
841			searchField = self._box.find('input[id="mfilter-opts-search"]'),
842			searchButton = self._box.find('[id="mfilter-opts-search_button"]');
843			
844		if( ! searchField.length )
845			return;
846			
847		var refreshDelay = parseInt( searchField.unbind('keyup keydown click').attr('data-refresh-delay').toString().replace(/[^0-9\-]+/, '') ),
848			lastValue = searchField.val();
849		
850		function clearInt() {
851			if( self._timeoutSearchFiled )
852				clearTimeout( self._timeoutSearchFiled );
853			
854			self._timeoutSearchFiled = null;
855		}
856	
857		if( refreshDelay != '-1' ) {
858			searchField.bind('keyup', function(e){
859				if( jQuery(this).val() == lastValue )
860					return;
861				
862				if( ! refreshDelay ) {
863					self.ajax();
864				} else if( e.keyCode != 13 ) {
865					clearInt();
866					
867					self._timeoutSearchFiled = setTimeout(function(){
868						self.ajax();
869						
870						self._timeoutSearchFiled = null;
871					}, refreshDelay);
872				}
873				
874				lastValue = searchField.val();
875			});
876		}
877		
878		searchField.bind('keydown', function(e){
879			if( e.keyCode == 13 ) {
880				clearInt();
881				
882				self.ajax();
883				
884				return false;
885			}
886		}).bind('keyup.mf_shv', function(){
887			jQuery(this)[jQuery(this).val()?'addClass':'removeClass']('mfilter-search-has-value');
888		}).trigger('keyup.mf_shv');
889	
890		searchButton.bind('click', function(){
891			clearInt();
892			
893			self.ajax();
894			
895			return false;
896		});
897	},
898	
899	encode: function( string ) {
900		string = string.replace( /,/g, 'LA==' );
901		string = string.replace( /\[/g, 'Ww==' );
902		string = string.replace( /\]/g, 'XQ==' );
903		string = string.replace( /"/g, 'Ig==' );
904		string = string.replace( /'/g, 'Jw==' );
905		
906		return string;
907	},
908	
909	decode: function( string ) {
910		string = string.replace( /LA==/g, ',' );
911		string = string.replace( /Ww==/g, '[' );
912		string = string.replace( /XQ==/g, ']' );
913		string = string.replace( /Ig==/g, '"' );
914		string = string.replace( /Jw==/g, "'" );
915		
916		return string;
917	},
918	
919	_parseSep: function( url ) {
920		var self = this,
921			urlSep = null;
922		
923		if( typeof url == 'undefined' )
924			url = self._url;
925		
926		if( ! self._options.smp.isInstalled || self._options.smp.disableConvertUrls ) {
927			url		= self.parse_url( url );
928			url		= url.scheme + '://' + url.host + (url.port ? ':'+url.port: '') + url.path;
929			url		= url.split('&')[0];
930		} else {
931			url		= url.indexOf('?') > -1 ? url.split('?')[0] : url.split(';')[0];
932		}
933		
934		urlSep	= {
935			'f' : '?',
936			'n' : '&'
937		};
938		
939		return {
940			url : url,
941			urlSep : urlSep
942		};
943	},
944	
945	/**
946	 * Inicjuj kontener
947	 */
948	_initContent: function() {
949		var self = this;
950		
951		self._jqContent
952			.css('position', 'relative');
953	},
954	
955	/**
956	 * @return {scheme: 'http', host: 'hostname', user: 'username', pass: 'password', path: '/path', query: 'arg=value', fragment: 'anchor'}
957	 */
958	parse_url: function(str, component) {
959		var query, key = ['source', 'scheme', 'authority', 'userInfo', 'user', 'pass', 'host', 'port',
960			'relative', 'path', 'directory', 'file', 'query', 'fragment'
961			],
962			ini = (this.php_js && this.php_js.ini) || {},
963			mode = (ini['phpjs.parse_url.mode'] &&
964			ini['phpjs.parse_url.mode'].local_value) || 'php',
965			parser = {
966			php: /^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
967			strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
968			loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/\/?)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // Added one optional slash to post-scheme to catch file:/// (should restrict this)
969			};
970
971		var m = parser[mode].exec(str),
972			uri = {},
973			i = 14;
974		while (i--) {
975			if (m[i]) {
976			uri[key[i]] = m[i];
977			}
978		}
979
980		if (component) {
981			return uri[component.replace('PHP_URL_', '')
982			.toLowerCase()];
983		}
984		if (mode !== 'php') {
985			var name = (ini['phpjs.parse_url.queryKey'] &&
986			ini['phpjs.parse_url.queryKey'].local_value) || 'queryKey';
987			parser = /(?:^|&)([^&=]*)=?([^&]*)/g;
988			uri[name] = {};
989			query = uri[key[12]] || '';
990			query.replace(parser, function($0, $1, $2) {
991			if ($1) {
992				uri[name][$1] = $2;
993			}
994			});
995		}
996		delete uri.source;
997		return uri;
998	},
999	
1000	baseTypes: function( skip ) {
1001		var self	= this,
1002			types	= [];
1003		
1004		function find( self ) {
1005			self._box.find('[data-base-type]').each(function(){
1006				var baseType = jQuery(this).attr('data-base-type'),
1007					type = jQuery(this).attr('data-type');
1008
1009				if( baseType == 'categories' ) {
1010					baseType += ':' + type;
1011				}
1012
1013				if( types.indexOf( baseType ) > -1 ) return;
1014				if( typeof skip != 'undefined' && skip.indexOf( baseType ) > -1 ) return;
1015				
1016				if( type == 'text' ) return;
1017
1018				types.push( baseType );
1019			});
1020		}
1021		
1022		find( self );
1023		
1024		for( var i = 0; i < MegaFilterINSTANCES.length; i++ ) {
1025			if( i == self._instanceIdx ) continue;
1026			
1027			find( MegaFilterINSTANCES[i] );
1028		}
1029		
1030		return types;
1031	},
1032	
1033	_ajaxUrl: function( url ) {
1034		url = url.replace( /\/mfp,([a-z0-9\-_]+\[[^\]]*\],?)+/g, '' );
1035		
1036		var self = this,
1037			params = url.indexOf('?') > -1 ? url.split('?')[1] : '',
1038			parts = ( url.indexOf('?') > -1 ? url.split('?')[0] : url ).split('/');
1039		
1040		for( i = 0; i < parts.length; i++ ) {
1041			if( /page-[0-9]+/.test( parts[i] ) ) {
1042				delete parts[i];
1043			}
1044		}
1045		
1046		url = parts.join('/');
1047		url = url.replace('://', '###URL###');
1048		url = url.replace( /\/+/g, '/' );
1049		url = url.replace('###URL###', '://');
1050		
1051		if( params != '' ) {
1052			url += '?' + params;
1053		}
1054		
1055		if( self._options.mijoshop ) {
1056			return url + ( url.indexOf('?') > -1 ? '&' : '?' ) + 'option=com_mijoshop&format=raw';
1057		}
1058		
1059		if( self._options.joo_cart != false ) {
1060			function parse( u ) {
1061				u = u.replace( 'index.php', '' );
1062				u = u.replace( /\/$/, '' );
1063				
1064				return u + '/';
1065			}
1066		
1067			var site_url 	= parse( self._options.joo_cart.site_url ),
1068				main_url 	= parse( self._options.joo_cart.main_url ),
1069				route 		= url.indexOf( 'index.php' ) > -1 ? self._parseUrl( url, {} ).route : url.replace( main_url, '' ),
1070				query		= self.parse_url( url ).query;
1071			
1072			if( typeof route == 'undefined' ) {
1073				route = '';
1074			}
1075			
1076			if( typeof query == 'undefined' ) {
1077				query = '';
1078			}
1079			
1080			if( route.indexOf('?') > -1 ) {
1081				route = route.split('?')[0];
1082			}
1083			
1084			if( route == 'module/mega_filter/getajaxinfo' ) {
1085				return site_url + 'index.php?route=' + route + ( query ? '&' + query : '' ) + '&option=com_opencart&format=raw';
1086			}
1087		}
1088		
1089		return url;
1090	},
1091	
1092	/**
1093	 * Inicjuj informacje o ilości
1094	 */
1095	_initCountInfo: function() {
1096		var self = this;
1097		
1098		if( ! self._options.calculateNumberOfProducts || self._isInit )
1099			return;
1100		
1101		jQuery.ajax({
1102			'url'		: self._ajaxUrl( self.createUrl( self._options.ajaxGetInfoUrl, jQuery.extend( {}, self._params ), true ) ),
1103			'type'		: 'GET',
1104			'data'		: {
1105				'mfilterIdx'	: self._options.idx,
1106				'mfilterRoute'	: self._options.route,
1107				'mfilterBTypes'	: self.baseTypes(['categories:tree','categories:cat_checkbox']).join(','),
1108				'mfilterLPath'	: self.locationPath()
1109			},
1110			'success'	: function( response ) {
1111				var $tmp = jQuery('<tmp>').html( response );
1112				
1113				self._parseInfo( self.base64_decode($tmp.find('#mfilter-json').html()) );
1114				
1115				/*self._cache.mainContent[self.location()] = {
1116					'html'	: self._jqContent.html(),
1117					'json'	: response
1118				};*/
1119			},
1120			'error'		: function() {
1121				
1122			}
1123		});
1124		
1125		self._parseInfo('{"stock_status":[],"manufacturers":[],"rating":[],"attributes":[],"options":[],"filters":[]}',true);
1126	},
1127	
1128	_parseInfo: function( data, first ) {
1129		var self	= this,
1130			filters	= self.filters(),
1131			json	= jQuery.parseJSON( data );
1132		
1133		for( var i in json ) {
1134			switch( i ) {
1135				case 'categories:tree' : {
1136					self._box.find('.mfilter-category-tree > ul > li').remove();
1137					
1138					for( var j = 0; j < json[i].length; j++ ) {
1139						if( self._options.hideInactiveValues && json[i][j].cnt == '0' ) continue;
1140						
1141						self._box.find('.mfilter-category-tree > ul').append(jQuery('<li class="mfilter-tb-as-tr">')
1142							.append(jQuery('<div class="mfilter-tb-as-td">')
1143								.append(jQuery('<a>')
1144									.attr('data-id', json[i][j].id)
1145									.attr('data-parent-id', json[i][j].pid)
1146									.html( json[i][j].name )
1147								)
1148							)
1149							.append('<div class="mfilter-tb-as-td mfilter-col-count"><span class="mfilter-counter">' + json[i][j].cnt + '</span></div>')
1150						);
1151					}
1152					
1153					self._initTreeCategory( true );
1154					
1155					break;
1156				}
1157				case 'categories:cat_checkbox' : {
1158					var cnt = {};
1159					
1160					for( var j in json[i] ) {
1161						cnt[json[i][j].id] = json[i][j].cnt;
1162					}
1163					
1164					self._box.find('.mfilter-filter-item.mfilter-cat_checkbox').each(function(){
1165						var $self = jQuery(this),
1166							cx = 0,
1167							idx = 0;
1168						
1169						$self.find('input[value]').each(function(i){
1170							var $self2 = $(this),
1171								$parent = $self2.parent().parent(),
1172								$cnt = $parent.find('.mfilter-counter'),
1173								checked = $self2.is(':checked'),
1174								id = $self2.val(),
1175								c = typeof cnt[id] == 'undefined' ? 0 : parseInt( cnt[id] ),
1176								ct = c;
1177							
1178							if( typeof filters['path'] != 'undefined' ) {
1179								if( filters['path'].indexOf( encodeURIComponent( id ) ) == -1 ) {
1180									ct = '+' + ct;
1181								}
1182							}
1183								
1184							$cnt.text( ct )[checked?'addClass':'removeClass']('mfilter-close');
1185							
1186							if( c ) {
1187								cx++;
1188								$parent.removeClass('mfilter-hide mfilter-first-child');
1189							}
1190							
1191							if( checked || c ) {
1192								$self2.removeAttr('disabled');
1193								$parent.removeClass('mfilter-disabled');
1194							} else {
1195								$self2.attr('disabled',true);
1196								$parent.addClass('mfilter-disabled');
1197							}
1198							
1199							if( ! $parent.hasClass('mfilter-hide') ) {
1200								if( i > 0 && idx == 0 ) {
1201									$parent.addClass('mfilter-first-child');
1202								}
1203								idx++;
1204							}
1205						});
1206						
1207						if( cx ) {
1208							$self.removeClass('mfilter-hide');
1209						}
1210					});
1211					
1212					break;
1213				}
1214				case 'price' : {
1215					var priceRange = self.getPriceRange();
1216					
1217					if( priceRange.min == self._options.priceMin && priceRange.max == self._options.priceMax ) {
1218						self._box.find('[id="mfilter-opts-price-min"]').val( json[i].min );
1219						self._box.find('[id="mfilter-opts-price-max"]').val( json[i].max );
1220					}
1221					
1222					self._options.priceMin = json[i].min;
1223					self._options.priceMax = json[i].max;
1224					
1225					self._refreshPrice();
1226					
1227					break;
1228				}
1229				case 'model' :
1230				case 'sku' :
1231				case 'upc' :
1232				case 'ean' :
1233				case 'jan' :
1234				case 'isbn' :
1235				case 'mpn' :
1236				case 'location' :
1237				case 'length' :
1238				case 'width' :
1239				case 'height' :
1240				case 'rating' :
1241				case 'attributes' :
1242				case 'filters' :
1243				case 'options' :
1244				case 'manufacturers' :
1245				case 'stock_status' : {					
1246					self._box.find('.mfilter-filter-item.mfilter-' + i).each(function(){
1247						var $item		= jQuery(this),
1248							seo			= $item.attr('data-seo-name'),
1249							id			= $item.attr('data-id'),
1250							$items		= $item.find( '.mfilter-options .mfilter-option'),
1251							hidden		= 0;
1252						
1253						$items.each(function(){
1254							var $self		= jQuery(this),
1255								$input		= $self.find('input[type=checkbox],input[type=radio],select'),
1256								val			= $input.val(),
1257								$counter	= jQuery(this).find('.mfilter-counter'),
1258								text		= '',
1259								cnt			= json[i];							
1260							
1261							if( id && typeof cnt[id] != 'undefined' ) {
1262								cnt = cnt[id];
1263							}
1264							
1265							if( $self.hasClass( 'mfilter-select' ) ) {
1266								var $options	= $input.find('option'),
1267									hOptions	= 0,
1268									val			= $input.val(),
1269									idx			= $input.prop('selectedIndex');
1270								
1271								if( typeof self._selectOptions[seo] == 'undefined' ) {
1272									self._selectOptions[seo] = [];
1273									
1274									$options.each(function(){
1275										self._selectOptions[seo].push({
1276											'name'	: jQuery(this).attr('data-name'),
1277											'id'	: jQuery(this).attr('id'),
1278											'value'	: jQuery(this).attr('value'),
1279											'text'	: jQuery(this).html()
1280										});
1281									});
1282								}
1283								
1284								$options.remove();
1285								
1286								(function(){
1287									function add( $option ) {
1288										$input.append( $option );
1289										
1290										if( val == $option.val() ) {
1291											idx = $input.find('option').length-1;
1292										}
1293									}
1294									
1295									for( var i = 0; i < self._selectOptions[seo].length; i++ ) {
1296										var $option = jQuery('<option>')
1297											.attr('value', self._selectOptions[seo][i].value);
1298
1299										if( self._selectOptions[seo][i].name ) {
1300											$option.attr('data-name', self._selectOptions[seo][i].name);
1301										}
1302
1303										if( self._selectOptions[seo][i].id ) {
1304											$option.attr('id', self._selectOptions[seo][i].id);
1305										}
1306
1307										if( self._selectOptions[seo][i].id ) {
1308											var idd = self._selectOptions[seo][i].id.split('-').pop();
1309
1310											if( first || typeof cnt[idd] != 'undefined' ) {
1311												$option.html( ( ! first && self._options.showNumberOfProducts ? '(' + cnt[idd] + ') ' : '' ) + self._selectOptions[seo][i].name );
1312												
1313												add( $option );
1314											} else {
1315												$option.attr('disabled', true).html( ( self._options.showNumberOfProducts ? '(0)' : '' ) + self._selectOptions[seo][i].name );
1316
1317												if( ! self._options.hideInactiveValues ) {
1318													add( $option );
1319												}
1320
1321												hOptions++;
1322											}
1323										} else {
1324											$option.html( self._selectOptions[seo][i].text );
1325											add( $option );
1326										}
1327									}
1328								})();
1329								
1330								if( idx >= 0 ) {
1331									$input.prop('selectedIndex', idx);
1332								}
1333								
1334								if( hOptions == self._selectOptions[seo].length ) {
1335									hidden++;
1336								}
1337							} else if( $self.hasClass( 'mfilter-slider' ) ) {
1338								//if( self._options.hideInactiveValues ) {
1339									self._box.find('[data-id="' + id + '"][data-slider-id]').each(function(){
1340										var slider_id = jQuery(this).attr('data-slider-id'),
1341											data = {};
1342
1343										for( var i in self._sliders[slider_id].data ) {
1344											if( typeof cnt != 'undefined' && typeof cnt[i] != 'undefined' && parseInt( cnt[i] ) > 0 ) {
1345												data[i] = self._sliders[slider_id].data[i];
1346											}
1347										}
1348										
1349										self._sliders[slider_id].init( data, true );
1350									});
1351								//}
1352							} else if( $self.hasClass( 'mfilter-text' ) ) {
1353								$input = $self.find('input[type=text]');
1354								
1355								if( typeof filters[seo] != 'undefined' ) {
1356									
1357								} else {
1358									
1359								}
1360							} else {
1361								var idd = $input.attr('id').split('-').pop();
1362								
1363								if( typeof filters[seo] != 'undefined' ) {
1364									if( filters[seo].indexOf( encodeURIComponent( self.encode( val ) ) ) > -1 ) {
1365										$counter.addClass( 'mfilter-close' );
1366									} else {
1367										if( ! $item.hasClass( 'mfilter-radio' ) && ! $item.hasClass('mfilter-image_list_radio') /*&& base_type != 'option'*/ )
1368											text += '+';
1369
1370										$counter.removeClass( 'mfilter-close' );
1371									}
1372								} else {
1373									$counter.removeClass( 'mfilter-close' );
1374								}
1375								
1376								$self.removeClass('mfilter-first-child mfilter-last-child mfilter-disabled mfilter-hide mfilter-visible');
1377								$self.parent().removeClass('mfilter-hide');
1378
1379								if( typeof cnt[idd] != 'undefined' && parseInt( cnt[idd] ) > 0 ) {
1380									text += cnt[idd];
1381
1382									$self.addClass('mfilter-visible');
1383									$input.attr('disabled', false);
1384								} else {
1385									text = '0';
1386									hidden++;
1387									
1388									$self.addClass('mfilter-disabled');
1389									$input.attr('disabled',true);
1390										
1391									if( first !== true && self._options.hideInactiveValues ) {
1392										$self.addClass('mfilter-hide');
1393										
1394										if( self._box.hasClass('mfilter-content_top') ) {
1395											$self.parent().addClass('mfilter-hide');
1396										}
1397									}
1398								}
1399
1400								$counter.text( text );
1401							}
1402						});
1403						
1404						if( first !== true && self._options.hideInactiveValues ) {
1405							$item[hidden==$items.length?'addClass':'removeClass']('mfilter-hide');
1406							$item.find('.mfilter-option').not('.mfilter-hide,.mfilter-hide-by-live-filter').first().addClass('mfilter-first-child');
1407							$item.find('.mfilter-option').not('.mfilter-hide,.mfilter-hide-by-live-filter').last().addClass('mfilter-last-child');
1408						}
1409					});
1410					
1411					break;
1412				}
1413			}
1414		}
1415						
1416		if( first !== true && ( self._options.hideInactiveValues || self._box.find('[data-display-live-filter!="0"]').length ) ) {							
1417			for( var s = 0; s < self._scrolls.length; s++ ) {
1418				self._scrolls[s].refresh();
1419			}
1420
1421			for( var b = 0; b < self._buttonsMore.length; b++ ) {
1422				self._buttonsMore[b].refresh();
1423			}
1424			
1425			for( var f = 0; f < self._liveFilters.length; f++ ) {
1426				self._liveFilters[f].refresh();
1427			}
1428
1429			if( self._relativeScroll != null ) {
1430				self._relativeScroll.refresh();
1431			}
1432		}
1433		
1434		self._updateInlineHorizontal();
1435	},
1436	
1437	_initAlwaysSearch: function() {
1438		var self	= this;
1439			
1440		function search() {
1441			self._jqContent.find('[name^=filter_],[name=search],[name=category_id],[name=sub_category],[name=description]').each(function(){
1442				var name	= jQuery(this).attr('name'),
1443					value	= jQuery(this).val(),
1444					type	= jQuery(this).attr('type');
1445
1446				if( [ 'checkbox', 'radio' ].indexOf( type ) > -1 && ! jQuery(this).is(':checked') )
1447					value = '';
1448					
1449				if( name ) {
1450					self._inUrl[name] = value;
1451					self._params[name] = value;
1452				}
1453			});
1454			
1455			self.reload();
1456			//self.ajax();
1457		}
1458			
1459		jQuery('#button-search').unbind('click').click(function(e){
1460			e.preventDefault();
1461				
1462			search();
1463		});
1464			
1465		self._jqContent.find('input[name=filter_name],input[name=search]').unbind('keydown').unbind('keyup').bind('keydown', function(e){
1466			if( e.keyCode == 13 ) {
1467				e.preventDefault();
1468					
1469				search();
1470			}
1471		});
1472	},
1473	
1474	_initAlwaysAjaxPagination: function(){
1475		var self = this;
1476		
1477		if( ! self._options.ajaxPagination ) return;
1478		
1479		self._jqContent.find('.pagination a').click(function(){
1480			var url = jQuery(this).attr('href'),
1481				params = self._parseUrl( url );
1482			
1483			if( typeof params.page != 'undefined' ) {
1484				self._ajaxPagination = params.page;
1485				
1486				self.ajax( url );
1487				
1488				return false;
1489			}
1490		});
1491	},
1492		
1493	__initLoader: function() {
1494		this._jqLoader = jQuery('<span class="mfilter-ajax-loader-container" style="cursor: wait; z-index: 100; margin: 0; padding: 0; position: absolute; text-align: center; background-color: rgba(255,255,255,0.7);"></span>')
1495			.prependTo( this._jqContent )
1496			.html( '<img src="catalog/view/theme/default/stylesheet/mf/images/ajax-loader.gif" alt="" />' )
1497			.hide();
1498	},
1499	
1500	__initLoaderFilter: function() {
1501		this._jqLoaderFilter = jQuery('<span style="cursor: wait; z-index: 10000; margin: 0; padding: 0; position: absolute; background-color: rgba(255,255,255,0.7);"></span>')
1502			.prependTo( this._box )
1503			.hide();
1504	},
1505	
1506	/**
1507	 * Inicjuj wyświetlanie listy
1508	 */
1509	_initDisplayItems: function() {
1510		var self = this,
1511			params = self.urlToFilters();
1512		
1513		self._box.find('.mfilter-filter-item').each(function(i){
1514			var _level0				= jQuery(this),
1515				type				= _level0.attr('data-type'),
1516				seo_name			= _level0.attr('data-seo-name'),
1517				displayLiveFilter	= parseInt( _level0.attr('data-display-live-filter') ),
1518				displayListOfItems	= _level0.attr('data-display-list-of-items');
1519					
1520			if( ! displayListOfItems ) {
1521				displayListOfItems = self._options.displayListOfItems.type;
1522			}
1523
1524			if( type == 'price' || type == 'rating' ) return;
1525			
1526			var wrapper = _level0.find('.mfilter-content-wrapper'),
1527				content	= _level0.find('> .mfilter-content-opts'),
1528				heading	= _level0.find('> .mfilter-heading'),
1529				idx = null;
1530
1531			if( ! self._box.hasClass('mfilter-content_top') && heading.hasClass( 'mfilter-collapsed' ) ) {
1532				if( typeof params[seo_name] == 'undefined' ) {
1533					content.show();
1534				}
1535			}
1536			
1537			if( displayListOfItems == 'scroll' ) {
1538				if( ( wrapper.actual ? wrapper.actual( 'outerHeight', { includeMargin: true } ) : wrapper.outerHeight(true) ) > self._options.displayListOfItems.maxHeight ) {
1539					if( jQuery.browser && jQuery.browser.msie && jQuery.browser.version < 9 ) {
1540						wrapper
1541							.css({
1542								'max-height': self._options.displayListOfItems.maxHeight + 'px',
1543								'overflow-y': 'scroll'
1544							});
1545					} else {
1546						wrapper
1547							.attr('id', 'mfilter-content-opts-' + self._instanceIdx + '-' + i)
1548							.addClass('mfilter-iscroll')
1549							.css('max-height', self._options.displayListOfItems.maxHeight + 'px');
1550
1551						(function(){
1552							var iscroll = new IScroll( '#mfilter-content-opts-' + self._instanceIdx + '-' + i, {
1553									bounce: false,
1554									scrollbars: true,
1555									mouseWheel: true,
1556									interactiveScrollbars: true,
1557									mouseWheelSpeed: 120
1558								}),
1559								start = false;
1560
1561							iscroll.on('moveStart', function(e){
1562								if( ! start ) return;
1563
1564								self._relativeScroll._end(e);
1565
1566								start = false;
1567							});
1568
1569							iscroll.on('moveStop', function(e){
1570								if( start ) return;
1571
1572								self._relativeScroll._start(e);
1573
1574								start = true;
1575							});
1576
1577							iscroll.on('scrollEnd', function(e){
1578								if( e == null ) return;
1579
1580								self._relativeScroll._end(e);
1581
1582								start = false;
1583							});
1584
1585							idx = self._scrolls.length;
1586
1587							self._scrolls.push({
1588								refresh: function(){
1589									iscroll.refresh();
1590								}
1591							});
1592						})();
1593					}
1594				}
1595			} else if( displayListOfItems == 'button_more' && ! self._box.hasClass('mfilter-content_top') && type != 'image' && type != 'image_radio' ) {
1596				self._buttonsMore.push((function( _level0 ){		
1597					function init( first ) {
1598						var lessHeight	= 0,
1599							moreHeight	= 0,
1600							show		= false,
1601							count		= 0,
1602							idx			= 0;
1603						
1604						_level0.find('.mfilter-option.mfilter-tb-as-tr').each(function(i){
1605							var _this = jQuery(this);
1606							
1607							if( _this.hasClass('mfilter-hide') || _this.hasClass('mfilter-hide-by-live-filter') ) return;
1608							
1609							var h = _this.actual ? _this.actual( 'outerHeight', { includeMargin: true } ) : _this.outerHeight(true);
1610
1611							moreHeight += h;
1612
1613							if( idx >= self._options.displayListOfItems.limit_of_items ) {
1614								lessHeight += h;
1615								count++;
1616							}
1617							
1618							idx++;
1619						});
1620
1621						lessHeight = moreHeight - lessHeight;
1622
1623						if( count ) {
1624							wrapper.css('overflow','hidden').css('height', lessHeight+'px');
1625							
1626							function sh( show, force ) {
1627								if( force ) {
1628									wrapper.height( moreHeight );
1629								} else {
1630									wrapper.animate({
1631										'height' : ! show ? moreHeight : lessHeight
1632									}, 500, function(){
1633										if( self._relativeScroll != null )
1634											self._relativeScroll.refresh();
1635									});
1636								}
1637										
1638								_level0.find('a.mfilter-button-more').text(show?self._options.displayListOfItems.textMore.replace( '%s', count ):self._options.displayListOfItems.textLess);
1639							}
1640
1641							_level0.find('.mfilter-content-opts').append(jQuery('<div>')
1642								.addClass( 'mfilter-button-more' )
1643								.append(jQuery('<a>')
1644									.attr( 'href', '#' )
1645									.addClass( 'mfilter-button-more' )
1646									.text( self._options.displayListOfItems.textMore.replace( '%s', count ) )
1647									.bind('click', function(){
1648										sh( show );
1649
1650										show = ! show;
1651										
1652										wrapper[show?'addClass':'removeClass']('mfilter-slide-down');
1653
1654										return false;
1655									})
1656								)
1657							);
1658						
1659							if( wrapper.hasClass('mfilter-slide-down') ) {
1660								sh( false, true );
1661								show = true;
1662							}
1663						}
1664					}
1665					
1666					init( true );
1667					
1668					idx = self._buttonsMore.length;
1669					
1670					return {
1671						refresh: function() {
1672							_level0.find('.mfilter-content-wrapper').removeAttr('style');
1673							_level0.find('.mfilter-button-more').remove();
1674							
1675							init();
1676						}
1677					};
1678				})( _level0 ));
1679			}
1680			
1681			if( type == 'cat_checkbox' ) {
1682				(function(){
1683					var cnt = 0;
1684					
1685					content.find('.mfilter-category .mfilter-option').each(function(i){
1686						if( jQuery(this).find('.mfilter-counter').text() != '0' ) {							
1687							if( i && ! cnt ) {
1688								jQuery(this).addClass('mfilter-first-child');
1689							}
1690							
1691							cnt++;
1692						} else {
1693							jQuery(this).addClass('mfilter-hide');
1694						}
1695					});
1696					
1697					if( ! cnt ) {
1698						_level0.addClass('mfilter-hide');
1699					}
1700				})();
1701			}
1702			
1703			(function(){
1704				if( self._box.hasClass( 'mfilter-content_top' ) ) {
1705					return;
1706				}
1707				
1708				if( displayLiveFilter < 1 || content.find('.mfilter-option').length < displayLiveFilter || type == 'image' || type == 'image_radio' ) {
1709					displayLiveFilter = 0;
1710					
1711					return;
1712				}
1713				
1714				content.prepend(jQuery('<div class="mfilter-live-filter">')
1715					.append(jQuery('<input type="text" class="form-control" id="mfilter-live-filter-input-' + self._instanceIdx + '-' + i + '" />'))
1716				);
1717				wrapper.find('> .mfilter-options > div').attr('id', 'mfilter-live-filter-list-' + self._instanceIdx + '-' + i);
1718
1719				_level0.addClass('mfilter-live-filter-init');
1720
1721				jQuery('#mfilter-live-filter-list-' + self._instanceIdx + '-' + i).liveFilter('#mfilter-live-filter-input-'+self._instanceIdx + '-' + i, '.mfilter-visible,.mfilter-should-visible,.mfilter-disabled,.mfilter-option:not(.mfilter-filter-item)', {
1722					'filterChildSelector' : 'label',
1723					'after' : function(contains, containsNot){
1724						var list = jQuery('#mfilter-live-filter-list-' + self._instanceIdx + '-' + i);
1725
1726						contains.removeClass('mfilter-should-visible').addClass('mfilter-visible');
1727						containsNot.removeClass('mfilter-visible').addClass('mfilter-should-visible');
1728
1729						list.find('> .mfilter-option').removeClass('mfilter-first-child mfilter-last-child');
1730						
1731						list.find('> .mfilter-option:not(.mfilter-hide):not(.mfilter-hide-by-live-filter):first').addClass('mfilter-first-child');
1732						list.find('> .mfilter-option:not(.mfilter-hide):not(.mfilter-hide-by-live-filter):last').addClass('mfilter-last-child');
1733
1734						if( idx !== null ) {
1735							if( displayListOfItems == 'scroll' ) {
1736								self._scrolls[idx].refresh();
1737							} else if( displayListOfItems == 'button_more' ) {
1738								self._buttonsMore[idx].refresh();
1739							}
1740						}
1741						
1742						if( self._relativeScroll != null ) {
1743							self._relativeScroll.refresh();
1744						}
1745					}
1746				});
1747					
1748				_level0.addClass('mfilter-live-filter-init');
1749				
1750				self._liveFilters.push({
1751					refresh: function(){
1752						content.find('.mfilter-live-filter')[content.find('.mfilter-option:not(.mfilter-hide)').length <= displayLiveFilter?'hide':'show']();
1753					},
1754					check: function() {
1755						jQuery('#mfilter-live-filter-input-'+self._instanceIdx + '-' + i).trigger('keyup');
1756					}
1757				});
1758				
1759				self._liveFilters[self._liveFilters.length-1].refresh();
1760			})();
1761
1762			if( ! self._box.hasClass('mfilter-content_top') && heading.hasClass( 'mfilter-collapsed' ) ) {
1763				if( typeof params[seo_name] == 'undefined' ) {
1764					//content.hide();
1765				}
1766			}
1767		});
1768	},
1769			
1770	/**
1771	 * Inicjuj nagłówki
1772	 */
1773	_initHeading: function() {
1774		var self = this;
1775		
1776		if( self._box.hasClass('mfilter-content_top') )
1777			return;
1778		
1779		self._box.find('.mfilter-heading').click(function(){
1780			var opts = jQuery(this).parent().find('> .mfilter-content-opts');
1781
1782			if( jQuery(this).hasClass('mfilter-collapsed') ) {
1783				opts.slideDown('normal', function(){
1784					if( self._relativeScroll != null )
1785						self._relativeScroll.refresh();
1786				});
1787				jQuery(this).removeClass('mfilter-collapsed');
1788			} else {
1789				opts.slideUp('normal', function(){
1790					if( self._relativeScroll != null )
1791						self._relativeScroll.refresh();
1792				});
1793				jQuery(this).addClass('mfilter-collapsed');
1794			}
1795		});
1796	},
1797	
1798	_updateInlineHorizontal: function() {
1799		for( var i = 0; i < this._inlineHorizontalUpdate.length; i++ ) {
1800			this._inlineHorizontalUpdate[i]();
1801		}
1802	},
1803	
1804	_initInlineHorizontal: function() {
1805		var self = this;
1806		
1807		if( ! self._box.hasClass( 'mfilter-content_top' ) ) {
1808			return;
1809		}
1810		
1811		self._box.find('li[data-inline-horizontal="1"][data-type="checkbox"],li[data-inline-horizontal="1"][data-type="radio"]').each(function(){
1812			var $container = jQuery(this).addClass('mfilter-inline-horizontal').find('.mfilter-opts-container'),
1813				$wrapper = $container.find('> .mfilter-content-wrapper'),
1814				$options = $wrapper.find('> .mfilter-options'),
1815				$optionsCnt = $options.find('> .mfilter-options-container'),
1816				$tb = $optionsCnt.find('> .mfilter-tb'),
1817				left = 0;
1818			
1819			function width() {
1820				var w = 0,
1821					b = false;
1822				
1823				left = 0;
1824				
1825				$tb.find('> .mfilter-tb').each(function(){
1826					var ww = jQuery(this).outerWidth(true);
1827					
1828					if( self._lastEvent ) {
1829						var $el = jQuery(this).find('[id="' + self._lastEvent + '"]');
1830						
1831						if( $el.length ) {
1832							b = true;
1833						} else if( ! b ) {
1834							left += ww;
1835						}
1836					}
1837					
1838					w += ww;
1839				});
1840				
1841				return w;
1842			}
1843			
1844			self._inlineHorizontalUpdate[self._inlineHorizontalUpdate.length] = function() {
1845				$optionsCnt.removeAttr('style');
1846				$tb.removeAttr('style').css('margin-left',$tb.attr('data-mgr')+'px');
1847				
1848				o1 = w1;
1849				o2 = w2;
1850				
1851				w1 = $optionsCnt.width()-2*8;
1852				w2 = width();
1853				
1854				$optionsCnt.css('width', w1);
1855				$tb.css('width', w2+fix);
1856				
1857				if( w2 > w1 ) {
1858					$right.addClass('mf-active');
1859					
1860					if( x >= w2-w1 && $left.hasClass('mf-active') ) {
1861						t=0;
1862						$right.trigger('click');
1863					} else if( self._lastEvent ) {
1864						var $el = $tb.find('[id="' + self._lastEvent + '"]');
1865						
1866						if( $el.length ) {
1867							var w = $el.parent().parent().parent().outerWidth(true);
1868							
1869							if( x > left ) {
1870								t=0;
1871								x=left-w+w1;
1872								$left.trigger('click');
1873							} else if( x+w1 < left+w ) {
1874								t=0;
1875								x=x+(w*2)-w1;
1876								$right.trigger('click');
1877							}
1878						}
1879					}
1880				} else {
1881					t=x=0;
1882					$left.addClass('mf-active').trigger('click');
1883					$right.removeClass('mf-active');
1884				}
1885				
1886				/*if( ! $right.hasClass('mf-active') ) {
1887					if( w2 > w1 ) {
1888						//t=0;
1889						$right.addClass('mf-active');//.trigger('click');
1890					} else {
1891						t=x=0;
1892						$left.addClass('mf-active').trigger('click');
1893						//$right.removeClass('mf-active');
1894					}
1895				} else {
1896					if( w2 <= w1 ) {
1897						$right.removeClass('mf-active');
1898					}
1899				}*/
1900			};
1901			
1902			var $left = jQuery('<a href="#"></a>'),
1903				$right = jQuery('<a href="#"></a>');
1904			
1905			$wrapper.prepend(jQuery('<div class="mfilter-scroll-left"></div>').append($left));
1906			$wrapper.append(jQuery('<div class="mfilter-scroll-right"></div>').append($right));
1907			
1908			var w1 = $optionsCnt.width(),
1909				w2 = width(),
1910				o1 = -1,
1911				o2 = -1,
1912				x = 0,
1913				fix = 50,
1914				t = 'normal';
1915			
1916			if( w2 > w1 ) {
1917				$right.addClass('mf-active');
1918			}
1919			
1920			$optionsCnt.css('width', w1);
1921			$tb.css('width', w2+fix).attr('data-mgr','0');
1922			
1923			$left.click(function(){
1924				var $self = jQuery(this);
1925				
1926				if( ! $self.hasClass('mf-active') ) return false;
1927				
1928				x -= w1;
1929				
1930				if( x <= 0 ) {
1931					x = 0;
1932					$self.removeClass('mf-active');
1933				}
1934				
1935				$tb.attr('data-mgr', -x).stop().animate({
1936					'marginLeft' : -x
1937				}, t);
1938				
1939				t = 'normal';
1940				
1941				$right.addClass('mf-active');
1942				
1943				return false;
1944			});
1945			$right.click(function(){
1946				var $self = jQuery(this);
1947				
1948				if( ! $self.hasClass('mf-active') ) return false;
1949				
1950				x += w1;
1951				
1952				if( x >= w2-w1 ) {
1953					x = w2-w1;
1954					$self.removeClass('mf-active');
1955				}
1956				
1957				$tb.attr('data-mgr', -x).stop().animate({
1958					'marginLeft' : -x
1959				}, t);
1960				
1961				t = 'normal';
1962				
1963				$left.addClass('mf-active');
1964				
1965				return false;
1966			});
1967		});
1968	},
1969	
1970	_initCategoryRelated: function() {
1971		var self	= this;
1972		
1973		self._box.find('.mfilter-filter-item.mfilter-related').each(function(){
1974			var $li			= jQuery(this),
1975				seoName		= $li.attr('data-seo-name'),
1976				autoLevels	= $li.attr('data-auto-levels'),
1977				fields		= $li.find('select[data-type="category-related"]');
1978			
1979			fields.each(function(i){
1980				if( ! autoLevels && i == fields.length - 1 ) {
1981					jQuery(this).change(function(){
1982						if( self._options['refreshResults'] != 'using_button' ) {
1983							self.runAjax();
1984						}
1985					});
1986				} else {						
1987					function eChange( $self, id ) {
1988						var $this = $self.parent().attr('data-id', id),
1989							labels = $this.parent().attr('data-labels').split('#|#');
1990						
1991						$self.change(function(){
1992							var cat_id = $self.val();
1993							
1994							$next = $this.next().find('select');
1995							$parent = $next.parent();
1996							label = typeof labels[id+1] == 'undefined' ? $parent.attr('data-next-label') : labels[id+1];
1997
1998							if( cat_id ) {
1999								$next.html('<option value="">' + self._options.text.loading + '</option>');
2000								$next.prop('selectedIndex', 0);
2001
2002								jQuery.post( self._ajaxUrl( self._options.ajaxGetCategoryUrl ), { 'cat_id' : cat_id }, function( response ){
2003									var data = jQuery.parseJSON( response );
2004
2005									if( data.length && autoLevels ) {
2006										var $li = jQuery('<li>');
2007
2008										$this.after( $li );
2009										$next = jQuery('<select>').appendTo( $li );
2010										
2011										if( ! label )
2012											label = MegaFilterLang.text_select;
2013
2014										eChange( $next, id+1 );
2015									}
2016
2017									$next.html('<option value="">' + label + '</option>');
2018									$next.prop('selectedIndex', 0);
2019
2020									for( var i = 0; i < data.length; i++ ) {
2021										$next.append( '<option value="' + data[i].id + '">' + data[i].name + '</option>' );
2022									}
2023
2024									if( autoLevels ) {
2025										if( ! data.length ) {
2026											if( self._options['refreshResults'] != 'using_button' ) {
2027												self.runAjax();
2028											}
2029										}
2030									} else if( ! data.length ) {
2031										if( self._options['refreshResults'] != 'using_button' ) {
2032											self.runAjax();
2033										}
2034									}
2035								});
2036							}
2037
2038							var $p = $parent;
2039
2040							while( $p.length ) {
2041								if( autoLevels ) {
2042									var $t = $p;
2043									$p = $p.next();
2044									$t.remove();
2045								} else {
2046									$p.find('select').prop('selectedIndex', 0).find('option[value!=""]').remove();
2047									$p = $p.next();
2048								}
2049							}
2050
2051							if( ! cat_id ) {
2052								var beforeVal	= self.urlToFilters()[seoName],
2053									afterVal	= self.filters()[seoName];
2054
2055								if( typeof beforeVal == 'undefined' )
2056									beforeVal = [-1];
2057
2058								if( typeof afterVal == 'undefined' )
2059									afterVal = [-1];
2060
2061								if( beforeVal.toString() != afterVal.toString() )
2062									self.runAjax();
2063							}
2064						});
2065					}
2066
2067					eChange( jQuery(this), i );
2068				}
2069			});
2070		});
2071	},
2072	
2073	/**
2074	 * Inicjuj zdarzenia
2075	 */
2076	_initEvents: function() {
2077		var self = this;
2078		
2079		function val( $input ) {
2080			var val = $input.val(),
2081				parent = $input.parent().parent();
2082			
2083			if( $input.attr('type') == 'checkbox' || $input.attr('type') == 'radio' ) {
2084				val = $input.is(':checked');
2085				
2086				if( ! self._options.calculateNumberOfProducts ) {
2087					if( self._isInit && $input.attr('type') == 'radio' ) {
2088						parent.parent().find('.mfilter-counter').removeClass('mfilter-close');
2089					}
2090					
2091					parent.find('.mfilter-counter')[val?'addClass':'removeClass']('mfilter-close');
2092				}
2093				
2094				if( $input.attr('type') == 'radio' ) {
2095					parent.parent().parent().parent().parent().parent().parent().find('.mfilter-input-active').removeClass('mfilter-input-active');
2096				}
2097			}
2098			
2099			parent[val?'addClass':'removeClass']('mfilter-input-active');
2100		}
2101		
2102		self._box.find('input[type=checkbox],input[type=radio],select:not([data-type="category-related"])').change(function(){
2103			self._lastEvent = jQuery(this).attr('id');
2104			
2105			if( self._options['refreshResults'] != 'using_button' ) {
2106				self.runAjax();
2107			}
2108			
2109			val(jQuery(this));
2110		});
2111		
2112		self._box.find('.mfilter-options .mfilter-option').each(function(){
2113			var input = jQuery(this).find('input[type=checkbox],input[type=radio]');
2114			
2115			if( ! input.length ) return;
2116			
2117			jQuery(this).find('.mfilter-counter').bind('click', function(){
2118				if( ! jQuery(this).hasClass( 'mfilter-close' ) ) return;
2119				
2120				input.prop('checked', false).trigger('change');
2121				//jQuery(this).removeClass('mfilter-close');
2122			});
2123		
2124			if( input.is(':checked') ) {
2125				val(input);
2126			}
2127		});
2128		
2129		self._box.find('.mfilter-button a').bind('click', function(){
2130			self._lastEvent = null;
2131			
2132			if( jQuery(this).hasClass( 'mfilter-button-reset' ) ) {
2133				self.eachInstances(function( self ){
2134					self.resetFilters();
2135				});
2136			}
2137			
2138			self.ajax();
2139			
2140			return false;
2141		});
2142	},
2143			
2144	/**
2145	 * Uruchom ładowanie
2146	 */
2147	runAjax: function() {
2148		var self = this;
2149				
2150		switch( self._options['refreshResults'] ) {
2151			case 'using_button' :
2152			case 'immediately' : {
2153				self.ajax();
2154					
2155				break;
2156			}
2157			case 'with_delay' : {
2158				if( self._timeoutAjax )
2159					clearTimeout( self._timeoutAjax );
2160					
2161				self._timeoutAjax = setTimeout(function(){
2162					self.ajax();
2163							
2164					self._timeoutAjax = null;
2165				}, self._options['refreshDelay'] );
2166					
2167				break;
2168			}
2169		}
2170	},
2171	
2172	/**
2173	 * Pobierz aktualny zakres cen
2174	 */
2175	getPriceRange: function() {
2176		var self		= this,
2177			minInput	= self._box.find('[id="mfilter-opts-price-min"]'),
2178			maxInput	= self._box.find('[id="mfilter-opts-price-max"]'),
2179			min			= minInput.val(),
2180			max			= maxInput.val();		
2181			
2182		if( ! /^[0-9]+$/.test( min ) || min < self._options.priceMin )
2183			min = self._options.priceMin;
2184		
2185		if( ! /^[0-9]+$/.test( max ) || max > self._options.priceMax )
2186			max = self._options.priceMax;
2187		
2188		return {
2189			min : parseInt( min ),
2190			max : parseInt( max )
2191		};
2192	},
2193	
2194	/**
2195	 * Inicjuj przedział cenowy
2196	 */
2197	_initPrice: function() {
2198		var self		= this,
2199			priceRange	= self.getPriceRange(),
2200			filters		= self.urlToFilters(),
2201			minInput	= self._box.find('[id="mfilter-opts-price-min"]').unbind('change').bind('change', function(){
2202				changePrice();
2203			}).val( filters.price ? filters.price[0] : priceRange.min ),
2204			maxInput	= self._box.find('[id="mfilter-opts-price-max"]').unbind('change').bind('change', function(){
2205				changePrice();
2206			}).val( filters.price ? filters.price[1] : priceRange.max ),
2207			slider		= self._box.find('[id="mfilter-price-slider"]');
2208		
2209		self._refreshPrice = function( minMax ) {
2210			var priceRange = self.getPriceRange();
2211			
2212			if( priceRange.min < self._options.priceMin ) {
2213				priceRange.min = self._options.priceMin;
2214			}
2215			
2216			if( priceRange.max > self._options.priceMax ) {
2217				priceRange.max = self._options.priceMax;
2218			}
2219			
2220			if( priceRange.min > priceRange.max ) {
2221				priceRange.min = priceRange.max;
2222			}
2223			
2224			if( priceRange.min.toString() != minInput.val() ) {
2225				minInput.val( priceRange.min );
2226			}
2227			
2228			if( priceRange.max.toString() != maxInput.val() ) {
2229				maxInput.val( priceRange.max );
2230			}
2231			
2232			slider.slider( 'option', 'values', [ priceRange.min, priceRange.max ] );
2233			
2234			if( minMax !== false ) {
2235				slider.slider( 'option', 'min', self._options.priceMin );
2236				slider.slider( 'option', 'max', self._options.priceMax );
2237				slider.slider( 'value', slider.slider('value') );
2238			}
2239		};
2240			
2241		function changePrice() {
2242			self._refreshPrice( false );
2243			
2244			if( self._options['refreshResults'] != 'using_button' ) {
2245				self.runAjax();
2246			}
2247		}
2248		
2249		slider.slider({
2250			range	: true,
2251			min		: self._options.priceMin ,
2252			max		: self._options.priceMax,
2253			values	: [ priceRange.min, priceRange.max ],
2254			slide	: function( e, ui ) {
2255				minInput.val( ui.values[0] );
2256				maxInput.val( ui.values[1] );
2257			},
2258			stop	: function( e, ui ) {
2259				if( self._options['refreshResults'] != 'using_button' )
2260					self.runAjax();
2261			}
2262		});
2263	},
2264	
2265	_initWindowOnPopState: function(){
2266		var self = this;
2267			
2268		if( self._isInit ) return;
2269		
2270		function update() {
2271			self.eachInstances(function( self ){
2272				self._urlToFilters = null;
2273				self.initUrls();
2274				self.setFiltersByUrl();
2275			});
2276		}
2277
2278		function setFilters( url ) {
2279			var params = self._parseUrl( url );
2280
2281			if( typeof params.mfp != 'undefined' ) {				
2282				self.setFiltersByUrl( self.__urlToFilters( decodeURIComponent( params.mfp ) ) );
2283			} else {
2284				self.resetFilters();
2285			}
2286		}
2287
2288		window.onpopstate = function(e){
2289			if( e.state ) {
2290				update();
2291
2292				self._render( e.state.html, e.state.json, true );
2293
2294				setFilters( e.state.url );
2295			} else if( typeof self._cache.mainContent[self.location()] != 'undefined' && self._history > 0 ) {
2296				update();
2297
2298				self._render( self._cache.mainContent[self.location()].html, self._cache.mainContent[self.location()].json, true );
2299
2300				setFilters( self.location() );
2301			} else if( self._changed && self._history > 0 ) {
2302				setFilters( self._startUrl.toString() );
2303
2304				self.ajax( null, true );
2305			}
2306
2307			self._history--;
2308		};
2309	},
2310	
2311	count: function( obj ) {
2312		var c = 0;
2313		
2314		for( var i in obj ) {
2315			c++;
2316		}
2317		
2318		return c;
2319	},
2320	
2321	setFiltersByUrl: function( params ) {
2322		var self	= this;
2323		
2324		if( typeof params == 'undefined' ) {
2325			params = self.urlToFilters();
2326		}
2327		
2328		self.resetFilters();
2329		
2330		self._box.find('li[data-type]').each(function(){
2331			var _this	= jQuery(this),
2332				type	= _this.attr('data-type'),
2333				seoName	= _this.attr('data-seo-name'),
2334				value	= params[seoName];
2335			
2336			if( typeof value == 'undefined' || typeof value[0] == 'undefined' )
2337				return;
2338					
2339			switch( type ) {
2340				case 'rating' :
2341				case 'stock_status' :
2342				case 'manufacturers' :
2343				case 'image' :
2344				case 'image_radio' :
2345				case 'radio' :
2346				case 'image_list_radio' :
2347				case 'image_list_checkbox' :
2348				case 'checkbox' : {
2349					for( var i in value ) {
2350						if( typeof value[i] == 'function' ) continue;
2351						
2352						if( type == 'image_radio' || type == 'radio' || type == 'image_list_radio' ) {
2353							_this.find('.mfilter-image-checked').removeClass('mfilter-image-checked');
2354						}
2355						
2356						var $p1 = _this.find('input[value="' + self.decode( decodeURIComponent( value[i] ) ).replace( /"/g, '&quot;' ) + '"]').prop('checked', true)
2357							.parent();
2358						
2359						$p1.parent()
2360							.addClass('mfilter-input-active').find('.mfilter-counter').addClass('mfilter-close');
2361						
2362						if( $p1.hasClass( 'mfilter-image' ) ) {
2363							$p1.addClass('mfilter-image-checked');
2364						}
2365					}
2366					
2367					break;
2368				}
2369				case 'select' : {
2370					_this.find('select option[value="' + self.decode( decodeURIComponent( value[0] ) ).replace( /"/g, '&quot;' ) + '"]').attr('selected', true);
2371						
2372					break;
2373				}
2374				case 'price' : {
2375					if( typeof value[0] != 'undefined' && typeof value[1] != 'undefined' ) {
2376						_this.find('input[id="mfilter-opts-price-min"]').val( value[0] );
2377						_this.find('input[id="mfilter-opts-price-max"]').val( value[1] );
2378
2379						_this.find('[id="mfilter-price-slider"]').each(function(){					
2380							//jQuery(this).slider( 'option', 'min', value[0] );
2381							//jQuery(this).slider( 'option', 'max', value[1] );
2382							jQuery(this).slider( 'option', 'values', [ value[0], value[1] ] );
2383							jQuery(this).slider( 'value', jQuery(this).slider('value') );
2384						});
2385					}
2386					
2387					break;
2388				}
2389				case 'text' :
2390				case 'search' : {
2391					_this.find('input').val( self.decode( decodeURIComponent( value[0] ) ) );
2392					
2393					break;
2394				}
2395			}
2396		});
2397		
2398		for( var i = 0; i < self._sliders.length; i++ ) {
2399			self._sliders[i].setValues();
2400		}
2401	},
2402	
2403	/**
2404	 * Pokaż loader
2405	 */
2406	_showLoader: function() {
2407		var self = this;
2408				
2409		if( self._jqLoader == null && self._options.showLoaderOverResults ) {
2410			self.__initLoader();
2411		}
2412		
2413		if( self._jqLoaderFilter == null && self._options.showLoaderOverFilter ) {
2414			self.__initLoaderFilter();
2415		}
2416		
2417		if( self._options.showLoaderOverResults ) {
2418			(function(){
2419				var w = self._jqContent.outerWidth(),
2420					h = self._jqContent.outerHeight(),
2421					j = self._jqContent.find('.product-list'),
2422					k = j.length ? j : self._jqContent.find('.product-grid'),
2423					l = k.length ? k : self._jqContent,
2424					t = k.length ? k.offset().top - 150 : l.offset().top;
2425
2426				self._jqLoader
2427					.css('width', w + 'px')
2428					.css('height', h + 'px')
2429					.fadeTo('normal', 1)
2430					.find('img')
2431					.css('margin-top', t + 'px');
2432			})();
2433		}
2434		
2435		if( self._options.showLoaderOverFilter ) {
2436			(function(){
2437				var w = self._box.outerWidth(),
2438					h = self._box.outerHeight();
2439				
2440				self._jqLoaderFilter
2441					.css('width', w + 'px')
2442					.css('height', h + 'px')
2443					.fadeTo('normal',1);
2444			})();
2445		}
2446		
2447		if( self._options.autoScroll ) {
2448			jQuery('html,body').stop().animate({
2449				scrollTop: self._jqContent.offset().top + self._options.addPixelsFromTop
2450			}, 'low', function(){
2451				self._busy = false;
2452				self.render();
2453			});
2454		} else {
2455			self._busy = false;
2456			self.render();
2457		}
2458	},
2459	
2460	/**
2461	 * Ukryj loader
2462	 */
2463	_hideLoader: function() {
2464		var self = this;
2465		
2466		if( self._jqLoader !== null ) {		
2467			self._jqLoader.remove();
2468			self._jqLoader = null;
2469		}
2470		
2471		if( self._jqLoaderFilter !== null ) {
2472			self._jqLoaderFilter.remove();
2473			self._jqLoaderFilter = null;
2474		}
2475	},
2476	
2477	/**
2478	 * Pokaż wczytane dane
2479	 */
2480	render: function( history ) {
2481		var self = this;
2482		
2483		if( self._lastResponse === '' || self._busy ) {
2484			return;
2485		}
2486		
2487		self._hideLoader();
2488		
2489		// usuń wszystkie linki do skryptów JS
2490		self._lastResponse = self._lastResponse.replace( /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '' );
2491		
2492		var tmp = jQuery('<tmp>').html( self._lastResponse ),
2493			content = tmp.find(self._contentId), // znajdź treść główną
2494			json = tmp.find('#mfilter-json'); // informacje JSON zawierające dane o ilości produktów wg kategorii
2495			
2496		if( ! content.length && self._contentId != '#content' ) {
2497			content = tmp.find('#content');
2498		}
2499			
2500		if( content.length ) {
2501			var styles = self._jqContent.html().match( /<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi );
2502			
2503			if( styles != null && styles.length ) {
2504				for( var i = 0; i < styles.length; i++ ) {
2505					jQuery('head:first').append( styles[i] );
2506				}
2507			}
2508			
2509			self._render( content.html(), json && json.length ? self.base64_decode(json.html()) : null, history );
2510			
2511			self._lastResponse = '';
2512		} else {
2513			self.reload();
2514		}
2515	},
2516	
2517	_render: function( html, json, history ) {
2518		var self = this;
2519		
2520		if( history !== true ) {
2521			self._lastUrl = self.createUrl();
2522			
2523			if( self._ajaxPagination !== null ) {
2524				self._lastUrl += self._lastUrl.indexOf( '?' ) > -1 ? '&' : '?';
2525				self._lastUrl += 'page=' + self._ajaxPagination;
2526				
2527				self._ajaxPagination = null;
2528			}
2529			
2530			self._urlToFilters = null;
2531			
2532			if( self._options.seo.enabled ) {
2533				var u = self.parse_url( self._lastUrl );
2534				
2535				self._lastUrl = '';
2536				self._lastUrl += u.scheme + '://';
2537				self._lastUrl += u.host;
2538				self._lastUrl += decodeURIComponent( u.path ).replace( /\/mfp,([a-z0-9\-_]+\[[^\]]*\],?)+/g, '' );
2539				
2540				if( typeof u.query != 'undefined' && u.query ) {
2541					var data = jQuery.parseJSON( json );
2542					
2543					//if( u.path != '/' ) {
2544						var mfp = u.query.match( /mfp=([^&]+)/ );
2545						
2546						self._lastUrl = self._lastUrl.replace( /\/$/, '' );
2547						
2548						if( mfp ) {
2549							self._lastUrl += typeof data['url_alias'] == 'undefined' ? '/mfp,' + mfp[1] : '/' + data['url_alias'];
2550							u.query = u.query.replace( 'mfp=' + mfp[1], '' );
2551							u.query = u.query.replace( /^(\?|&)|&$/g, '' );
2552						}
2553						
2554						if( u.query != '' ) {
2555							self._lastUrl += '?' + u.query;
2556						}
2557					//} else {
2558					//	self._lastUrl += '?' + u.query;
2559					//}
2560				}
2561			}
2562			
2563			try {
2564				window.history.pushState({
2565					'html'	: html,
2566					'json'	: json,
2567					'url'	: self._lastUrl
2568				}, '', self._lastUrl );
2569				
2570				self._history++;
2571			} catch( e ) {}
2572		}
2573		
2574		if( json ) {
2575			self.eachInstances(function( self ){
2576				self._parseInfo( json );
2577			});
2578		}
2579		
2580		self.beforeRender( self._lastResponse, html, json );
2581			
2582		self._jqContent.html( html );
2583			
2584		/*if( self._box.hasClass( 'mfilter-content_top' ) ) {
2585			self._jqContent.prepend( self._box.removeClass('init') );
2586			self.init( self._box, self._options );
2587		}*/
2588			
2589		if( typeof jQuery.totalStorage == 'function' && jQuery.totalStorage('display') ) {
2590			display_MFP( jQuery.totalStorage('display') );
2591		} else if( typeof jQuery.cookie == 'function' && jQuery.cookie('display') ) {
2592			display_MFP( jQuery.cookie('display') );
2593		} else {
2594			display_MFP( 'list' );
2595		}
2596			
2597		for( var i in self ) {
2598			if( i.indexOf( '_initAlways' ) === 0 && typeof self[i] == 'function' ) {
2599				self[i]();
2600			}
2601		}
2602		
2603		for( var f = 0; f < self._liveFilters.length; f++ ) {
2604			self._liveFilters[f].check();
2605		}
2606		
2607		// Support for Product Quantity Extension (15186)
2608		if( typeof pq_initExt == 'function' ) {
2609			pq_initExt();
2610		}
2611		
2612		if( self._options.routeHome == self._options.route && self._options.homePageAJAX ) {
2613			self._jqContent.find('.pagination > li > a').unbind('click').bind('click', function(){
2614				self.ajax( jQuery(this).attr('href') );
2615				
2616				return false;
2617			});
2618		}
2619		
2620		if( self._relativeScroll ) {
2621			self._relativeScroll.reinit();
2622		}
2623		
2624		self.afterRender( self._lastResponse, html, json );
2625	},
2626	
2627	beforeRequest: function(){},
2628	
2629	beforeRender: function(){},
2630	
2631	afterRender: function(){},
2632	
2633	eachInstances: function( fn, skipCurrent ) {
2634		for( var i = 0; i < MegaFilterINSTANCES.length; i++ ) {
2635			if( skipCurrent === true && i == this._instanceIdx ) continue;
2636			
2637			fn( MegaFilterINSTANCES[i] );
2638		}
2639	},
2640	
2641	/**
2642	 * Załaduj dane
2643	 */
2644	ajax: function( url, history ) {
2645		var self = this;
2646		
2647		if( self._busy ) {
2648			self._waitingChanges = true;
2649			
2650			return;
2651		}
2652		
2653		(function(){
2654			var filters = self.filters( true );
2655			
2656			self.eachInstances(function( self ){
2657				var params = $.extend( self.filters(), filters );
2658				
2659				self.setFiltersByUrl( params );
2660			}, true);
2661		})();
2662		
2663		if( typeof url == 'undefined' || url === null ) {
2664			//url	= [ self._options.routeProduct, self._options.routeHome ].indexOf( self._options.route ) > -1 ? self.createUrl( self._options.ajaxResultsUrl ) : self.createUrl();
2665			url = [ self._options.routeProduct, self._options.routeHome, self._options.routeInformation, self._options.routeManufacturerList ].indexOf( self._options.route ) > -1 ? self.createUrl( self._options.ajaxResultsUrl ) : self.createUrl();
2666		}
2667		
2668		var cname	= url + self._options.idx;
2669		
2670		if( ( ! self._options.homePageAJAX && self._options.routeHome == self._options.route ) || [ self._options.routeProduct, self._options.routeInformation, self._options.routeManufacturerList ].indexOf( self._options.route ) > -1 ) {
2671		//if( ( ! self._options.homePageAJAX && self._options.routeHome == self._options.route ) || self._options.routeProduct == self._options.route ) {
2672			window.location.href = url;return;
2673		}
2674		
2675		self.eachInstances(function( self ){
2676			self._busy = true;
2677			self._lastResponse = '';
2678		});
2679		
2680		self._showLoader();
2681		
2682		if( typeof self._params['page'] != 'undefined' ) {
2683			delete self._params['page'];
2684		}
2685		
2686		if( typeof self._cache.lastResponse[cname] != 'undefined' ) {
2687			self.eachInstances(function( self2 ){
2688				self2._lastResponse = self._cache.lastResponse[cname];
2689			});
2690			
2691			setTimeout(function(){
2692				self.eachInstances(function( self ){
2693					self._busy = false;
2694				});
2695				
2696				self.render( history );
2697			}, 100);
2698			
2699			return;
2700		}
2701		
2702		if( self.beforeRequest() === false ) {
2703			return;
2704		}
2705		
2706		self._changed = true;
2707		
2708		jQuery.ajax({
2709			'type'		: 'GET',
2710			'url'		: self._ajaxUrl( url ),
2711			'timeout'	: 60 * 1000,
2712			'cache'		: false,
2713			'data'		: {
2714				'mfilterAjax'	: '1',
2715				'mfilterIdx'	: self._options.idx,
2716				'mfilterBTypes'	: self.baseTypes().join(','),
2717				'mfilterPath'	: typeof self._options.params.mfp_org_path != 'undefined' ? self._options.params.mfp_org_path : self._options.params.path,
2718				'mfilterLPath'	: self.locationPath()
2719			},
2720			'success'	: function( response ) {
2721				self.eachInstances(function( self ){
2722					self._busy = false;
2723				});
2724				
2725				if( response ) {
2726					self.eachInstances(function( self ){
2727						self._lastResponse	= response;
2728						self._cache.lastResponse[cname]	= response;
2729					});
2730					
2731					self.render( history );
2732					
2733					if( self._waitingChanges ) {
2734						self._waitingChanges = false;
2735						self.ajax();
2736					}
2737				} else {
2738					self.reload();
2739				}
2740			},
2741			'error'		: function() {
2742				self.reload();
2743			}
2744		});
2745	},
2746	
2747	/**
2748	 * Utwórz pełny adres URL
2749	 */
2750	createUrl: function( url, attribs, force ) {
2751		var self	= this,
2752			params	= self.paramsToUrl( url, attribs ),
2753			filters	= self.filtersToUrl(),
2754			urlSep	= self._urlSep;
2755		
2756		if( typeof url == 'undefined' ) {
2757			url = self._url;
2758		} else {
2759			urlSep = self._parseSep( url.split('#')[0] ).urlSep;
2760			url = self._parseSep( url.split('#')[0] ).url;
2761		}
2762		
2763		url = decodeURIComponent( url ).replace( /\/mfp,([a-z0-9\-_]+\[[^]]*\],?)+/, '' );
2764		
2765		if( params || filters ) {
2766			url += urlSep.f;
2767			
2768			if( params ) {
2769				url += params;
2770			}
2771			
2772			if( filters ) {
2773				if( params ) {
2774					url += urlSep.n;
2775				}
2776				
2777				url += 'mfp' + ( urlSep.n == '&' ? '=' : urlSep.n ) + filters;
2778			} else if( force ) {
2779				var mfp = self.filtersToUrl( self.urlToFilters() );
2780
2781				if( mfp ) {
2782					url += urlSep.n;
2783					url += 'mfp' + ( urlSep.n == '&' ? '=' : urlSep.n ) + mfp;
2784				}
2785			}
2786		}
2787		
2788		return url;
2789	},
2790	
2791	/**
2792	 * Sprawdź poprawność wpisanego zakresu cen
2793	 * 
2794	 * @return bool
2795	 */
2796	_validPrice: function( min, max ) {
2797		var self = this;
2798		
2799		min = parseInt( min );
2800		max = parseInt( max );
2801		
2802		if( min < self._options.priceMin )
2803			return false;
2804		
2805		if( max > self._options.priceMax )
2806			return false;
2807		
2808		if( min > max )
2809			return false;
2810		
2811		if( min == max && min == self._options.priceMin && max == self._options.priceMax )
2812			return false;
2813		
2814		return true;
2815	},
2816	
2817	/**
2818	 * Przekształć parametry z adresu URL na obiekt
2819	 * 
2820	 * @return object
2821	 */
2822	urlToFilters: function() {
2823		if( this._urlToFilters !== null ) {
2824			return this._urlToFilters;
2825		}
2826		
2827		var self = this;
2828			
2829		self._urlToFilters = {};
2830		
2831		if( ! self._params.mfp )
2832			return self._urlToFilters;
2833		
2834		self._params.mfp =  decodeURIComponent( self._params.mfp );
2835		
2836		self._urlToFilters = self.__urlToFilters( self._params.mfp );
2837		
2838		return self._urlToFilters;
2839	},
2840	
2841	__urlToFilters: function( mfp ) {
2842		var self	= this,
2843			obj		= {},
2844			matches	= mfp.match( /[a-z0-9\-_]+\[[^\]]+\]/g );
2845		
2846		if( ! matches ) {
2847			return obj;
2848		}
2849		
2850		for( var i = 0; i < matches.length; i++ ) {
2851			var key = matches[i].match( /([a-z0-9\-_]+)\[[^\]]+\]/ )[1],
2852				val = matches[i].match( /[a-z0-9\-_]+\[([^\]]+)\]/ )[1].split(',');
2853			
2854			switch( key ) {
2855				case 'price' : {
2856					if( typeof val[0] != 'undefined' && val[1] != 'undefined' ) {
2857						if( self._validPrice( val[0], val[1] ) )
2858							obj[key] = val;
2859					}
2860					
2861					break;
2862				}
2863				default : {
2864					obj[key] = val;
2865				}
2866			}
2867		}
2868		
2869		return obj;
2870	},
2871	
2872	resetFilters: function(){
2873		var self	= this;
2874		
2875		self._box.find('li[data-type]').each(function(){
2876			var _this		= jQuery(this),
2877				type		= _this.attr('data-type'),
2878				baseType	= _this.attr('data-base-type'),
2879				defaultVal	= null;
2880				
2881			_this.find('.mfilter-input-active').removeClass('mfilter-input-active');
2882			
2883			if( baseType == 'stock_status' && self._options.inStockDefaultSelected ) {
2884				defaultVal = self._options.inStockStatus;
2885			}
2886			
2887			switch( type ) {
2888				case 'image_radio' :
2889				case 'image' : {
2890					_this.find('input[type=checkbox]:checked,input[type=radio]:checked').prop('checked', false).parent().removeClass('mfilter-image-checked');
2891					
2892					break;
2893				}
2894				case 'cat_checkbox' : {
2895					_this.find('input[type=checkbox]:checked').prop('checked', false);
2896					_this.find('.mfilter-counter').removeClass('mfilter-close');
2897					
2898					break;
2899				}
2900				case 'tree' : {
2901					_this.find('input[name=path]').val( typeof self._options.params.path == 'undefined' ? '' : self._options.params.path );
2902					
2903					break;
2904				}
2905				case 'rating' :
2906				case 'stock_status' :
2907				case 'manufacturers' :
2908				case 'checkbox' : 
2909				case 'image_list_checkbox' : 
2910				case 'image_list_radio' : 
2911				case 'radio' : {
2912					_this.find('input[type=checkbox]:checked,input[type=radio]:checked').prop('checked', false);
2913					_this.find('.mfilter-counter').removeClass('mfilter-close');
2914					
2915					if( defaultVal !== null ) {
2916						_this.find('input[value="' + defaultVal.replace( /"/g, '&quot;' ) + '"]').prop('checked', true)
2917							.parent().parent().find('.mfilter-counter').addClass('mfilter-close');
2918					}
2919					
2920					break;
2921				}
2922				case 'search_oc' :
2923				case 'search' : {
2924					_this.find('input[id="mfilter-opts-search"]').val( '' );
2925						
2926					break;
2927				}
2928				case 'text' : {
2929					_this.find('input[type=text]').val( '' );
2930					
2931					break;
2932				}
2933				case 'slider' : {					
2934					
2935					
2936					break;
2937				}
2938				case 'price' : {
2939					_this.find('input[id="mfilter-opts-price-min"]').val( self._options.priceMin );
2940					_this.find('input[id="mfilter-opts-price-max"]').val( self._options.priceMax );
2941					_this.find('[id="mfilter-price-slider"]').each(function(){					
2942						jQuery(this).slider( 'option', 'min', self._options.priceMin );
2943						jQuery(this).slider( 'option', 'max', self._options.priceMax );
2944						jQuery(this).slider( 'option', 'values', [ self._options.priceMin, self._options.priceMax ] );
2945						jQuery(this).slider( 'value', jQuery(this).slider('value') );
2946					});
2947					
2948					break;
2949				}
2950				case 'related' :
2951				case 'select' : {
2952					_this.find('select option').removeAttr('selected');
2953					
2954					if( defaultVal !== null ) {
2955						_this.find('select option').each(function(i){
2956							if( jQuery(this).val() == defaultVal ) {
2957								jQuery(this).attr('selected', true);
2958								_this.find('select').prop('selectedIndex', i);
2959								
2960								return false;
2961							}
2962						});
2963					} else {
2964						_this.find('select option:first').attr('selected', true);
2965						_this.find('select').prop('selectedIndex', 0);
2966					}
2967					
2968					if( type == 'related' ) {
2969						_this.find('select').each(function(i){
2970							if( i ) {
2971								if( _this.attr('data-auto-levels') ) {
2972									jQuery(this).parent().remove();
2973								} else {
2974									jQuery(this).find('option[value!=""]').remove();
2975								}
2976							}
2977						});
2978					}
2979					
2980					break;
2981				}
2982			}
2983		});
2984		
2985		for( var i = 0; i < self._sliders.length; i++ ) {
2986			self._sliders[i].resetValues();
2987		}
2988	},
2989	
2990	/**
2991	 * Pobierz aktualne wartości filtrów
2992	 * 
2993	 * @return object
2994	 */
2995	filters: function( alsoEmpty ) {
2996		var self	= this,
2997			params	= { },
2998			stockStatusExist = self._box.find('li[data-base-type="stock_status"]').length ? true : false;
2999				
3000		self._box.find('li[data-type]').each(function(){
3001			var _this	= jQuery(this),
3002				type	= _this.attr('data-type'),
3003				seoName	= _this.attr('data-seo-name');
3004				
3005			if( alsoEmpty === true ) {
3006				if( typeof params[seoName] == 'undefined' ) {
3007					params[seoName] = [];
3008				}
3009			}
3010					
3011			switch( type ) {
3012				case 'cat_checkbox' : 
3013				case 'rating' :
3014				case 'stock_status' : 
3015				case 'manufacturers' :
3016				case 'image_list_checkbox' :
3017				case 'image' :
3018				case 'checkbox' : {
3019					_this.find('input[type=checkbox]:checked').each(function(){
3020						if( typeof params[seoName] == 'undefined' ) {
3021							params[seoName] = [];
3022							
3023							/*if( type == 'cat_checkbox' ) {
3024								if( typeof self._options.params.mfp_org_path != 'undefined' ) {
3025									params[seoName].push( self._options.params.mfp_org_path );
3026								} else if( typeof self._options.params.path != 'undefined' ) {
3027									params[seoName].push( self._options.params.path );
3028								}
3029							}*/
3030						}
3031						
3032						params[seoName].push( encodeURIComponent( self.encode( jQuery(this).val() ) ) );
3033					});
3034					
3035					break;
3036				}
3037				case 'image_radio' :
3038				case 'image_list_radio' :
3039				case 'radio' : {
3040					_this.find('input[type=radio]:checked').each(function(){
3041						params[seoName] = [ encodeURIComponent( self.encode( jQuery(this).val() ) ) ];
3042					});
3043						
3044					break;
3045				}
3046				case 'slider' : {
3047					var slider_id = _this.attr('data-slider-id'),
3048						slider_vals = self._sliders[slider_id].getValues();
3049						
3050					if( slider_vals.length ) {
3051						params[seoName] = slider_vals;
3052					}
3053					
3054					break;
3055				}
3056				case 'price' : {
3057					var priceRange = self.getPriceRange();
3058					
3059					if( priceRange.min != self._options.priceMin || priceRange.max != self._options.priceMax ) {
3060						if( self._validPrice( priceRange.min, priceRange.max ) )
3061							params[seoName] = [ priceRange.min, priceRange.max ];
3062					}
3063					
3064					break;
3065				}
3066				case 'search_oc' :
3067				case 'search' : {
3068					_this.find('input[id="mfilter-opts-search"]').each(function(){
3069						if( jQuery(this).val() !== '' ) {
3070							params[seoName] = [ encodeURIComponent( self.encode( jQuery(this).val() ) ) ];
3071						}
3072					});
3073					
3074					break;
3075				}
3076				case 'text' : {
3077					_this.find('input[type=text]').each(function(){
3078						if( jQuery(this).val() != '' ) {
3079							params[seoName] = [ encodeURIComponent( self.encode( jQuery(this).val() ) ) ];
3080						}
3081					});
3082					
3083					break;
3084				}
3085				case 'select' : {
3086					_this.find('select').each(function(){
3087						if( jQuery(this).val() )
3088							params[seoName] = [ encodeURIComponent( self.encode( jQuery(this).val() ) ) ];
3089					});
3090						
3091					break;
3092				}
3093				case 'related' : {
3094					//if( _this.find('select:last').val() ) {
3095						_this.find('select').each(function(){
3096							var val = jQuery(this).val();
3097							
3098							if( val ) {							
3099								if( typeof params[seoName] == 'undefined' )
3100									params[seoName] = [];
3101
3102								params[seoName].push( val );
3103							}
3104						});
3105					//}
3106				}
3107				case 'tree' : {
3108					_this.find('input').each(function(){
3109						var val = jQuery(this).val(),
3110							path = typeof self._options.params.mfp_org_path == 'undefined' ? self._options.params.path : self._options.params.mfp_org_path;
3111						
3112						if( val && val != path ) {
3113							params['path'] = [ val ];
3114						}
3115					});
3116					
3117					break;
3118				}
3119			}
3120		});
3121		
3122		// sprawdź czy domyślnie powinna być zaznaczona opcja "in stock"
3123		if( self._options.inStockDefaultSelected && typeof params['stock_status'] == 'undefined' ) {
3124			params['stock_status'] = stockStatusExist ? [] : [ self._options.inStockStatus ];
3125		}
3126		
3127		return params;
3128	},
3129			
3130	/**
3131	 * Utwórz URL na podstawie parametrów
3132	 */
3133	filtersToUrl: function( params ) {
3134		var self	= this,
3135			url		= '';
3136		
3137		if( typeof params == 'undefined' ) {
3138			params	= self.filters();
3139		
3140			self.eachInstances(function( self ){
3141				params = $.extend( self.filters(), params );
3142			}, true);
3143		}
3144				
3145		for( var i in params ) {
3146			url += url ? ',' : '';
3147			url += '' + i + '[' + params[i].join(',') + ']';
3148		}
3149			
3150		return url;
3151	},
3152	
3153	/**
3154	 * Przekształć parametry na adres URL
3155	 * 
3156	 * @return string
3157	 */
3158	paramsToUrl: function( url, attribs ) {
3159		var self	= this,
3160			params	= typeof url == 'undefined' ? self._params : self._parseUrl( url, attribs ),
3161			urlSep	= typeof url == 'undefined' ? self._urlSep : self._parseSep( url ).urlSep;
3162		
3163		return self._paramsToUrl( params, {
3164			'skip'	: [ 'mfilter-ajax', 'mfp', 'page' ],
3165			'sep'	: urlSep.n,
3166			'sep2'	: urlSep.n == '&' ? '=' : urlSep.n,
3167			'fn'	: function( i ) {
3168				return typeof url == 'undefined' && typeof self._inUrl[i] == 'undefined';
3169			}
3170		});
3171	},
3172	
3173	_paramsToUrl: function( params, o ) {
3174		var url = '';
3175		
3176		o = jQuery.extend({
3177			'skip'	: [],
3178			'sep'	: '&',
3179			'sep2'	: '=',
3180			'fn'	: function(){}
3181		}, typeof o == 'object' ? o : {});
3182		
3183		for( var i in params ) {
3184			if( o.skip.indexOf( i ) > -1 ) continue;
3185			
3186			if( o.fn( i, params[i] ) ) continue;
3187			
3188			url += url ? o.sep : '';
3189			url += i + o.sep2 + params[i];
3190		}
3191		
3192		return url;
3193	},
3194		
3195	/**
3196	 * @param url string
3197	 * @param attribs object
3198	 * @return object
3199	 */
3200	_parseUrl: function( url, attribs ) {		
3201		if( typeof attribs != 'object' )
3202			attribs = {
3203				'mfilter-ajax'	: '1'
3204			};
3205		
3206		if( typeof url == 'undefined' )
3207			return attribs;
3208			
3209		var self	= this,
3210			params, i, name, value, param,
3211			mfp;
3212		
3213		url = url.split('#')[0];
3214		mfp = url.match( /\/mfp,([a-z0-9\-_]+\[[^\]]*\],?)+/g );
3215		
3216		if( mfp ) {
3217			attribs['mfp'] = mfp[0].replace( /^\/mfp,/, '' );
3218		}
3219		
3220		if( url.indexOf( '?' ) > -1 || url.indexOf( '&' ) > -1 ) {
3221			params = typeof self.parse_url( url ).query != 'undefined' ? self.parse_url( url ).query.split('&') : url.split('&');
3222			
3223			for( i = 0; i < params.length; i++ ) {
3224				if( params[i].indexOf( '=' ) < 0 ) continue;
3225				
3226				param	= params[i].split('=');
3227				name	= param[0];
3228				value	= param[1];
3229
3230				if( ! name ) continue;
3231
3232				attribs[name] = value;
3233			}
3234		} else {
3235			params	= url.split( ';' );
3236			name	= null;
3237				
3238			for( i = 1; i < params.length; i++ ) {
3239				if( name === null )
3240					name = params[i];
3241				else {
3242					attribs[name] = params[i];
3243					name = null;
3244				}
3245			}
3246		}
3247		
3248		return attribs;
3249	},
3250	
3251	/**
3252	 * Przeładuj stronę
3253	 */
3254	reload: function() {
3255		var self = this;
3256		
3257		window.location.href = self.createUrl();
3258	}
3259};
3260var MegaFilterLang = {};
3261
3262function display_MFP(view) {
3263	// Product List
3264	jQuery('#list-view').click(function() {
3265		jQuery('#content .product-layout > .clearfix').remove();
3266
3267		jQuery('#content .product-layout').attr('class', 'product-layout product-list col-xs-12');
3268
3269		localStorage.setItem('display', 'list');
3270	});
3271
3272	// Product Grid
3273	jQuery('#grid-view').click(function() {
3274		jQuery('#content .product-layout > .clearfix').remove();
3275
3276		// What a shame bootstrap does not take into account dynamically loaded columns
3277		cols = jQuery('#column-right, #column-left').length;
3278
3279		if (cols == 2) {
3280			jQuery('#content .product-layout').attr('class', 'product-layout product-grid col-lg-6 col-md-6 col-sm-12 col-xs-12');
3281
3282			jQuery('#content .product-layout:nth-child(2)').after('<div class="clearfix visible-md visible-sm"></div>');
3283		} else if (cols == 1) {
3284			jQuery('#content .product-layout').attr('class', 'product-layout product-grid col-lg-4 col-md-4 col-sm-6 col-xs-12');
3285
3286			jQuery('#content .product-layout:nth-child(3)').after('<div class="clearfix visible-lg"></div>');
3287		} else {
3288			jQuery('#content .product-layout').attr('class', 'product-layout product-grid col-lg-3 col-md-3 col-sm-6 col-xs-12');
3289
3290			jQuery('#content .product-layout:nth-child(4)').after('<div class="clearfix"></div>');
3291		}
3292
3293		 localStorage.setItem('display', 'grid');
3294	});
3295
3296	if (localStorage.getItem('display') == 'list') {
3297		jQuery('#list-view').trigger('click');
3298	} else {
3299		jQuery('#grid-view').trigger('click');
3300	}
3301}

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.