PageSourceSearch

https://stagebuddy.com/wp-content/plugins/wp-views/embedded/res/js/wpv-pagination-embedded.js?ver=2.3.1

js stagebuddy.com collected 2026-10-02 04:21:17 UTC 143,469 bytes, 3,971 lines download raw bytes

1var WPViews = WPViews || {};
2
3var wpv_stop_rollover = {};
4window.wpvPaginationAjaxLoaded = {};
5window.wpvPaginationAnimationFinished = {};
6window.wpvPaginationQueue = {};
7
8// ------------------------------------
9// Clone
10// ------------------------------------
11
12// Textarea and select clone() bug workaround | Spencer Tipping
13// Licensed under the terms of the MIT source code license
14// Motivation.
15// jQuery's clone() method works in most cases, but it fails to copy the value of textareas and select elements. This patch replaces jQuery's clone() method with a wrapper that fills in the
16// values after the fact.
17// An interesting error case submitted by Piotr Przybyl: If two <select> options had the same value, the clone() method would select the wrong one in the cloned box. The fix, suggested by Piotr
18// and implemented here, is to use the selectedIndex property on the <select> box itself rather than relying on jQuery's value-based val().
19;( function() {
20    jQuery.fn.wpv_clone = function() {
21        var result = jQuery.fn.clone.apply( this, arguments ),
22		my_textareas = this.find( 'textarea' ).add( this.filter( 'textarea' ) ),
23		result_textareas = result.find( 'textarea' ).add( result.filter( 'textarea' ) ),
24		my_selects = this.find( 'select' ).add( this.filter( 'select' ) ),
25		result_selects = result.find( 'select' ).add( result.filter( 'select' ) );
26		for ( var i = 0, l = my_textareas.length; i < l; ++i ) {
27			jQuery( result_textareas[i] ).val( jQuery( my_textareas[i] ).val() );
28		}
29		for ( var i = 0, l = my_selects.length; i < l; ++i ) {
30			for ( var j = 0, m = my_selects[i].options.length; j < m; ++j ) {
31				if ( my_selects[i].options[j].selected === true ) {
32					result_selects[i].options[j].selected = true;
33				} else {
34					result_selects[i].options[j].selected = false;
35				}
36			}
37		}
38        return result;
39    };
40})();
41
42WPViews.ViewFrontendUtils = function( $ ) {
43	
44	// ------------------------------------
45	// Constants and variables
46	// ------------------------------------
47	
48	var self = this;
49	
50	self.datepicker_style_id		= 'js-toolset-datepicker-style';
51	self.is_datepicker_style_loaded	= false;
52	
53	// ------------------------------------
54	// Methods
55	// ------------------------------------
56	
57	self.just_return = function() {
58		return;
59	};
60	
61	/**
62	* extract_url_query_parameters
63	*
64	* Extracts parameters from a query string, managing arrays, and returns an array of pairs key => value
65	*
66	* @param string query_string
67	*
68	* @return array
69	*
70	* @note ##URLARRAYVALHACK## is a hacky constant
71	*
72	* @uses decodeURIComponent
73	*
74	* @since 1.9
75	*/
76	
77	self.extract_url_query_parameters = function( query_string ) {
78		var query_string_pairs = {};
79		if ( query_string == "" ) {
80			return query_string_pairs;
81		}
82		var query_string_split = query_string.split( '&' ),
83		query_string_split_length = query_string_split.length;
84		for ( var i = 0; i < query_string_split_length; ++i ) {
85			var qs_part = query_string_split[i].split( '=' );
86			if ( qs_part.length != 2 ) {
87				continue;
88			};
89			var thiz_key = qs_part[0],
90			thiz_val = decodeURIComponent( qs_part[1].replace( /\+/g, " " ) );
91			// Adjust thiz_key to work with POSTed arrays
92			thiz_key = thiz_key.replace( /(\[)\d?(\])/, "" );
93			thiz_key = thiz_key.replace( "[]", "" );// Just in case
94			thiz_key = thiz_key.replace( /(%5B)\d?(%5D)/, "" );
95			thiz_key = thiz_key.replace( "%5B%5D", "" );// Just in case
96			thiz_key = thiz_key.replace( /(%255B)\d?(%255D)/, "" );
97			thiz_key = thiz_key.replace( "%255B%255D", "" );// Just in case
98			if ( query_string_pairs.hasOwnProperty( thiz_key ) ) {
99				if ( query_string_pairs[thiz_key] != thiz_val ) {
100					// @hack alert!! We can not avoid using this :-(
101					query_string_pairs[thiz_key] += '##URLARRAYVALHACK##' + thiz_val;
102				} else {
103					query_string_pairs[thiz_key] = thiz_val;
104				}
105			} else {
106				query_string_pairs[thiz_key] = thiz_val;
107			}
108		}
109		return query_string_pairs;
110	};
111	
112	/**
113	* get_extra_url_query_parameters
114	*
115	* Gets the current URL query parameters, but only those that do not belong to the current form already.
116	*
117	* @note Arrays are returned on a single key with values on a single str
117ing, separated by the ##URLARRAYVALHACK## placeholder. We might review that later
118	* @note Since 2.2, force include URL parameters that belong to form controls when the form does not use dependency nor AJAX results.
119	* 		As the form should be posted with page reload in this case, and we are not performing a dependency call, URL parameters win over optios in the form
120	* 		and have been not recorded yet in the AJAX method manager.
121	*
122	* @return array
123	*
124	* @uses self.extract_url_query_parameters
125	*
126	* @since 2.1
127	*/
128
129	self.get_extra_url_query_parameters_by_form = function( form ) {
130		var query_string = self.extract_url_query_parameters( window.location.search.substr( 1 ) ),
131		data = {},
132		force_from_form = ! ( form.hasClass( 'js-wpv-dps-enabled' ) 
133			|| form.hasClass( 'js-wpv-ajax-results-enabled' ) 
134			|| form.hasClass( 'js-wpv-ajax-results-submit-enabled' ) 
135		);
136		for ( var prop in query_string ) {
137			if ( 
138				query_string.hasOwnProperty( prop ) 
139				&& ! data.hasOwnProperty( prop )
140				&& (
141					force_from_form 
142					|| form.find( '[name="' + prop + '"], [name="' + prop + '\\[\\]"]' ).length === 0 
143				)
144			) {
145				data[ prop ] = query_string[ prop ];
146			}
147		}
148		return data;
149	};
150	
151	/**
152	* set_extra_url_query_parameters
153	*
154	* Forces the current URL query parameters in a form, but only those that do not belong to the form already.
155	*
156	* @uses self.extract_url_query_parameters
157	*
158	* @since 2.1
159	*/
160
161	self.set_extra_url_query_parameters_by_form = function( form ) {
162		var extra = self.get_extra_url_query_parameters_by_form( form );
163		$.each( extra, function( key, value ) {
164			if ( form.find( '[name="' + key + '"], [name="' + key + '\\[\\]"]' ).length === 0 ) {
165				// @hack alert!! WE can not avoid this :-(
166				var pieces = value.split( '##URLARRAYVALHACK##' ),
167				pieces_length = pieces.length;
168				if ( pieces_length < 2 ) {
169					$( '<input>' ).attr({
170						type: 'hidden',
171						name: key,
172						value: value
173					})
174					.appendTo( form );
175				} else {
176					for ( var iter = 0; iter < pieces_length; iter++ ) {
177						$( '<input>' ).attr({
178							type: 'hidden',
179							name: key + "[]",
180							value: pieces[iter]
181						})
182						.appendTo( form );
183					}
184				}
185			}
186		});
187	};
188	
189	/**
190	 * Dynamically load the Toolset datepicker style, only when needed.
191	 *
192	 * @note we should do the same with mediaelement and wp-mediaelement
193	 * @note the handle for this used to be wptoolset-field-datepicker
194	 *
195	 * @since 2.3.0
196	 */
197	
198	self.maybe_load_datepicker_style = function() {
199		
200		if ( ! self.is_datepicker_style_loaded ) {
201			
202			if ( document.getElementById( self.datepicker_style_id ) ) {
203				
204				self.is_datepicker_style_loaded = true;
205				
206			} else {
207				
208				var head	= document.getElementsByTagName( 'head' )[0],
209					link	= document.createElement( 'link' );
210				
211				link.id 	= self.datepicker_style_id;
212				link.rel	= 'stylesheet';
213				link.type	= 'text/css';
214				link.href	= wpv_pagination_local.datepicker_style_url;
215				link.media	= 'all';
216				head.appendChild( link );
217				
218				self.is_datepicker_style_loaded = true;
219				
220			}
221				
222		}
223		
224	};
225	
226	/**
227	 * Destroy all initialized datepickers in the page, before doing changes and initializing them again.
228	 *
229	 * @since 2.3.0
230	 */
231	
232	self.destroy_frontend_datepicker = function() {
233		
234		$( ".js-wpv-frontend-datepicker.js-wpv-frontend-datepicker-inited" )
235			.removeClass( 'js-wpv-frontend-datepicker-inited' )
236			.datepicker( "destroy" );
237			
238	};
239	
240	/**
241	* render_frontend_datepicker
242	*
243	* Adds a datepicker to a selector but only if it has not been added before.
244	*
245	* Fired on document.ready, after AJAX pagination and after AJAX parametric search events.
246	*
247	* @since 1.9
248	*/
249	
250	self.render_frontend_datepicker = function() {
251		$( '.js-wpv-frontend-datepicker:not(.js-wpv-frontend-datepicker-inited)' ).each( function() {
252			self.maybe_load_datepicker_style();
253			var thiz = $( this );
254			thiz
255				.addClass( 'js-wpv-frontend-datepicker-inited' )
256				.datepicker({
257					onSelect: function( dateText, inst ) {
258						var url_param = thiz.data( 'param' ),
259						data = 'date=' + dateText,
260						form = thiz.closest( 'form' );
261						data += '&date-format=' + $( '.js-wpv-date-param-' + url_param + '-format' ).val();
262						data += '&action=wpv_format_date';
263						$.post( wpv_pagination_local.front_ajaxurl, data, function( response ) {
264							response = $.parseJSON( response );
265							form.find('.js-wpv-date-param-' + url_param ).html( response['display'] );
266							form.find('.js-wpv-date-front-end-clear-' + url_param ).show();
267							form.find('.js-wpv-date-param-' + url_param + '-value' ).val( response['timestamp'] ).trigger( 'change' );
268						});
269					},
270					dateFormat: 'ddmmyy',
271					minDate: wpv_pagination_local.datepicker_min_date,
272					maxDate: wpv_pagination_local.datepicker_max_date,
273					showOn: "button",
274					buttonImage: wpv_pagination_local.calendar_image,
275					buttonText: wpv_pagination_local.calendar_text,
276					buttonImageOnly: true,
277					changeMonth: true,
278					changeYear: true
279				});
280		});
281	};
282	
283	/**
284	* clone_form
285	*
286	* Clones a form using the fixed clone() method that covers select and textarea elements
287	*
288	* @param object fil
289	* @param array targets
290	*
291	* @since 1.9
292	*/
293	
294	self.clone_form = function( fil, targets ) {
295		var cloned = fil.wpv_clone();
296		targets.each( function() {
297			$( this ).replaceWith( cloned );
298		});
299	};
300	
301	/**
302	* render_frontend_media_shortcodes
303	*
304	* Render the WordPress media players for items inside a container.
305	*
306	* @param object container
307	*
308	* @since 1.9
309	*/
310	
311	self.render_frontend_media_shortcodes = function( container ) {
312		container.find( '.wp-audio-shortcode, .wp-video-shortcode' ).each( function() {
313			var thiz = $( this );
314			thiz.mediaelementplayer();
315		});
316		container.find( '.wp-playlist' ).each( function() {
317			var thiz = $( this );
318			return new WPPlaylistView({ el: this });
319		});
320	};
321	
322	/**
323	* get_form_element_type
324	*
325	* Get a form element type, be it text, radio, checkbox, textarea or select
326	*
327	* @param selector	A jQuery selector object
328	*
329	* @return string	'text'|'radio'|'checkbox'|'textarea'|'select'|empty if selector is empty
330	*
331	* @since 2.2
332	*/
333	
334	self.get_form_element_type = function( selector ) {
335		if ( selector.length > 0 ) {
336			return selector[0].tagName == "INPUT" ? selector[0].type.toLowerCase() : selector[0].tagName.toLowerCase();
337		} else {
338			return '';
339		}
340	}
341	
342	self.get_hidden_item_width = function( item ) {
343		var item_clone = item
344			.clone()
345				.css({
346					'display': 'block',
347					'visibility': 'visible',
348					'position': 'absolute',
349					'z-index': '-99999',
350					'left': '99999999px',
351					'top': '0px',
352					'white-space': 'nowrap'
353				})
354				.appendTo( 'body' ),
355			width = item_clone.outerWidth();
356		item_clone.remove();
357		return width;
358	};
359	
360	// ------------------------------------
361	// Get updated results
362	// ------------------------------------
363	
364	/**
365	* get_updated_query_results
366	*
367	* Shared method for paginating Views and WordPress Archives, and also for parametric search on both.
368	* Returns a promise so you can operate on the response at will.
369	*
370	* Note that it applis the current form regardless it being submitted or not.
371	* @todo we might want to avoid adding that data when the form contains unsubmitted changes.
372	*
373	* @param view_number	The object hash
374	* @param page			The page that we want to get
375	* @param form			The form to track changes against
376	* @param expect			'form'|'full'|'both' Whether to return the full View, just the form, or both
377	*
378	* @since 2.1
379	*/
380	
381	self.get_updated_query_results = function( view_number, page, form, expect ) {
382		var data				= {},
383		sort					= {},
384		environment				= {},
385		search					= {},
386		extra					= {}.
387		attributes				= {},
388		lang					= ( typeof icl_lang == 'undefined' ) ? false : icl_lang,
389		parametric_data			= form.data( 'parametric' );
390		
391		sort = WPViews.view_sorting.get_sort_data( view_number, form );
392		
393		if ( parametric_data['environment'].current_post_id > 0 ) {
394			environment['wpv_aux_current_post_id'] = parametric_data['environment'].current_post_id;
395		}
396		if ( parametric_data['environment'].parent_post_id > 0 ) {
397			environment['wpv_aux_parent_post_id'] = parametric_data['environment'].parent_post_id;
398		}
399		if ( parametric_data['environment'].parent_term_id > 0 ) {
400			environment['wpv_aux_parent_term_id'] = parametric_data['environment'].parent_term_id;
401		}
402		if ( parametric_data['environment'].parent_user_id > 0 ) {
403			environment['wpv_aux_parent_user_id'] = parametric_data['environment'].parent_user_id;
404		}
405		
406		environment['archive'] = parametric_data['environment'].archive;
407		
408		if ( form.find( '.js-wpv-post-relationship-update' ).length ) {
409			search['dps_pr'] = form.find( '.js-wpv-post-relationship-update' ).serializeArray();
410		}
411		if ( 
412			form.hasClass( 'js-wpv-dps-enabled' ) 
413			|| form.hasClass( 'js-wpv-ajax-results-enabled' ) 
414			|| form.hasClass( 'js-wpv-ajax-results-submit-enabled' ) 
415		) {
416			search['dps_general'] = form.find( '.js-wpv-filter-trigger, .js-wpv-filter-trigger-delayed' ).serializeArray();
417		}
418		
419		attributes = parametric_data['attributes'];
420		
421		extra = self.get_extra_url_query_parameters_by_form( form );
422		
423		data = {
424			'view_number':	view_number,
425			page:			page,
426			sort:			sort,
427			attributes:		attributes,
428			environment:	environment,
429			search:			search,
430			extra:			extra,
431			expect:			expect
432		};
433		
434		if ( lang ) {
435			data['lang'] = lang;
436		}
437		
438		switch ( parametric_data.query ) {
439			case 'archive':
440				data['action']	= 'wpv_get_archive_query_results';
441				data['loop']	= parametric_data.loop;
442				break;
443			default:
444				data['action']	= 'wpv_get_view_query_results';
445				data['id']		= parametric_data.id;
446				if ( form.attr( 'data-targetid' ) ) {
447					data['target_id'] = form.data( 'targetid' );
448				} else if ( $( '.js-wpv-form-only.js-wpv-filter-form-' + view_number ).length > 0 ) {
449					data['target_id'] = $( '.js-wpv-form-only.js-wpv-filter-form-' + view_number ).data( 'targetid' );
450				}
451				data['wpv_view_widget_id']	= parametric_data['widget_id'];
452				break;
453		}
454		return $.ajax({
455			type:		"POST",
456			dataType:	"json",
457			url:		wpv_pagination_local.front_ajaxurl,
458			data:		data
459		});
460	};
461
462    /**
463     * Add, update or remove query string argument.
464     *
465     * @param 	key		{string} 	Argument name
466     * @param 	value	{string} 	Argument value. Not supplying a value will remove the parameter, supplying one will
467     *     							add/update the argument.
468     * @param 	url		{string} 	The URL. If no URL is supplied, it will be grabbed from window.location
469     * @return	string				The updated URL.
470	 * @link http://stackoverflow.com/a/11654596/3191395
471     *
472     * @since 2.3
473     */
474    self.updateUrlQuery = function(key, value, url) {
475        if(!url) {
476            url = window.location.href;
477        }
478        var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi");
479        var hash;
480        if (re.test(url)) {
481            if (typeof value !== 'undefined' && value !== null) {
482                return url.replace(re, '$1' + key + "=" + value + '$2$3');
483            } else {
484                hash = url.split('#');
485                url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
486                if(typeof hash[1] !== 'undefined' && hash[1] !== null) {
487                    url += '#' + hash[1];
488                }
489                return url;
490            }
491        } else {
492            if (typeof value !== 'undefined' && value !== null) {
493                var separator = url.indexOf('?') !== -1 ? '&' : '?';
494                hash = url.split('#');
495                url = hash[0] + separator + key + '=' + value;
496                if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
497                    url += '#' + hash[1];
498                }
499                return url;
500            } else {
501                return url;
502            }
503        }
504    };
505
506	// ------------------------------------
507	// Events
508	// ------------------------------------
509	
510	/**
511	* Window resize event
512	*
513	* Make Views layouts responsive
514	*
515	* @since 1.9
516	* @since 1.11 added debounce
517	*/
518	
519	$( window ).on( 'resize', _.debounce(
520		function() {
521			$( '.js-wpv-layout-responsive' ).each( function() {
522				$( this ).css( 'width', '' );
523			})
524			.promise()
525			.done( function() {
526				$( document ).trigger( 'js_event_wpv_layout_responsive_resize_completed' );
527			});
528		},
529		wpv_pagination_local.resize_debounce_tolerance
530	));
531	
532	// ------------------------------------
533	// Init
534	// ------------------------------------
535	
536	self.init = function() {
537		self.render_frontend_datepicker();
538	};
539	
540	self.init();
541
542};
543
544WPViews.ViewSorting = function( $ ) {
545	
546	var self = this;
547	
548	/**
549	 * Get the sort data for a given View.
550	 *
551	 * @note If the current orderby option does not have an orderby_as option and does not match the stored option, 
552	 * we remove (we empty) that value so it gets sorted as a native, string value.
553	 *
554	 * @since 2.3.0
555	 */
556	self.get_sort_data = function( view_number, form ) {
557		var sort			= {},
558		parametric_data		= form.data( 'parametric' );
559		
560		sort['wpv_sort_orderby']	= parametric_data['sort']['orderby'];
561		sort['wpv_sort_order']		= parametric_data['sort']['order'];
562		sort['wpv_sort_orderby_as']	= parametric_data['sort']['orderby_as'];
563		sort['wpv_sort_orderby_second']	= parametric_data['sort']['orderby_second'];
564		sort['wpv_sort_order_second']	= parametric_data['sort']['order_second'];
565		
566		if ( form.find( '.js-wpv-sort-control-orderby' ).length > 0 ) {
567			var orderby_type = WPViews.view_frontend_utils.get_form_element_type( form.find( '.js-wpv-sort-control-orderby' ) );
568			switch ( orderby_type ) {
569				case 'select':
570					sort['wpv_sort_orderby'] = form.find( '.js-wpv-sort-control-orderby' ).val();
571					if ( form.find( '.js-wpv-sort-control-orderby option:selected' ).data( 'orderbyas' ) ) {
572						sort['wpv_sort_orderby_as'] = form.find( '.js-wpv-sort-control-orderby option:selected' ).data( 'orderbyas' );
573					} else if ( sort['wpv_sort_orderby'] != parametric_data['sort']['orderby'] ) {
574						sort['wpv_sort_orderby_as'] = '';
575					}
576					break;
577				case 'radio':
578					sort['wpv_sort_orderby'] = form.find( '.js-wpv-sort-control-orderby:checked' ).val();
579					if ( form.find( '.js-wpv-sort-control-orderby:checked' ).data( 'orderbyas' ) ) {
580						sort['wpv_sort_orderby_as'] = form.find( '.js-wpv-sort-control-orderby:checked' ).data( 'orderbyas' );
581					} else if ( sort['wpv_sort_orderby'] != parametric_data['sort']['orderby'] ) {
582						sort['wpv_sort_orderby_as'] = '';
583					}
584					break;
585				case 'text':
586				case 'hidden':
587					sort['wpv_sort_orderby'] = form.find( '.js-wpv-sort-control-orderby' ).val();
588					if ( form.find( '.js-wpv-sort-control-orderby' ).data( 'orderbyas' ) ) {
589						sort['wpv_sort_orderby_as'] = form.find( '.js-wpv-sort-control-orderby' ).data( 'orderbyas' );
590					} else if ( sort['wpv_sort_orderby'] != parametric_data['sort']['orderby'] ) {
591						sort['wpv_sort_orderby_as'] = '';
592					}
593					break;
594			}
595		}
596		
597		if ( form.find( '.js-wpv-sort-control-order' ).length > 0 ) {
598			var order_type = WPViews.view_frontend_utils.get_form_element_type( form.find( '.js-wpv-sort-control-order' ) );
599			switch ( order_type ) {
600				case 'select':
601					sort['wpv_sort_order'] = form.find( '.js-wpv-sort-control-order' ).val();
602					break;
603				case 'radio':
604					sort['wpv_sort_order'] = form.find( '.js-wpv-sort-control-order:checked' ).val();
605					break;
606				case 'text':
607				case 'hidden':
608					sort['wpv_sort_order'] =  form.find( '.js-wpv-sort-control-order' ).val();
609					break;
610			}
611		}
612		
613		return sort;
614	}
615	
616	/**
617	 * Sync the sorting controls used inside and outside of the View form.
618	 *
619	 * @since 2.3.0
620	 * @since 2.3.1 Split into set_sort_data_inside_form and set_sort_data_outside_form.
621	 */
622	self.set_sort_data = function( form, sort ) {
623		self.set_sort_data_inside_form( form, sort )
624			.set_sort_data_outside_form( form, sort );
625		return self;
626	};
627	
628	/**
629	 * Set the sort data for orderby controls as select dropdowns.
630	 *
631	 * @since 2.3.1
632	 */
633	self.set_sort_data_orderby_select = function( orderby_control, sort ) {
634		if ( orderby_control.find( 'option[value="' + sort['orderby'] + '"]' ).length == 0 ) {
635			orderby_control.append( $('<option>', {
636				value:	sort['orderby'],
637				text:	sort['orderby']
638			}));
639		}
640		orderby_control.val( sort['orderby'] );
641		if ( _.has( sort, 'orderby_as' ) ) {
642			orderby_control.find( 'option:selected' )
643				.data( 'orderbyas', sort['orderby_as'] )
644				.attr( 'data-orderbyas', sort['orderby_as'] );
645		}
646		return self;
647	};
648	
649	/**
650	 * Set the sort data for orderby controls as text or hidden input
650s.
651	 *
652	 * @since 2.3.1
653	 */
654	self.set_sort_data_orderby_text = function( orderby_control, sort ) {
655		orderby_control.val( sort['orderby'] );
656		if ( _.has( sort, 'orderby_as' ) ) {
657			orderby_control
658				.data( 'orderbyas', sort['orderby_as'] )
659				.attr( 'data-orderbyas', sort['orderby_as'] );
660		}
661		return self;
662	};
663	
664	/**
665	 * Set the sort data for orderby controls as radio inputs.
666	 *
667	 * @note Create a radio input if it does not exist one for the right orderby value.
668	 *
669	 * @since 2.3.1
670	 */
671	self.set_sort_data_orderby_radio = function( orderby_control, sort, form ) {
672		if ( orderby_control.filter( '[value="' + sort['orderby'] + '"]' ).length == 0 ) {
673			form.append( $('<input>', {
674				type:		'radio',
675				"class":	'js-wpv-sort-control-orderby',
676				name:		'wpv_sort_orderby',
677				value:		sort['orderby']
678			}));
679		}
680		form.find( '.js-wpv-sort-control-orderby[value="' +  sort['orderby'] + '"]' ).prop( 'checked', true );
681		if ( _.has( sort, 'orderby_as' ) ) {
682			form.find( '.js-wpv-sort-control-orderby:checked' )
683				.data( 'orderbyas', sort['orderby_as'] )
684				.attr( 'data-orderbyas', sort['orderby_as'] );
685		}
686		return self;
687	};
688	
689	/**
690	 * Set the sort data for orderby controls as radio inputs.
691	 *
692	 * @note Uncheck all radio inputs if it does not exist one for the right orderby value.
693	 *
694	 * @since 2.3.1
695	 */
696	self.maybe_set_sort_data_orderby_radio = function( orderby_control, sort ) {
697		if ( orderby_control.filter( '[value="' + sort['orderby'] + '"]' ).length == 0 ) {
698			orderby_control.prop( 'checked', false );
699		} else {
700			orderby_control.filter( '[value="' +  sort['orderby'] + '"]' ).prop( 'checked', true );
701			if ( _.has( sort, 'orderby_as' ) ) {
702				orderby_control.filter( ':checked' )
703					.data( 'orderbyas', sort['orderby_as'] )
704					.attr( 'data-orderbyas', sort['orderby_as'] );
705			}
706		}
707		return self;
708	};
709	
710	/**
711	 * Set the sort data for orderby controls as lists.
712	 *
713	 * @since 2.3.1
714	 */
715	self.set_sort_data_orderby_list = function( orderby_control, sort ) {
716		var orderby_control_to_set = orderby_control.find( '.js-wpv-sort-list-orderby[data-orderby="' + sort['orderby'] + '"]' );
717		if ( orderby_control_to_set.length == 0 ) {
718			
719		} else {
720			if ( ! orderby_control_to_set.closest( '.js-wpv-sort-list-item' ).hasClass( 'wpv-sort-list-current' ) ) {
721				orderby_control
722					.find( 'span.wpv-sort-list-current' )
723						.removeClass( 'wpv-sort-list-current' );
724				orderby_control
725					.find( '.js-wpv-sort-list-item' )
726						.css( {'display':'none'} );
727				orderby_control_to_set
728					.closest( '.js-wpv-sort-list-item' )
729						.addClass( 'wpv-sort-list-current' )
730						.css( {'display': 'block'} );
731				orderby_control
732					.find( '.js-wpv-sort-list' )
733						.prepend( orderby_control_to_set.closest( '.js-wpv-sort-list-item' ) );
734			}
735		}
736		return self;
737	};
738	
739	/**
740	 * Set the sort data for order controls as select dropdowns.
741	 *
742	 * @since 2.3.1
743	 */
744	self.set_sort_data_order_select = function( order_control, sort ) {
745		if ( order_control.find( 'option[value="' + sort['order'] + '"]' ).length == 0 ) {
746			order_control.append( $('<option>', {
747				value:	sort['order'],
748				text:	sort['order']
749			}));
750		}
751		order_control.val( sort['order'] );
752		if ( 
753			_.has( sort, 'orderby' ) 
754			&& typeof order_control.data('labels') !== 'undefined'
755		) {
756			// We are setting the order in a command that also sets the orderby, so we need to modify the order labels
757			var order_labels = order_control.data( 'labels' ),
758				order_labels_to_push = {},
759				orderby_to_check = sort.orderby.toLowerCase();
760			if ( _.has( order_labels, orderby_to_check ) ) {
761				order_labels_to_push = order_labels[ orderby_to_check ];
762			} else if ( _.has( order_labels, 'default' ) ) {
763				order_labels_to_push = order_labels[ 'default' ];
764			}
765			
766			if ( _.has( order_labels_to_push, 'asc' ) ) {
767				order_control.find( 'option[value="asc"]' ).html( order_labels_to_push.asc );
768			}
769			if ( _.has( order_labels_to_push, 'desc' ) ) {
770				order_control.find( 'option[value="desc"]' ).html( order_labels_to_push.desc );
771			}
772		}
773		return self;
774	};
775	
776	/**
777	 * Set the sort data for order controls as text or hidden input
777s.
778	 *
779	 * @since 2.3.1
780	 */
781	self.set_sort_data_order_text = function( order_control, sort ) {
782		order_control.val( sort['order'] );
783		return self;
784	};
785	
786	/**
787	 * Set the sort data for order controls as radio inputs.
788	 *
789	 * @note Create a radio input if it does not exist one for the right order value.
790	 *
791	 * @since 2.3.1
792	 */
793	self.set_sort_data_order_radio = function( order_control, sort, form ) {
794		if ( order_control.filter( '[value="' + sort['order'] + '"]' ).length == 0 ) {
795			form.append( $('<input>', {
796				type:		'radio',
797				"class":	'js-wpv-sort-control-order',
798				name:		'wpv_sort_order',
799				value:		sort['order']
800			}));
801		}
802		form.find( '.js-wpv-sort-control-order[value="' +  sort['order'] + '"]' ).prop( 'checked', true );
803		
804		if ( 
805			_.has( sort, 'orderby' ) 
806			&& typeof order_control.data('labels') !== 'undefined'
807		) {
808			// We are setting the order in a command that also sets the orderby, so we need to modify the order labels
809			var order_labels = order_control.data( 'labels' ),
810				order_labels_to_push = {},
811				orderby_to_check = sort.orderby.toLowerCase(),
812				label_to_update = null,
813				input_to_keep = null;
814			if ( _.has( order_labels, orderby_to_check ) ) {
815				order_labels_to_push = order_labels[ orderby_to_check ];
816			} else if ( _.has( order_labels, 'default' ) ) {
817				order_labels_to_push = order_labels[ 'default' ];
818			}
819			
820			if ( _.has( order_labels_to_push, 'asc' ) ) {
821				label_to_update = order_control.filter( '[value="asc"]' ).closest( 'label' );
822				input_to_keep = order_control.filter( '[value="asc"]' ).detach();
823				
824				label_to_update
825					.html( order_labels_to_push.asc )
826					.prepend( input_to_keep );
827			}
828			if ( _.has( order_labels_to_push, 'desc' ) ) {
829				label_to_update = order_control.filter( '[value="desc"]' ).closest( 'label' );
830				input_to_keep = order_control.filter( '[value="desc"]' ).detach();
831				
832				label_to_update
833					.html( order_labels_to_push.desc )
834					.prepend( input_to_keep );
835			}
836		}
837		return self;
838	};
839	
840	/**
841	 * Set the sort data for order controls as radio inputs.
842	 *
843	 * @note Uncheck all radio inputs if it does not exist one for the right order value.
844	 *
845	 * @since 2.3.1
846	 */
847	self.maybe_set_sort_data_order_radio = function( order_control, sort ) {
848		if ( order_control.filter( '[value="' + sort['order'] + '"]' ).length == 0 ) {
849			order_control.prop( 'checked', true );
850		} else {
851			order_control.filter( '[value="' +  sort['order'] + '"]' ).prop( 'checked', true );
852		}
853		return self;
854	};
855	
856	/**
857	 * Set the sort data for order controls as lists.
858	 *
859	 * @since 2.3.1
860	 */
861	self.set_sort_data_order_list = function( order_control, sort ) {
862		var order_control_to_set = order_control.find( '.js-wpv-sort-list-order[data-order="' + sort['order'] + '"]' );
863		if ( order_control_to_set.length == 0 ) {
864			
865		} else {
866			if ( ! order_control_to_set.closest( '.js-wpv-sort-list-item' ).hasClass( 'wpv-sort-list-current' ) ) {
867				order_control
868					.find( 'span.wpv-sort-list-current' )
869						.removeClass( 'wpv-sort-list-current' );
870				order_control
871					.find( '.js-wpv-sort-list-item' )
872						.css( {'display':'none'} );
873				order_control_to_set
874					.closest( '.js-wpv-sort-list-item' )
875						.addClass( 'wpv-sort-list-current' )
876						.css( {'display': 'block'} );
877				order_control
878					.find( '.js-wpv-sort-list' )
879						.prepend( order_control_to_set.closest( '.js-wpv-sort-list-item' ) );
880			}
881		}
882		if ( 
883			_.has( sort, 'orderby' ) 
884			&& typeof order_control.data('labels') !== 'undefined'
885		) {
886			// We are setting the order in a command that also sets the orderby, so we need to modify the order labels
887			var order_labels = order_control.data( 'labels' ),
888				order_labels_to_push = {},
889				orderby_to_check = sort.orderby.toLowerCase(),
890				width_update_needed = false;
891			if ( _.has( order_labels, orderby_to_check ) ) {
892				order_labels_to_push = order_labels[ orderby_to_check ];
893			} else if ( _.has( order_labels, 'default' ) ) {
894				order_labels_to_push = order_labels[ 'default' ];
895			}
896			
897			if ( _.has( order_labels_to_push, 'asc' ) ) {
898				order_control.find( '.js-wpv-sort-list-order[data-order="asc"] span' ).html( order_labels_to_push.asc );
899				width_update_needed = true;
900			}
901			if ( _.has( order_labels_to_push, 'desc' ) ) {
902				order_control.find( '.js-wpv-sort-list-order[data-order="desc"] span' ).html( order_labels_to_push.desc );
903				width_update_needed = true;
904			}
905			if ( width_update_needed ) {
906				self.adjust_sort_list_width( order_control );
907			}
908		}
909		return self;
910	};
911	
912	/**
913	 * Sync the sorting controls used inside of the View form.
914	 *
915	 * @since 2.3.1
916	 *
917	 * @note Setting "orderby_as" demands that "orderby" is also set.
918	 */
919	self.set_sort_data_inside_form = function( form, sort ) {
920		if ( _.has( sort, 'orderby' ) ) {
921			if ( form.find( '.js-wpv-sort-control-orderby' ).length > 0 ) {
922				var orderby_control = form.find( '.js-wpv-sort-control-orderby' ),
923					orderby_type = WPViews.view_frontend_utils.get_form_element_type( orderby_control );
924				switch ( orderby_type ) {
925					case 'select':
926						self.set_sort_data_orderby_select( orderby_control, sort );
927						break;
928					case 'text':
929					case 'hidden':
930						self.set_sort_data_orderby_text( orderby_control, sort );
931						break;
932					case 'radio':
933						self.set_sort_data_orderby_radio( orderby_control, sort, form );
934						break;
935				}
936			} else {
937				var orderby_attributes = {
938					type:		'hidden',
939					"class":	'js-wpv-sort-control-orderby',
940					name:		'wpv_sort_orderby',
941					value:		sort['orderby']
942				};
943				if ( _.has( sort, 'orderby_as' ) ) {
944					orderby_attributes['data-orderbyas'] = sort['orderby_as'];
945				}
946				$( '<input>' )
947					.attr( orderby_attributes )
948					.appendTo( form );
949			}
950			// We set this as a hidden input for forms that submit with page refresh.
951			if ( _.has( sort, 'orderby_as' ) ) {
952				if ( form.find( '.js-wpv-sort-control-orderby-as' ).length > 0 ) {
953					form.find( '.js-wpv-sort-control-orderby-as' ).remove();
954				}
955				$( '<input>' )
956					.attr({
957						type:		'hidden',
958						"class":	'js-wpv-sort-control-orderby-as',
959						name:		'wpv_sort_orderby_as',
960						value:		sort['orderby_as']
961					})
962					.appendTo( form );
963			}
964			if ( form.find( '.js-wpv-sort-list-orderby-dropdown' ).length > 0 ) {
965				var orderby_list_control = form.find( '.js-wpv-sort-list-orderby-dropdown' );
966				self.set_sort_data_orderby_list( orderby_list_control, sort );
967			}
968		}
969		if ( _.has( sort, 'order' ) ) {
970			if ( form.find( '.js-wpv-sort-control-order' ).length > 0 ) {
971				var order_control = form.find( '.js-wpv-sort-control-order' ),
972					order_type = WPViews.view_frontend_utils.get_form_element_type( order_control );
973				switch ( order_type ) {
974					case 'select':
975						self.set_sort_data_order_select( order_control, sort );
976						break;
977					case 'text':
978					case 'hidden':
979						self.set_sort_data_order_text( order_control, sort );
980						break;
981					case 'radio':
982						self.set_sort_data_order_radio( order_control, sort, form );
983						break;
984				}
985			} else {
986				$( '<input>' )
987					.attr({
988						type:		'hidden',
989						"class":	'js-wpv-sort-control-order',
990						name:		'wpv_sort_order',
991						value:		sort['order']
992					})
993					.appendTo( form );
994			}
995			if ( form.find( '.js-wpv-sort-list-order-dropdown' ).length > 0 ) {
996				var order_list_control = form.find( '.js-wpv-sort-list-order-dropdown' );
997				self.set_sort_data_order_list( order_list_control, sort );
998			}
999		}
1000		return self;
1001	}
1002	
1003	/**
1004	 * Sync the sorting controls used outside of the View form.
1005	 *
1006	 * @since 2.3.1
1007	 *
1008	 * @note Setting "orderby_as" demands that "orderby" is also set.
1009	 */
1010	self.set_sort_data_outside_form = function( form, sort ) {
1011		
1012		var view_number = form.data( 'viewnumber' );
1013		
1014		if ( _.has( sort, 'orderby' ) ) {
1015			var extra_orderby = $( '.js-wpv-sort-control-orderby[data-viewnumber="' + view_number + '"]:not(.js-wpv-filter-form .js-wpv-sort-control-orderby)' ),
1016				extra_orderby_list = $( '.js-wpv-sort-list-orderby-dropdown[data-viewnumber="' + view_number + '"]:not(.js-wpv-filter-form .js-wpv-sort-list-orderby-dropdown)' );
1017			if ( extra_orderby.length > 0 ) {
1018				var orderby_type = WPViews.view_frontend_utils.get_form_element_type( extra_orderby );
1019				switch ( orderby_type ) {
1020					case 'select':
1021						self.set_sort_data_orderby_select( extra_orderby, sort );
1022						break;
1023					case 'text':
1024					case 'hidden':
1025						self.set_sort_data_orderby_text( extra_orderby, sort );
1026						break;
1027					case 'radio':
1028						self.maybe_set_sort_data_orderby_radio( extra_orderby, sort );
1029						break;
1030				}
1031			}
1032			if ( extra_orderby_list.length > 0 ) {
1033				self.set_sort_data_orderby_list( extra_orderby_list, sort );
1034			}
1035		}
1036		
1037		if ( _.has( sort, 'order' ) ) {
1038			var extra_order = $( '.js-wpv-sort-control-order[data-viewnumber="' + view_number + '"]:not(.js-wpv-filter-form .js-wpv-sort-control-order)' ),
1039				extra_order_list = $( '.js-wpv-sort-list-order-dropdown[data-viewnumber="' + view_number + '"]:not(.js-wpv-filter-form .js-wpv-sort-list-order-dropdown)' );
1040			if ( extra_order.length > 0 ) {
1041				var order_type = WPViews.view_frontend_utils.get_form_element_type( extra_order );
1042				switch ( order_type ) {
1043					case 'select':
1044						self.set_sort_data_order_select( extra_order, sort );
1045						break;
1046					case 'text':
1047					case 'hidden':
1048						self.set_sort_data_order_text( extra_order, sort );
1049						break;
1050					case 'radio':
1051						self.maybe_set_sort_data_order_radio( extra_order, sort );
1052						break;
1053				}
1054			}
1055			if ( extra_order_list.length > 0 ) {
1056				self.set_sort_data_order_list( extra_order_list, sort );
1057			}
1058		}
1059		
1060		return self;
1061		
1062	};
1063	
1064	// ------------------------------------
1065	// Sorting links - not implemented yet
1066	// ------------------------------------
1067	
1068	$( document ).on( 'click', '.js-wpv-sort-trigger', function( e ) {
1069		e.preventDefault();
1070		var thiz		= $( this ),
1071		view_number		= thiz.data( 'viewnumber' ),
1072		form			= $( '.js-wpv-filter-form-' + view_number ),
1073		sort			= {
1074							'orderby':		( typeof thiz.data( 'orderby' ) != 'undefined' ) ? thiz.data( 'orderby' ) : '',
1075							'order':		( typeof thiz.data( 'order' ) != 'undefined' ) ? thiz.data( 'order' ) : '',
1076							'orderby_as':	( typeof thiz.data( 'orderbyas' ) != 'undefined' ) ? thiz.data( 'orderbyas' ) : '',
1077		},
1078		form_each;
1079		form.each( function() {
1080			form_each = $( this );
1081			self.set_sort_data( form_each, sort );
1082			WPViews.view_frontend_utils.set_extra_url_query_parameters_by_form( form_each );
1083		});
1084		if ( 
1085			thiz.hasClass( 'js-wpv-column-header-click' ) 
1086			|| (
1087				! form.hasClass( 'js-wpv-ajax-results-enabled' ) 
1088				&& ! form.hasClass( 'js-wpv-ajax-results-submit-enabled' )
1089			)
1090		) {
1091			// Backwards compatibility: table sorting does reload the page for sorting
1092			// Also, submit the form for a page reload when the form is not set to load results using AJAX
1093			form.submit();
1094		} else {
1095			// Elsewhere, trigger a parametric search change, and make sure AJAX is used where due
1096			var data_for_events = {
1097				view_unique_id:			view_number,
1098				form:					form,
1099				force_results_update:	form.hasClass( 'js-wpv-ajax-results-submit-enabled' )
1100			};
1101			
1102			data_for_events = WPViews.view_parametric_search.extend_wpv_parametric_search_triggered_data( data_for_events );
1103			
1104			$( document ).trigger( 'js_event_wpv_parametric_search_triggered', [ data_for_events ] );
1105		}
1106	});
1107	
1108	// ------------------------------------
1109	// Sorting controls
1110	// ------------------------------------
1111	
1112	$( document ).on( 'change', 'select.js-wpv-sort-control-orderby', function() {
1113		
1114		var thiz		= $( this ),
1115		thiz_selected	= thiz.find( ':selected' ),
1116		sort			= {},
1117		view_number		= thiz.data( 'viewnumber' ),
1118		form			= $( '.js-wpv-filter-form-' + view_number ),
1119		data_for_events = {
1120			view_unique_id:	view_number,
1121			form:			form
1122		};
1123		
1124		sort[ 'orderby' ] = thiz.val();
1125		if ( thiz_selected.data( 'orderbyas' ) !== undefined ) {
1126			sort[ 'orderby_as' ] = thiz_selected.data( 'orderbyas' );
1127		}
1128		if ( 
1129			thiz_selected.data( 'forceorder' ) !== undefined 
1130			&& thiz_selected.data( 'forceorder' ) !== ''
1131		) {
1132			sort[ 'order' ] = thiz_selected.data( 'forceorder' );
1133		}
1134		
1135		self.set_sort_data( form, sort );
1136		
1137		wpv_stop_rollover[ view_number ] = true;
1138		
1139		data_for_events = WPViews.view_parametric_search.extend_wpv_parametric_search_triggered_data( data_for_events );
1140		
1141		$( document ).trigger( 'js_event_wpv_parametric_search_triggered', [ data_for_events ] );
1142		
1143	});
1144	
1145	$( document ).on( 'change', 'input.js-wpv-sort-control-orderby', function() {
1146		
1147		var thiz		= $( this ),
1148		sort			= {},
1149		view_number		= thiz.data( 'viewnumber' ),
1150		sort_control	= $( '.js-wpv-sort-control-orderby[data-viewnumber="' + view_number + '"]:checked' ),
1151		form			= $( '.js-wpv-filter-form-' + view_number ),
1152		data_for_events = {
1153			view_unique_id:	view_number,
1154			form:			form
1155		};
1156		
1157		sort[ 'orderby' ] = sort_control.val();
1158		if ( sort_control.data( 'orderbyas' ) !== undefined ) {
1159			sort[ 'orderby_as' ] = sort_control.data( 'orderbyas' );
1160		}
1161		if ( 
1162			sort_control.data( 'forceorder' ) !== undefined 
1163			&& sort_control.data( 'forceorder' ) !== '' 
1164		) {
1165			sort[ 'order' ] = sort_control.data( 'forceorder' );
1166		}
1167		
1168		self.set_sort_data( form, sort );
1169		
1170		wpv_stop_rollover[ view_number ] = true;
1171		
1172		data_for_events = WPViews.view_parametric_search.extend_wpv_parametric_search_triggered_data( data_for_events );
1173		
1174		$( document ).trigger( 'js_event_wpv_parametric_search_triggered', [ data_for_events ] );
1175		
1176	});
1177	
1178	$( document ).on( 'click', '.js-wpv-sort-list-orderby', function( e ) {
1179		e.preventDefault();
1180		var orderby_link = $( this ),
1181			orderby = orderby_link.data( 'orderby' ),
1182			orderby_as = orderby_link.data( 'orderbyas' ),
1183			orderby_order = orderby_link.data( 'forceorder' ),
1184			orderby_list = orderby_link.closest( '.wpv-sort-list' ),
1185			orderby_list_item = orderby_link.closest( 'span.js-wpv-sort-list-item' ),
1186			view_number = orderby_link.data( 'viewnumber' ),
1187			form = $( '.js-wpv-filter-form-' + view_number ),
1188			sort = {
1189				'orderby':		orderby,
1190				'orderby_as':	orderby_as
1191			},
1192			data_for_events = {
1193				view_unique_id:	view_number,
1194				form:			form
1195			};
1196		
1197		
1198		if ( orderby_list_item.hasClass( 'wpv-sort-list-current' ) ) {
1199			return;
1200		}
1201		
1202		orderby_list
1203			.find( 'span.wpv-sort-list-current' )
1204				.removeClass( 'wpv-sort-list-current' );
1205		orderby_list
1206			.find( '.js-wpv-sort-list-item' )
1207				.css( {'display':'none'} );
1208		orderby_list_item
1209			.addClass( 'wpv-sort-list-current' )
1210			.css( {'display': 'block'} );
1211		orderby_list.prepend( orderby_list_item );
1212		
1213		if ( orderby_order !== '' ) {
1214			sort[ 'order' ] = orderby_order;
1215		}
1216		
1217		self.set_sort_data( form, sort );
1218		
1219		wpv_stop_rollover[ view_number ] = true;
1220		
1221		data_for_events = WPViews.view_parametric_search.extend_wpv_parametric_search_triggered_data( data_for_events );
1222		
1223		$( document ).trigger( 'js_event_wpv_parametric_search_triggered', [ data_for_events ] );
1224		
1225	});
1226	
1227	$( document ).on( 'change', 'select.js-wpv-sort-control-order', function() {
1228		
1229		var thiz		= $( this ),
1230		sort			= {},
1231		view_number		= thiz.data( 'viewnumber' ),
1232		form			= $( '.js-wpv-filter-form-' + view_number ),
1233		data_for_events = {
1234			view_unique_id:	view_number,
1235			form:			form
1236		};
1237		
1238		sort[ 'order' ] = thiz.val();
1239		
1240		self.set_sort_data( form, sort );
1241		
1242		wpv_stop_rollover[ view_number ] = true;
1243		
1244		data_for_events = WPViews.view_parametric_search.extend_wpv_parametric_search_triggered_data( data_for_events );
1245		
1246		$( document ).trigger( 'js_event_wpv_parametric_search_triggered', [ data_for_events ] );
1247		
1248	});
1249	
1250	$( document ).on( 'change', 'input.js-wpv-sort-control-order', function() {
1251		
1252		var thiz		= $( this ),
1253		sort			= {},
1254		view_number		= thiz.data( 'viewnumber' ),
1255		sort_control	= $( '.js-wpv-sort-control-order[data-viewnumber="' + view_number + '"]:checked' ),
1256		form			= $( '.js-wpv-filter-form-' + view_number ),
1257		data_for_events = {
1258			view_unique_id:	view_number,
1259			form:			form
1260		};
1261		
1262		sort[ 'order' ] = sort_control.val();
1263		
1264		self.set_sort_data( form, sort );
1265		
1266		wpv_stop_rollover[ view_number ] = true;
1267		
1268		data_for_events = WPViews.view_parametric_search.extend_wpv_parametric_search_triggered_data( data_for_events );
1269		
1270		$( document ).trigger( 'js_event_wpv_parametric_search_triggered', [ data_for_events ] );
1271		
1272	});
1273	
1274	$( document ).on( 'click', '.js-wpv-sort-list-order', function( e ) {
1275		e.preventDefault();
1276		var order_link = $( this ),
1277			order = order_link.data( 'order' ),
1278			order_list = order_link.closest( '.wpv-sort-list' ),
1279			order_list_item = order_link.closest( 'span.js-wpv-sort-list-item' ),
1280			view_number = order_link.data( 'viewnumber' ),
1281			form = $( '.js-wpv-filter-form-' + view_number ),
1282			sort = {
1283				'order': order
1284			},
1285			data_for_events = {
1286				view_unique_id:	view_number,
1287				form:			form
1288			};
1289		
1290		
1291		if ( order_list_item.hasClass( 'wpv-sort-list-current' ) ) {
1292			return;
1293		}
1294		
1295		order_list
1296			.find( 'span.wpv-sort-list-current' )
1297				.removeClass( 'wpv-sort-list-current' );
1298		order_list
1299			.find( '.js-wpv-sort-list-item' )
1300				.css( {'display':'none'} );
1301		order_list_item
1302			.addClass( 'wpv-sort-list-current' )
1303			.css( {'display': 'block'} );
1304		order_list.prepend( order_list_item );
1305		
1306		self.set_sort_data( form, sort );
1307		
1308		wpv_stop_rollover[ view_number ] = true;
1309		
1310		data_for_events = WPViews.view_parametric_search.extend_wpv_parametric_search_triggered_data( data_for_events );
1311		
1312		$( document ).trigger( 'js_event_wpv_parametric_search_triggered', [ data_for_events ] );
1313		
1314	});
1315	
1316	$( document ).on( 'mouseenter', '.js-wpv-sort-list-dropdown', function() {
1317		var orderby_list = $( this );
1318		orderby_list
1319			.find( '.js-wpv-sort-list-item' )
1320				.css( {'display': 'block'} );
1321	});
1322	
1323	$( document ).on( 'mouseleave', '.js-wpv-sort-list-dropdown', function() {
1324		var orderby_list = $( this );
1325		orderby_list
1326			.find( '.js-wpv-sort-list-item:not(.wpv-sort-list-current)' )
1327				.css( {'display': 'none'} );
1328	});
1329	
1330	// @todo calculate inital width and height of the container and also maybe re-calculate height on selection
1331	
1332	self.init_sort_list_width = function( selector ) {
1333		/*
1334		selector
1335			.find( '.js-wpv-sort-list-dropdown' )
1336				.each( function() {
1337					var sort_list = $( this ),
1338						sort_list_width = 0,
1339						sort_list_items = sort_list.find( '.js-wpv-sort-list-item' ),
1340						sort_list_anchors = sort_list.find( '.wpv-sort-list-anchor' );
1341						sort_list_anchors.each( function() {
1342							var item_width = WPViews.view_frontend_utils.get_hidden_item_width( $( this ) );
1343							if ( item_width > sort_list_width ) {
1344								sort_list_width = item_width;
1345							}
1346						});
1347						sort_list.css( { 'width': sort_list_width + 'em' } );
1348						sort_list_items.css( { 'width': sort_list_width + 'em' } );
1349				});
1350		*/
1351	};
1352	
1353	/**
1354	 * Adjust the sort list width to span at least its length in "em" units.
1355	 *
1356	 * @note When the length is less than 10 units, add an extra one for the toggle icon.
1357	 *
1358	 * @since 2.3.1
1359	 */
1360	self.adjust_sort_list_width = function( selector ) {
1361		var sort_list = selector,
1362			sort_list_width = 0,
1363			sort_list_items = sort_list.find( '.js-wpv-sort-list-item' ),
1364			sort_list_anchors = sort_list.find( '.wpv-sort-list-anchor span' );
1365		
1366		sort_list_anchors.each( function() {
1367			var item_width = $( this ).text().length;
1368			if ( item_width > sort_list_width ) {
1369				sort_list_width = item_width;
1370			}
1371		});
1372		sort_list_width = ( sort_list_width < 10 ) ? sort_list_width + 1 : sort_list_width;
1373		sort_list.css( { 'width': sort_list_width + 'em' } );
1374		sort_list_items.css( { 'width': sort_list_width + 'em' } );
1375	};
1376	
1377	/**
1378	 * Initialize sorting data for special cass:
1379	 * - When the sorting controls are of type 'list'.
1380	 * - When the sorting controls are of type 'dropdown' or 'radio', but are located outside of their related form.
1381	 * In those cases, there are no real sorting control elements inside the form, so we need to manually add them.
1382	 *
1383	 * @param selector The DOM object where this should be run, helps to narrow down on AJAX related operations.
1384	 *
1385	 * @since 2.3.0
1386	 *
1387	 * @todo Check whether we need to initialize the order coming from "forceorder" attributes in orderby controlos.
1388	 */
1389	self.maybe_init_sort_data = function( selector ) {
1390		
1391		// Init sort data for sort list controls, as they do not add proper form input elements
1392		selector.find( '.js-wpv-sort-list-dropdown' ).each( function() {
1393			var sorting_list = $( this ),
1394				sorting_list_type = sorting_list.hasClass( 'wpv-sort-list-orderby-dropdown' ) ? 'orderby' : 'order';
1395			
1396			switch ( sorting_list_type ) {
1397				case 'orderby':
1398					var sorting_current = sorting_list.find( '.wpv-sort-list-current .js-wpv-sort-list-orderby' ),
1399						sorting_viewnumber = sorting_current.data( 'viewnumber' ),
1400						sorting_form = $( '.js-wpv-filter-form-' + sorting_viewnumber ),
1401						sorting_data = {
1402							orderby: sorting_current.data( 'orderby' ),
1403							orderby_as: sorting_current.data( 'orderbyas' )
1404						};
1405						
1406						self.set_sort_data( sorting_form, sorting_data );
1407					break;
1408				case 'order':
1409					var sorting_current = sorting_list.find( '.wpv-sort-list-current .js-wpv-sort-list-order' ),
1410						sorting_viewnumber = sorting_current.data( 'viewnumber' ),
1411						sorting_form = $( '.js-wpv-filter-form-' + sorting_viewnumber ),
1412						sorting_data = {
1413							order: sorting_current.data( 'order' ),
1414						};
1415						
1416						self.set_sort_data( sorting_form, sorting_data );
1417					break;
1418			}
1419		});
1420		
1421		// Init sort data for dropdowns or radios that are rendered outside their proper form
1422		selector.find( 'select.js-wpv-sort-control-orderby' ).each( function() {
1423			var sorting_control = $( this );
1424			if ( sorting_control.closest( '.js-wpv-filter-form' ).length == 0 ) {
1425				var sorting_viewnumber = sorting_control.data( 'viewnumber' ),
1426					sorting_form = $( '.js-wpv-filter-form-' + sorting_viewnumber ),
1427					sorting_data = {
1428						orderby: sorting_control.val()
1429					};
1430				
1431				if ( sorting_control.find( ':selected' ).data( 'orderbyas' ) !== undefined ) {
1432					sorting_data[ 'orderby_as' ] = sorting_control.find( ':selected' ).data( 'orderbyas' );
1433				}
1434				
1435				self.set_sort_data( sorting_form, sorting_data );
1436			}
1437		});
1438		selector.find( 'select.js-wpv-sort-control-order' ).each( function() {
1439			var sorting_control = $( this );
1440			if ( sorting_control.closest( '.js-wpv-filter-form' ).length == 0 ) {
1441				var sorting_viewnumber = sorting_control.data( 'viewnumber' ),
1442					sorting_form = $( '.js-wpv-filter-form-' + sorting_viewnumber ),
1443					sorting_data = {
1444						order: sorting_control.val()
1445					};
1446				
1447				self.set_sort_data( sorting_form, sorting_data );
1448			}
1449		});
1450		selector.find( 'input.js-wpv-sort-control-orderby:checked' ).each( function() {
1451			var sorting_control = $( this );
1452			if ( sorting_control.closest( '.js-wpv-filter-form' ).length == 0 ) {
1453				var sorting_viewnumber = sorting_control.data( 'viewnumber' ),
1454					sorting_form = $( '.js-wpv-filter-form-' + sorting_viewnumber ),
1455					sorting_data = {
1456						orderby: sorting_control.val()
1457					};
1458				
1459				if ( sorting_control.data( 'orderbyas' ) !== undefined ) {
1460					sorting_data[ 'orderby_as' ] = sorting_control.data( 'orderbyas' );
1461				}
1462				
1463				self.set_sort_data( sorting_form, sorting_data );
1464			}
1465		});
1466		selector.find( 'input.js-wpv-sort-control-order:checked' ).each( function() {
1467			var sorting_control = $( this );
1468			if ( sorting_control.closest( '.js-wpv-filter-form' ).length == 0 ) {
1469				var sorting_viewnumber = sorting_control.data( 'viewnumber' ),
1470					sorting_form = $( '.js-wpv-filter-form-' + sorting_viewnumber ),
1471					sorting_data = {
1472						order: sorting_control.val()
1473					};
1474				
1475				self.set_sort_data( sorting_form, sorting_data );
1476			}
1477		});
1478		
1479	};
1480	
1481	$( document ).on( 'js_event_wpv_pagination_completed', function( event, data ) {
1482		//self.init_sort_list_width( data.layout );
1483		self.maybe_init_sort_data( data.layout );
1484	});
1485	
1486	$( document ).on( 'js_event_wpv_parametric_search_form_updated', function( event, data ) {
1487		//self.init_sort_list_width( data.view_changed_form );
1488		self.maybe_init_sort_data( data.view_changed_form );
1489	});
1490	
1491	$( document ).on( 'js_event_wpv_parametric_search_results_updated', function( event, data ) {
1492		//self.init_sort_list_width( data.layout );
1493		self.maybe_init_sort_data( data.layout );
1494	});
1495	
1496	// ------------------------------------
1497	// Init
1498	// ------------------------------------
1499	
1500	self.init = function() {
1501		//self.init_sort_list_width( $( 'body' ) );
1502		self.maybe_init_sort_data( $( 'body' ) );
1503	};
1504	
1505	self.init();
1506	
1507};
1508
1509WPViews.ViewPagination = function( $ ) {
1510	
1511	// ------------------------------------
1512	// Constants and variables
1513	// ------------------------------------
1514	
1515	var self = this;
1516	
1517	self.rollover_running = [];
1518	self.rollover_stopped = [];
1519    self.rollover_paused = [];
1520	
1521	self.init_rollover_timing_fired = false;
1522	
1523	self.pagination_queue = {};
1524	
1525	self.pagination_effects				= {};
1526	self.pagination_effects_conditions	= {};
1527	self.pagination_effects_spinner		= {};
1528	self.paged_views					= {};
1529	self.paged_views_initial_page		= {};
1530	
1531	self.last_paginated_view				= [];
1532	self.paginated_history_reach			= 0;
1533	self.add_paginated_history				= true;
1534	self.pagination_effect_state_push		= [ 'fade', 'slidev', 'slideh' ];
1535	self.pagination_effect_state_replace	= [];
1536	self.pagination_effect_state_keep		= [ 'infinite' ];
1537	
1538	self.init_scrolling_event_fired = false;
1539		
1540	self.slide_data_defaults = { 
1541		view_number:		'',
1542		page:				0,
1543		max_pages:			0,
1544		speed:				500,
1545		next:				true,
1546		effect:				'fade',
1547		response:			null,
1548		wpvPaginatorFilter: null,
1549		wpvPaginatorLayout: null,
1550		responseFilter:		null,
1551		responseView:		null,
1552		callback_next_func:	WPViews.view_frontend_utils.just_return
1553	};
1554	
1555	self.pagination_doing_ajax = [];
1556	
1557	// ------------------------------------
1558	// Methods
1559	// ------------------------------------
1560	
1561	/**
1562	* add_view_parameters
1563	*
1564	* Add several information to the data used to get pagination pages.
1565	* For example, add column sorting data, parametric search data and parent View data.
1566	*
1567	* @since 1.9
1568	* @since 2.1	Deprecated
1569	*/
1570	
1571	self.add_view_parameters = function( data, page, view_number ) {
1572		var this_form			= $( 'form.js-wpv-filter-form-' + view_number ),
1573		this_prelements			= this_form.find( '.js-wpv-post-relationship-update' ),
1574		this_form_environment	= this_form.data( 'environment' );
1575		
1576		data['action']				= 'wpv_get_page';
1577		data['page']				= page;
1578		data['view_number']			= view_number;
1579		data['wpv_sort_orderby']	= ( typeof this_form.data( 'orderby' ) != 'undefined' ) ? this_form.data( 'orderby' ) : '';
1580		data['wpv_sort_order']		= ( typeof this_form.data( 'order' ) != 'undefined' ) ? this_form.data( 'order' ) : '';
1581		data['wpv_sort_orderby_as']	= ( typeof this_form.data( 'orderbyas' ) != 'undefined' ) ? this_form.data( 'orderbyas' ) : '';
1582		data['wpv_sort_orderby_second']	= ( typeof this_form.data( 'orderbysecond' ) != 'undefined' ) ? this_form.data( 'orderbysecond' ) : '';
1583		data['wpv_sort_order_second']	= ( typeof this_form.data( 'ordersecond' ) != 'undefined' ) ? this_form.data( 'ordersecond' ) : '';
1584		data['wpv_view_widget_id']	= this_form.data( 'viewwidgetid' );
1585		data['view_hash']			= this_form.data( 'viewhash' );
1586		data['dps_pr']				= {};
1587		data['dps_general']			= {};
1588		
1589		if ( this_form_environment.current_post_id > 0 ) {
1590			data['wpv_aux_current_post_id'] = this_form_environment.current_post_id;
1591		}
1592		if ( this_form_environment.parent_post_id > 0 ) {
1593			data['wpv_aux_parent_post_id'] = this_form_environment.parent_post_id;
1594		}
1595		if ( this_form_environment.parent_term_id > 0 ) {
1596			data['wpv_aux_parent_term_id'] = this_form_environment.parent_term_id;
1597		}
1598		if ( this_form_environment.parent_user_id > 0 ) {
1599			data['wpv_aux_parent_user_id'] = this_form_environment.parent_user_id;
1600		}
1601		
1602		if ( this_prelements.length ) {
1603			data['dps_pr'] = this_prelements.serializeArray();
1604		}
1605		if ( this_form.hasClass( 'js-wpv-dps-enabled' ) || this_form.hasClass( 'js-wpv-ajax-results-enabled' ) ) {
1606			data['dps_general'] = this_form.find( '.js-wpv-filter-trigger, .js-wpv-filter-trigger-delayed' ).serializeArray();
1607		}
1608		
1609		return data;
1610	};
1611	
1612	/**
1613	* pagination_preload_pages
1614	*
1615	* Preload pages to a reach.
1616	*
1617	* @param object preload_data
1618	*
1619	* @since 1.9
1620	*/
1621	
1622	self.pagination_preload_pages = function( preload_data ) {
1623		var page = parseInt( preload_data.page, 10 ),
1624		max_pages = parseInt( preload_data.max_pages, 10 ),
1625		max_reach = parseInt( preload_data.max_reach, 10 );
1626		
1627		if ( max_reach > max_pages ) {
1628			max_reach = max_pages;
1629		}
1630		
1631		if ( preload_data.preload_pages == 'enabled' ) {
1632			var reach = 1;
1633			while ( reach < max_reach ) {
1634				self.pagination_preload_next_page( preload_data.view_number, page, max_pages, reach );
1635				self.pagination_preload_previous_page( preload_data.view_number, page, max_pages, reach );
1636				reach++;
1637			}
1638		}
1639		if ( preload_data.cache_pages == 'enabled' ) {
1640			self.pagination_cache_current_page( preload_data.view_number, page );
1641		}
1642	};
1643	
1644	/**
1645	* pagination_cache_current_page
1646	*
1647	* Cache current page.
1648	*
1649	* @param string	view_number
1650	* @param int	page
1651	*
1652	* @since 1.9
1653	*/
1654	
1655	self.pagination_cache_current_page = function( view_number, page ) {
1656		window.wpvCachedPages[ view_number ] = window.wpvCachedPages[ view_number ] || [];
1657		var current_page_permalink,
1658		content;
1659		icl_lang = ( typeof icl_lang == 'undefined' ) ? false : icl_lang;
1660		if ( ! window.wpvCachedPages[view_number].hasOwnProperty( page ) ) {
1661			WPViews.view_frontend_utils.get_updated_query_results( view_number, page, $( 'form.js-wpv-filter-form-' + view_number ), 'full' )
1662				.done( function( response ) {
1663					if ( response.success ) {
1664						window.wpvCachedPages[view_number][page] = response.data.full;
1665						content = $( response.data.full ).find( 'img' );
1666						content.each( function() {
1667							window.wpvCachedImages.push( this.src );
1668						});
1669					}
1670				});
1671		}
1672	};
1673	
1674	/**
1675	* pagination_preload_next_page
1676	*
1677	* Load the next page, or the next one counting "reach" pages.
1678	*
1679	* @param string	view_number
1680	* @param int	page
1681	* @param int	max_pages
1682	* @param int	reach
1683	*
1684	* @since 1.9
1685	*/
1686	
1687	self.pagination_preload_next_page = function( view_number, page, max_pages, reach ) {
1688		window.wpvCachedPages[ view_number ] = window.wpvCachedPages[ view_number ] || [];
1689		var next_page = page + reach,
1690		content,
1691		current_page_permalink;
1692		icl_lang = ( typeof icl_lang == 'undefined' ) ? false : icl_lang;
1693		if ( ! window.wpvCachedPages[view_number].hasOwnProperty( next_page ) ) {
1694			if ( ( next_page - 1 ) < max_pages ) {
1695				WPViews.view_frontend_utils.get_updated_query_results( view_number, next_page, $( 'form.js-wpv-filter-form-' + view_number ), 'full' )
1696					.done( function( response ) {
1697						if ( response.success ) {
1698							window.wpvCachedPages[view_number][next_page] = response.data.full;
1699							content = $( response.data.full ).find( 'img' );
1700							content.each( function() {
1701								window.wpvCachedImages.push( this.src );
1702							});
1703						}
1704					});
1705			}
1706		}
1707	};
1708	
1709	/**
1710	* pagination_preload_previous_page
1711	*
1712	* Load the previous page, or the previous one counting "reach" pages.
1713	*
1714	* @param string	view_number
1715	* @param int	page
1716	* @param int	max_pages
1717	* @param int	reach
1718	*
1719	* @since 1.9
1720	*/
1721	
1722	self.pagination_preload_previous_page = function(view_number, page, max_pages, reach) {
1723		window.wpvCachedPages[ view_number ] = window.wpvCachedPages[ view_number ] || [];
1724		var previous_page = page - reach,
1725		current_page_permalink,
1726		content;
1727		icl_lang = ( typeof icl_lang == 'undefined' ) ? false : icl_lang;
1728		if ( ! window.wpvCachedPages[view_number].hasOwnProperty( previous_page ) ) {
1729			// LOAD PREVIOUS
1730			if ( ( previous_page + 1 ) > 1 ) {
1731				WPViews.view_frontend_utils.get_updated_query_results( view_number, previous_page, $( 'form.js-wpv-filter-form-' + view_number ), 'full' )
1732					.done( function( response ) {
1733						if ( response.success ) {
1734							window.wpvCachedPages[view_number][previous_page] = response.data.full;
1735							content = $( response.data.full ).find( 'img' );
1736							content.each( function() {
1737								window.wpvCachedImages.push( this.src );
1738							});
1739						}
1740					});
1741			} else if ( (previous_page + 1 ) === 1 ) { // LOAD LAST PAGE IF ON FIRST PAGE
1742				WPViews.view_frontend_utils.get_updated_query_results( view_number, max_pages, $( 'form.js-wpv-filter-form-' + view_number ), 'full' )
1743					.done( function( response ) {
1744						if ( response.success ) {
1745							window.wpvCachedPages[view_number][max_pages] = response.data.full;
1746							window.wpvCachedPages[view_number][0] = response.data.full;
1747							content = $( response.data.full ).find( 'img' );
1748							content.each( function() {
1749								window.wpvCachedImages.push( this.src );
1750							});
1751						}
1752					});
1753			}
1754		}
1755	};
1756	
1757	/**
1758	* trigger_pagination
1759	*
1760	* Manage the View pagination after a control has been inited
1761	*
1762	* @param string	view_number
1763	* @param int	page
1764	*
1765	* @since 1.9
1766	*/
1767	
1768	self.trigger_pagination = function( view_number, page ) {
1769		if ( ! window.wpvPaginationAnimationFinished.hasOwnProperty( view_number ) ) {
1770			window.wpvPaginationAnimationFinished[ view_number ] = false;
1771		} else if ( window.wpvPaginationAnimationFinished[ view_number ] !== true ) {
1772			if ( ! window.wpvPaginationQueue.hasOwnProperty( view_number ) ) {
1773				window.wpvPaginationQueue[view_number] = [];
1774			}
1775			window.wpvPaginationQueue[ view_number ].push( arguments );
1776			return;
1777		}
1778		
1779		window.wpvPaginationAnimationFinished[ view_number ] = false;
1780		
1781		var data = {},
1782		wpvPaginatorLayout = $( '#wpv-view-layout-' + view_number ),
1783		wpvPaginatorFilter = $( 'form[name="wpv-filter-' + view_number + '"]' ),
1784		speed = 500,
1785		next = true,
1786		paged_view_data = self.get_paged_view( view_number ),
1787		max_reach = parseInt( paged_view_data.preload_reach ) + 1,
1788		callback_next_func = WPViews.view_frontend_utils.just_return,
1789		data_for_get_page,
1790		img;
1791		
1792		// Not using AJAX pagination
1793		// For WPAs we just need to adjust the form target and we are done :-)
1794		if ( 
1795			paged_view_data.type == 'disabled' 
1796			|| paged_view_data.type == 'paged' 
1797		) {
1798
1799			switch ( paged_view_data.query ) {
1800				case 'archive':
1801					current_page_permalink = paged_view_data[ 'base_permalink' ].replace( 'WPV_PAGE_NUM', page );
1802					window.location.replace( current_page_permalink );
1803					break;
1804				default:
1805					WPViews.view_frontend_utils.set_extra_url_query_parameters_by_form( wpvPaginatorFilter );
1806					// Adjust the wpv_paged hidden input to the page that we want to show
1807					if ( $( 'input[name="wpv_paged"]' ).length > 0 ) {
1808						$( 'input[name="wpv_paged"]' ).attr( 'value', page );
1809					} else {
1810						$( '<input>')
1811							.attr({
1812								type: 'hidden',
1813								name: 'wpv_paged',
1814								value: page
1815							})
1816							.appendTo( wpvPaginatorFilter );
1817					}
1818					wpvPaginatorFilter[0].submit();
1819					break;
1820			}
1821			return;
1822		}
1823		
1824		// Using AJAX pagination
1825		
1826		if ( paged_view_data.effect in self.pagination_effects_conditions ) {
1827			if ( ! self.pagination_effects_conditions[ paged_view_data.effect ]( paged_view_data, page ) ) {
1828				window.wpvPaginationAnimationFinished[ view_number ] = true;
1829				return;
1830			}
1831		}
1832		
1833		window.wpvPaginationAjaxLoaded[view_number] = false;
1834		window.wpvCachedPages[ view_number ] = window.wpvCachedPages[view_number] || [];
1835		
1836		if ( this.historyP.hasOwnProperty( view_number ) ) {
1837			next = ( this.historyP[ view_number ] < page ) ? true : false;
1838		}
1839		
1840		if ( paged_view_data.callback_next !== '' ) {
1841			callback_next_func = window[ paged_view_data.callback_next ];
1842			if ( typeof callback_next_func !== "function" ) {
1843				callback_next_func = WPViews.view_frontend_utils.just_return;
1844			}
1845		}
1846		
1847		data_for_get_page = { 
1848			view_number:		view_number,
1849			page:				page,
1850			max_pages:			parseInt( paged_view_data.max_pages, 10 ),
1851			speed:				parseFloat( paged_view_data.duration ),
1852			next:				next,
1853			effect:				paged_view_data.effect,
1854			wpvPaginatorFilter: wpvPaginatorFilter,
1855			wpvPaginatorLayout: wpvPaginatorLayout,
1856			responseView:		null,
1857			callback_next_func:	callback_next_func
1858		};
1859		
1860		if ( 
1861			window.wpvCachedPages[ view_number ].hasOwnProperty( page ) 
1862		) {
1863			data_for_get_page.response = window.wpvCachedPages[ view_number ][ page ];
1864			self.prepare_slide( data_for_get_page );
1865		} else {
1866			// Set loading class
1867			if ( paged_view_data.spinner !== 'disabled' ) {
1868				if ( paged_view_data.effect in self.pagination_effects_spinner ) {
1869					self.pagination_effects_spinner[ paged_view_data.effect ]( view_number, wpvPaginatorLayout );
1870				} else {
1871					self.pagination_effects_spinner[ 'fade' ]( view_number, wpvPaginatorLayout );
1872				}
1873			}
1874			WPViews.view_frontend_utils.get_updated_query_results( view_number, page, $( 'form.js-wpv-filter-form-' + view_number ), 'full' )
1875				.done( function( response ) {
1876					if ( response.success ) {
1877						data_for_get_page.response = response.data.full;
1878						self.prepare_slide( data_for_get_page );
1879					}
1880				});
1881		}
1882		self.pagination_preload_pages({
1883			view_number:	view_number, 
1884			cache_pages:	paged_view_data.cache_pages, 
1885			preload_pages:	paged_view_data.preload_pages, 
1886			page:			page, 
1887			max_reach:		max_reach, 
1888			max_pages:		paged_view_data.max_pages 
1889		});
1890		this.historyP[ view_number ] = page;
1891		return;
1892	};
1893	
1894	/**
1895	* prepare_slide
1896	*
1897	* Wrap the old layout into a div.wpv_slide_remove and change its ID to ~-response
1898	* Preload images on the new page if needed
1899	* Fire self.pagination_slide
1900	*
1901	* @param object data
1902	*
1903	* @since 1.9
1904	*/
1905	
1906	self.prepare_slide = function( data ) {
1907		var slide_data = $.extend( {}, self.slide_data_defaults, data ),
1908		width = slide_data.wpvPaginatorLayout.width(),
1909		outer_width = slide_data.wpvPaginatorLayout.outerWidth(),
1910		height = slide_data.wpvPaginatorLayout.height(),
1911		outer_height = slide_data.wpvPaginatorLayout.outerHeight(),
1912		responseObj = $( '<div></div>' ).append( slide_data.response ),
1913		preloadedImages,
1914		images;
1915		
1916		slide_data.responseView = responseObj.find( '.js-wpv-view-layout-' + slide_data.view_number );
1917		slide_data.responseFilter = responseObj.find( 'form.js-wpv-filter-form-' + slide_data.view_number ).html();
1918		slide_data.pagination_page_permalink = slide_data.responseView.data( 'permalink' );
1919		
1920		// Wrap old layout in a div.wpv_slide_remove nd change its ID to ~-response
1921		slide_data.wpvPaginatorLayout
1922			.attr( 'id', 'wpv-view-layout-' + slide_data.view_number + '-response' )
1923			.wrap( '<div class="wpv_slide_remove" style="width:' + outer_width + 'px;height:' + outer_height + 'px;overflow:hidden;" />' )
1924			.css( 'width', width );
1925		// Add an ID attribute to the upcoming new layout, and hide it
1926		slide_data.responseView
1927			.attr( 'id', 'wpv-view-layout-' + slide_data.view_number )
1928			.css( {
1929				'visibility': 'hidden',
1930				'width': width
1931			} );
1932		
1933		// Preload images if needed
1934		if ( slide_data.wpvPaginatorLayout.hasClass( 'js-wpv-layout-preload-images' ) ) {
1935			preloadedImages = [];
1936			images = slide_data.responseView.find( 'img' );
1937			if ( images.length < 1 ) {
1938				self.pagination_slide( slide_data );
1939			} else {
1940				images.one( 'load', function() {
1941					preloadedImages.push( $( this ).attr( 'src' ) );
1942					if ( preloadedImages.length === images.length ) {
1943						self.pagination_slide( slide_data );
1944					}
1945				}).each( function() {
1946					$( this ).load();
1947				});
1948			}
1949			// Fix inner nested Views with AJAX pagination: the inner View, when preloading images, was rendered with visibility:hidden by default
1950			slide_data.responseView
1951				.find( '.js-wpv-layout-preload-images' )
1952					.css( 'visibility', 'visible' );
1953		} else {
1954			self.pagination_slide( slide_data );
1955		}
1956	};
1957	
1958	/**
1959	* pagination_slide
1960	*
1961	* Routes to the right pagination effect callback
1962	*
1963	* @param object data
1964	*
1965	* @since 1.9
1966	*/
1967	
1968	self.pagination_slide = function( data ) {
1969		var slide_data = $.extend( {}, self.slide_data_defaults, data );
1970		
1971		switch ( slide_data.effect ) {
1972			case 'slideleft':
1973				slide_data.next = true;
1974				slide_data.effect = 'slideh';
1975				break;
1976			case 'slideright':
1977			case 'sliderightforward':
1978				slide_data.next = false;
1979				slide_data.effect = 'slideh';
1980				break;
1981			case 'slidedown':
1982			case 'slidedownforward':
1983				slide_data.next = false;
1984				slide_data.effect = 'slidev';
1985				break;
1986			case 'slideup':
1987				slide_data.next = true;
1988				slide_data.effect = 'slidev';
1989				break;
1990		}
1991		
1992		if ( ! slide_data.effect in self.pagination_effects ) {
1993			slide_data.effect = 'fade';
1994		}
1995		
1996		self.pagination_effects[ slide_data.effect ]( slide_data );
1997	};
1998	
1999	/**
2000	* pagination_queue_trigger
2001	*
2002	* Manage multiple and fast pagination requests.
2003	*
2004	* @param int		view_number
2005	* @param boolean	next
2006	* @param object		wpvPaginatorFilter
2007	*
2008	* @todo why do we pass next and wpvPaginatorFilter here?
2009	*
2010	* @since 1.9
2011	*/
2012	
2013	self.pagination_queue_trigger = function( view_number, next, wpvPaginatorFilter ) {
2014		var args,
2015		page,
2016		max_pages;
2017		if ( window.wpvPaginationQueue.hasOwnProperty( view_number ) && window.wpvPaginationQueue[view_number].length > 0 ) {
2018		// when double clicking,we have set window.wpvPaginationQueue[view_number][1] and maybe we could tweak it to change the page number. Maybe checkin historyP
2019			window.wpvPaginationQueue[view_number].sort();
2020			args = window.wpvPaginationQueue[view_number][0];
2021			window.wpvPaginationQueue[view_number].splice(0, 1);
2022			page = args[1];
2023			max_pages = args[4];
2024			if ( page > max_pages ) {
2025				page = 1;
2026			} else if ( page < 1 ) {
2027				page = max_pages;
2028			}
2029			self.trigger_pagination( view_number, page );
2030		}
2031	};
2032	
2033	// ------------------------------------
2034	// Events for Views pagination
2035	// ------------------------------------
2036	
2037	/**
2038	* Manage pagination triggered from prev/next links
2039	*
2040	* @since 1.9
2041	*/
2042	
2043	$( document ).on( 'click', '.js-wpv-pagination-next-link, .js-wpv-pagination-previous-link', function( e ) {
2044		e.preventDefault();
2045		var thiz = $( this ),
2046		view_number = thiz.data( 'viewnumber' ),
2047		page = thiz.data( 'page' );
2048		wpv_stop_rollover[ view_number ] = true;
2049		self.trigger_pagination( view_number, page );
2050	});
2051	
2052	/**
2053	* Manage pagination triggered by a change in the page selector dropdown
2054	*
2055	* @since 1.9
2056	*/
2057	
2058	$( document ).on( 'change', '.js-wpv-page-selector', function( e ) {
2059		e.preventDefault();
2060		var thiz = $( this ),
2061		view_number = thiz.data( 'viewnumber' ),
2062		page = thiz.val();
2063		wpv_stop_rollover[ view_number ] = true
2064		self.trigger_pagination( view_number, page );
2065	});
2066	
2067	/**
2068	* Manage pagination triggered by a click on a pagination link.
2069	*
2070	* @since 1.9
2071	*
2072	* @note Safari on iOS might need to also listen to the touchstart event. Investigate this!
2073	*/
2074	
2075	$( document ).on( 'click', '.js-wpv-pagination-link', function( e ) {
2076		e.preventDefault();
2077		var thiz = $( this ),
2078		data_collected = {};
2079		data_collected.view_number = thiz.data( 'viewnumber');
2080		data_collected.page = thiz.data( 'page' );
2081		var i;
2082		// TODO this can be improved: we should not need a loop here at all
2083		// @todo review this, data_collected.max_pages is UNDEFINED
2084		for ( i = 1; i <= data_collected.max_pages; i++ ) {
2085			if ( i === data_collected.page ) {
2086				$( '.js-wpv-page-link-' + data_collected.view_number + '-' + i ).addClass( 'wpv_page_current' );
2087			} else {
2088				$( '.js-wpv-page-link-' + data_collected.view_number + '-' + i ).removeClass( 'wpv_page_current' );
2089			}
2090			
2091		}
2092		wpv_stop_rollover[ data_collected.view_number ] = true
2093		self.trigger_pagination( data_collected.view_number, data_collected.page );
2094	});
2095	
2096	/*
2097	$( document ).on( 'click', '.js-wpv-pagination-pause-rollover', function( e ) {
2098		e.preventDefault();
2099		var view_num = $( this ).data( 'viewnumber' );
2100		wpv_stop_rollover[view_num] = true;
2101	});
2102	
2103	$( document ).on( 'click', '.js-wpv-pagination-resume-rollover', function( e ) {
2104		e.preventDefault();
2105		var view_num = $( this ).data( 'viewnumber' );
2106		delete wpv_stop_rollover[view_num];
2107	});
2108	*/
2109	
2110	// ------------------------------------
2111	// Events for WordPress Archives pagination
2112	// ------------------------------------
2113	
2114	/**
2115	* Manage pagination triggered from prev/next links, and numeric links, including their own prev/next ones
2116	*
2117	* @since 2.1
2118	*/
2119	
2120	$( document ).on( 'click', '.js-wpv-archive-pagination-link, .js-wpv-archive-pagination-next-link, .js-wpv-archive-pagination-prev-link, .js-wpv-archive-pagination-links-next-link, .js-wpv-archive-pagination-links-prev-link', function( e ) {
2121		e.preventDefault();
2122		var thiz = $( this ),
2123		view_number = thiz.data( 'viewnumber' ),
2124		page = thiz.data( 'page' );
2125		wpv_stop_rollover[ view_number ] = true;
2126		self.trigger_pagination( view_number, page );
2127	});
2128	
2129	// ------------------------------------
2130	// Custom events
2131	// ------------------------------------
2132	
2133	/**
2134	* js_event_wpv_pagination_completed
2135	*
2136	* Event fired after a pagination transition has been completed
2137	*
2138	* @param data
2139	* 	- view_unique_id
2140	* 	- effect
2141	* 	- speed
2142	* 	- layout
2143	*
2144	* @since 1.9
2145	*/
2146	
2147	$( document ).on( 'js_event_wpv_pagination_completed', function( event, data ) {
2148		WPViews.view_frontend_utils.render_frontend_media_shortcodes( data.layout );
2149		WPViews.view_frontend_utils.render_frontend_datepicker();
2150		// Init pagination for any inner View that might be included inside the new page
2151		self.init_paged_views( data.layout );
2152		self.init_preload_images( data.layout );
2153		self.init_preload_pages( data.layout );
2154	});
2155	
2156	$( document ).on( 'js_event_wpv_parametric_search_results_updated', function( event, data ) {
2157		// Init the pagination settings for this View results being updated
2158		self.init_paged_view( data.view_unique_id );
2159		// Init pagination for any inner View that might be included inside the new page
2160		self.init_paged_views( data.layout );
2161		self.init_preload_images( data.layout );
2162		self.init_preload_pages( data.layout );
2163	});
2164	
2165	// ------------------------------------
2166	// Init
2167	// ------------------------------------
2168	
2169	/**
2170	* init_effects
2171	*
2172	* Define the default pagination effects, can be extended by third parties.
2173	* Each callback gets the following parameters:
2174	* @param object slide_data
2175	*
2176	* @since 1.11
2177	*/
2178	
2179	self.init_effects = function() {
2180		self.pagination_effects = {
2181			infinite: function( slide_data ) {
2182				
2183				if ( slide_data.page != ( self.get_paged_view( slide_data.view_number ).page + 1 ) ) {
2184					// This should never happen! See self.pagination_effects_conditions
2185					$( '.js-wpv_slide_loading_img_' + slide_data.view_number ).fadeOut( function() {
2186						$( this ).remove();
2187					});
2188					slide_data.wpvPaginatorLayout
2189						.animate( { opacity: 1 }, 300 )
2190						.unwrap()// If it got here, it has a -response suffix in the ID and is wrapped in an auxiliar div
2191						.attr( 'id', 'wpv-view-layout-' + slide_data.view_number  );
2192					window.wpvPaginationAjaxLoaded[slide_data.view_number] = true;
2193					window.wpvPaginationAnimationFinished[slide_data.view_number] = true;
2194					
2195				} else {
2196				
2197					// content.match(/<!-- HOOK OPEN -->(W?)\<!-- HOOK CLOSE -->/);
2198					var data_for_events = {},
2199					data_for_history = {};
2200					
2201					data_for_events.view_unique_id	= slide_data.view_number;
2202					data_for_events.effect			= 'infinite';
2203					data_for_events.speed			= slide_data.speed;
2204					
2205					data_for_history.view_number				= slide_data.view_number;
2206					data_for_history.page						= slide_data.page;
2207					data_for_history.effect						= 'infinite';
2208					data_for_history.pagination_page_permalink	= slide_data.pagination_page_permalink;
2209					
2210					if (
2211						slide_data.wpvPaginatorLayout.find( '.js-wpv-loop' ).length > 0 
2212						&& slide_data.responseView.find( '.js-wpv-loop' ).length > 0 
2213					) {
2214						slide_data.responseView
2215							.find( '.js-wpv-loop' )
2216							.children()
2217								.addClass( 'wpv-loop-item-blink' )
2218								.css( { 'opacity': '0.3' } );
2219						slide_data.responseView
2220							.find( '.js-wpv-loop' )
2221							.prepend( 
2222								slide_data.wpvPaginatorLayout
2223									.find( '.js-wpv-loop' )
2224									.html() 
2225							);
2226						slide_data.wpvPaginatorLayout.html( slide_data.responseView.html() );
2227						slide_data.wpvPaginatorLayout
2228							.find( '.wpv-loop-item-blink' )
2229								.removeClass( 'wpv-loop-item-blink' )
2230								.animate( { opacity: 1 }, slide_data.speed );
2231								
2232					} else {
2233						var oldHTML = slide_data.wpvPaginatorLayout.html(),
2234						oldArray = oldHTML.split( '<!-- WPV_Infinite_Scroll -->', 3 ),
2235						oldReplace = ( oldArray.length > 2 ) ? oldArray[1] : '';
2236						slide_data.wpvPaginatorLayout.html(
2237							slide_data.responseView.html().replace( 
2238								'<!-- WPV_Infinite_Scroll_Insert -->',
2239								oldReplace
2240							)
2241						);
2242					}
2243					data_for_events.layout = slide_data.wpvPaginatorLayout;
2244					$( '.js-wpv_slide_loading_img_' + slide_data.view_number ).fadeOut( function() {
2245						$( this ).remove();
2246					});
2247					slide_data.wpvPaginatorLayout
2248						.unwrap()
2249						.attr( 'id', 'wpv-view-layout-' + slide_data.view_number  )
2250						.animate( { opacity: 1 }, 300, function() {
2251							slide_data.wpvPaginatorFilter.html( slide_data.responseFilter );
2252
2253							self.get_paged_view( slide_data.view_number ).page = slide_data.page;
2254
2255							window.wpvPaginationAjaxLoaded[slide_data.view_number] = true;
2256							window.wpvPaginationAnimationFinished[slide_data.view_number] = true;
2257							slide_data.callback_next_func();
2258							self.manage_browser_history( data_for_history );
2259							$( document ).trigger( 'js_event_wpv_pagination_completed', [ data_for_events ] );
2260							self.pagination_queue_trigger( slide_data.view_number, slide_data.next, slide_data.wpvPaginatorFilter );
2261						});
2262				}
2263			},
2264			slideh: function( slide_data ) {
2265				var height = slide_data.wpvPaginatorLayout.height(),
2266				old_height = slide_data.wpvPaginatorLayout.outerHeight(),
2267				new_height,
2268				data_for_events = {},
2269				data_for_history = {};
2270				
2271				data_for_events.view_unique_id	= slide_data.view_number;
2272				data_for_events.effect			= 'slideh';
2273				data_for_events.speed			= slide_data.speed;
2274				data_for_events.layout			= slide_data.responseView;
2275				
2276				data_for_history.view_number				= slide_data.view_number;
2277				data_for_history.page						= slide_data.page;
2278				data_for_history.effect						= 'slideh';
2279				data_for_history.pagination_page_permalink	= slide_data.pagination_page_permalink;
2280				
2281				if ( slide_data.next === true ) {
2282					slide_data.wpvPaginatorLayout.css( 'float', 'left' );
2283					slide_data.responseView.css( {"float": "left", "visibility": "visible"} );
2284					slide_data.wpvPaginatorLayout
2285						.after( slide_data.responseView )
2286						.parent()
2287							.children()
2288								.wrapAll( '<div style="width:5000px;" />' );
2289					$( '.js-wpv_slide_loading_img_' + slide_data.view_number ).fadeOut(function() {
2290						$( this ).remove();
2291					});
2292					new_height = slide_data.responseView.outerHeight();
2293					if ( old_height === new_height ) {
2294						slide_data.wpvPaginatorLayout
2295							.parent()
2296								.animate( {marginLeft: '-' + slide_data.wpvPaginatorLayout.outerWidth()+'px'}, slide_data.speed+500, function() {
2297									slide_data.responseView.css( {'position': 'static', 'float': 'none'} );
2298									slide_data.wpvPaginatorLayout.unwrap().unwrap().remove();
2299									
2300									slide_data.wpvPaginatorFilter.html( slide_data.responseFilter );
2301									
2302									window.wpvPaginationAjaxLoaded[slide_data.view_number] = true;
2303									window.wpvPaginationAnimationFinished[slide_data.view_number] = true;
2304									slide_data.callback_next_func();
2305									self.manage_browser_history( data_for_history );
2306									$( document ).trigger( 'js_event_wpv_pagination_completed', [ data_for_events ] );
2307									self.pagination_queue_trigger( slide_data.view_number, slide_data.next, slide_data.wpvPaginatorFilter );
2308								});
2309					} else if ( old_height > new_height ) {
2310						slide_data.wpvPaginatorLayout
2311							.parent()
2312								.animate( {marginLeft: '-' + slide_data.wpvPaginatorLayout.outerWidth()+'px'}, slide_data.speed+500, function() {
2313									slide_data.wpvPaginatorLayout
2314										.parent().parent()
2315											.animate( {height: slide_data.responseView.outerHeight()+'px'}, slide_data.speed/2, function() {
2316												slide_data.responseView.css( {'position': 'static', 'float': 'none'} );
2317												slide_data.wpvPaginatorLayout.unwrap().unwrap().remove();
2318												
2319												slide_data.wpvPaginatorFilter.html( slide_data.responseFilter );
2320												
2321												window.wpvPaginationAjaxLoaded[slide_data.view_number] = true;
2322												window.wpvPaginationAnimationFinished[slide_data.view_number] = true;
2323												slide_data.callback_next_func();
2324												self.manage_browser_history( data_for_history );
2325												$( document ).trigger( 'js_event_wpv_pagination_completed', [ data_for_events ] );
2326												self.pagination_queue_trigger( slide_data.view_number, slide_data.next, slide_data.wpvPaginatorFilter );
2327											});
2328								});
2329					} else {
2330						slide_data.wpvPaginatorLayout
2331							.parent().parent()
2332								.animate( {height: slide_data.responseView.outerHeight()+'px'}, slide_data.speed/2, function() {
2333									slide_data.wpvPaginatorLayout
2334										.parent()
2335											.animate( {marginLeft: '-' + slide_data.wpvPaginatorLayout.outerWidth()+'px'}, slide_data.speed+500, function() {
2336												slide_data.responseView.css( {'position': 'static', 'float': 'none'} );
2337												slide_data.wpvPaginatorLayout.unwrap().unwrap().remove();
2338												
2339												slide_data.wpvPaginatorFilter.html( slide_data.responseFilter );
2340												
2341												window.wpvPaginationAjaxLoaded[slide_data.view_number] = true;
2342												window.wpvPaginationAnimationFinished[slide_data.view_number] = true;
2343												slide_data.callback_next_func();
2344												self.manage_browser_history( data_for_history );
2345												$( document ).trigger( 'js_event_wpv_pagination_completed', [ data_for_events ] );
2346												self.pagination_queue_trigger( slide_data.view_number, slide_data.next, slide_data.wpvPaginatorFilter );
2347											});
2348								});
2349					}
2350				} else {
2351					slide_data.wpvPaginatorLayout.css( 'float', 'right' );
2352					slide_data.responseView.css( {'float': 'right', 'visibility': 'visible'} );
2353					slide_data.wpvPaginatorLayout
2354						.after( slide_data.responseView )
2355						.parent()
2356							.children()
2357								.wrapAll( '<div style="height:' + height +  ';width:' + ( slide_data.responseView.outerWidth() + slide_data.wpvPaginatorLayout.outerWidth() ) + 'px; margin-left:-' + ( slide_data.wpvPaginatorLayout.outerWidth() ) + 'px;" />' );
2358					$( '.js-wpv_slide_loading_img_' + slide_data.view_number ).fadeOut( function() {
2359						$( this ).remove();
2360					});
2361					new_height = slide_data.responseView.outerHeight();
2362					if ( old_height === new_height ) {
2363						slide_data.wpvPaginatorLayout
2364							.parent()
2365								.animate( {marginLeft: '0px'}, slide_data.speed+500, function() {
2366									slide_data.responseView.css( {'position': 'static', 'margin': '0px', 'float': 'none'} );
2367									slide_data.wpvPaginatorLayout.unwrap().unwrap().remove();
2368									
2369									slide_data.wpvPaginatorFilter.html( slide_data.responseFilter );
2370									
2371									window.wpvPaginationAjaxLoaded[slide_data.view_number] = true;
2372									window.wpvPaginationAnimationFinished[slide_data.view_number] = true;
2373									slide_data.callback_next_func();
2374									self.manage_browser_history( data_for_history );
2375									$( document ).trigger( 'js_event_wpv_pagination_completed', [ data_for_events ] );
2376									self.pagination_queue_trigger( slide_data.view_number, slide_data.next, slide_data.wpvPaginatorFilter );
2377								});
2378					} else if ( old_height > new_height ) {
2379						slide_data.wpvPaginatorLayout
2380							.parent()
2381								.animate( {marginLeft: '0px'}, slide_data.speed+500, function() {
2382									slide_data.wpvPaginatorLayout
2383										.parent().parent()
2384											.animate( {height: slide_data.responseView.outerHeight()+'px'}, slide_data.speed/2, function() {
2385												slide_data.responseView.css( {'position': 'static', 'margin': '0px', 'float': 'none'} );
2386												slide_data.wpvPaginatorLayout.unwrap().unwrap().remove();
2387												
2388												slide_data.wpvPaginatorFilter.html( slide_data.responseFilter );
2389												
2390												window.wpvPaginationAjaxLoaded[slide_data.view_number] = true;
2391												window.wpvPaginationAnimationFinished[slide_data.view_number] = true;
2392												slide_data.callback_next_func();
2393												self.manage_browser_history( data_for_history );
2394												$( document ).trigger( 'js_event_wpv_pagination_completed', [ data_for_events ] );
2395												self.pagination_queue_trigger( slide_data.view_number, slide_data.next, slide_data.wpvPaginatorFilter );
2396											});
2397								});
2398					} else {
2399						slide_data.wpvPaginatorLayout
2400							.parent().parent()
2401								.animate( {height: slide_data.responseView.outerHeight()+'px'}, slide_data.speed/2, function() {
2402									slide_data.wpvPaginatorLayout
2403										.parent()
2404											.animate( {marginLeft: '0px'}, slide_data.speed+500, function() {
2405												slide_data.responseView.css( {'position': 'static', 'margin': '0px', 'float': 'none'} );
2406												slide_data.wpvPaginatorLayout.unwrap().unwrap().remove();
2407												
2408												slide_data.wpvPaginatorFilter.html( slide_data.responseFilter );
2409												
2410												window.wpvPaginationAjaxLoaded[slide_data.view_number] = true;
2411												window.wpvPaginationAnimationFinished[slide_data.view_number] = true;
2412												slide_data.callback_next_func();
2413												self.manage_browser_history( data_for_history );
2414												$( document ).trigger( 'js_event_wpv_pagination_completed', [ data_for_events ] );
2415												self.pagination_queue_trigger( slide_data.view_number, slide_data.next, slide_data.wpvPaginatorFilter );
2416											});
2417								});
2418					}
2419				}
2420			},
2421			slidev: function( slide_data ) {
2422				var old_height = slide_data.wpvPaginatorLayout.outerHeight(),
2423				new_height,
2424				data_for_events = {},
2425				data_for_history = {};
2426				
2427				data_for_events.view_unique_id	= slide_data.view_number;
2428				data_for_events.effect			= 'slidev';
2429				data_for_events.speed			= slide_data.speed;
2430				data_for_events.layout			= slide_data.responseView;
2431				
2432				data_for_history.view_number				= slide_data.view_number;
2433				data_for_history.page						= slide_data.page;
2434				data_for_history.effect						= 'slidev';
2435				data_for_history.pagination_page_permalink	= slide_data.pagination_page_permalink;
2436				
2437				if ( slide_data.next === true ) {
2438					slide_data.responseView.css( 'visibility', 'visible' );
2439					slide_data.wpvPaginatorLayout
2440						.after( slide_data.responseView )
2441						.parent()
2442							.children()
2443								.wrapAll( '<div />' );
2444					$( '.js-wpv_slide_loading_img_' + slide_data.view_number ).fadeOut( function(){
2445						$( this ).remove();
2446					});
2447					new_height = slide_data.responseView.outerHeight();
2448					if ( old_height === new_height ) {
2449						slide_data.wpvPaginatorLayout
2450							.parent()
2451								.animate( {marginTop: '-' + slide_data.responseView.outerHeight()+'px'}, slide_data.speed+500, function() {
2452									slide_data.responseView.css( {'position': 'static', 'margin': '0px'} );
2453									slide_data.wpvPaginatorLayout.unwrap().unwrap().remove();
2454									
2455									slide_data.wpvPaginatorFilter.html( slide_data.responseFilter );
2456									
2457									window.wpvPaginationAjaxLoaded[slide_data.view_number] = true;
2458									window.wpvPaginationAnimationFinished[slide_data.view_number] = true;
2459									slide_data.callback_next_func();
2460									self.manage_browser_history( data_for_history );
2461									$( document ).trigger( 'js_event_wpv_pagination_completed', [ data_for_events ] );
2462									self.pagination_queue_trigger( slide_data.view_number, slide_data.next, slide_data.wpvPaginatorFilter );
2463								});
2464					} else if ( old_height > new_height ) {
2465						slide_data.wpvPaginatorLayout
2466							.parent()
2467								.animate( {marginTop: '-'+old_height+'px'}, slide_data.speed+500, function() {
2468									slide_data.wpvPaginatorLayout
2469										.parent().parent()
2470											.animate( {height: slide_data.responseView.outerHeight()+'px'}, slide_data.speed/2, function() {
2471												slide_data.responseView.css( {'position': 'static', 'margin': '0px'} );
2472												slide_data.wpvPaginatorLayout.unwrap().unwrap().remove();
2473												
2474												slide_data.wpvPaginatorFilter.html( slide_data.responseFilter );
2475												
2476												window.wpvPaginationAjaxLoaded[slide_data.view_number] = true;
2477												window.wpvPaginationAnimationFinished[slide_data.view_number] = true;
2478												slide_data.callback_next_func();
2479												self.manage_browser_history( data_for_history );
2480												$( document ).trigger( 'js_event_wpv_pagination_completed', [ data_for_events ] );
2481												self.pagination_queue_trigger( slide_data.view_number, slide_data.next, slide_data.wpvPaginatorFilter );
2482											});
2483								});
2484					} else {
2485						slide_data.wpvPaginatorLayout
2486							.parent().parent()
2487								.animate( {height: slide_data.responseView.outerHeight()+'px'}, slide_data.speed/2, function() {
2488									slide_data.wpvPaginatorLayout
2489										.parent()
2490											.animate( {marginTop: '-'+old_height+'px'}, slide_data.speed+500, function() {
2491												slide_data.responseView.css( {'position': 'static', 'margin': '0px'} );
2492												slide_data.wpvPaginatorLayout.unwrap().unwrap().remove();
2493												
2494												slide_data.wpvPagi
2494natorFilter.html( slide_data.responseFilter );
2495												
2496												window.wpvPaginationAjaxLoaded[slide_data.view_number] = true;
2497												window.wpvPaginationAnimationFinished[slide_data.view_number] = true;
2498												slide_data.callback_next_func();
2499												self.manage_browser_history( data_for_history );
2500												$( document ).trigger( 'js_event_wpv_pagination_completed', [ data_for_events ] );
2501												self.pagination_queue_trigger( slide_data.view_number, slide_data.next, slide_data.wpvPaginatorFilter );
2502											});
2503								});
2504					}
2505				} else {
2506					slide_data.responseView.css( 'visibility', 'visible' );
2507					slide_data.wpvPaginatorLayout
2508						.before( slide_data.responseView )
2509						.parent()
2510							.children()
2511								.wrapAll( '<div />' );
2512					$( '.js-wpv_slide_loading_img_' + slide_data.view_number ).fadeOut( function() {
2513						$( this ).remove();
2514					});
2515					new_height = slide_data.responseView.outerHeight();
2516					slide_data.wpvPaginatorLayout.parent().css( {'position': 'relative', 'margin-top': '-' + slide_data.responseView.outerHeight() + 'px'} );
2517					if ( old_height === new_height ) {
2518						slide_data.wpvPaginatorLayout
2519							.parent()
2520								.animate( {marginTop: '0px'}, slide_data.speed+500, function() {
2521									slide_data.responseView.css( {'position': 'static', 'margin': '0px'} );
2522									slide_data.wpvPaginatorLayout.unwrap().unwrap().remove();
2523									
2524									slide_data.wpvPaginatorFilter.html( slide_data.responseFilter );
2525									
2526									window.wpvPaginationAjaxLoaded[slide_data.view_number] = true;
2527									window.wpvPaginationAnimationFinished[slide_data.view_number] = true;
2528									slide_data.callback_next_func();
2529									self.manage_browser_history( data_for_history );
2530									$( document ).trigger( 'js_event_wpv_pagination_completed', [ data_for_events ] );
2531									self.pagination_queue_trigger( slide_data.view_number, slide_data.next, slide_data.wpvPaginatorFilter );
2532								});
2533					} else if ( old_height > new_height ) {
2534						slide_data.wpvPaginatorLayout
2535							.parent()
2536								.animate( {marginTop: '0px'}, slide_data.speed+500, function() {
2537									slide_data.wpvPaginatorLayout
2538										.parent().parent()
2539											.animate( {height: slide_data.responseView.outerHeight()+'px'}, slide_data.speed/2, function() {
2540												slide_data.responseView.css( {'position': 'static', 'margin': '0px'} );
2541												slide_data.wpvPaginatorLayout.unwrap().unwrap().remove();
2542												
2543												slide_data.wpvPaginatorFilter.html( slide_data.responseFilter );
2544												
2545												window.wpvPaginationAjaxLoaded[slide_data.view_number] = true;
2546												window.wpvPaginationAnimationFinished[slide_data.view_number] = true;
2547												slide_data.callback_next_func();
2548												self.manage_browser_history( data_for_history );
2549												$( document ).trigger( 'js_event_wpv_pagination_completed', [ data_for_events ] );
2550												self.pagination_queue_trigger( slide_data.view_number, slide_data.next, slide_data.wpvPaginatorFilter );
2551											});
2552						});
2553					} else {
2554						slide_data.wpvPaginatorLayout
2555							.parent().parent()
2556								.animate( {height: slide_data.responseView.outerHeight()+'px'}, slide_data.speed/2, function() {
2557									slide_data.wpvPaginatorLayout
2558										.parent()
2559											.animate( {marginTop: '0px'}, slide_data.speed+500, function() {
2560												slide_data.responseView.css( {'position': 'static', 'margin': '0px'} );
2561												slide_data.wpvPaginatorLayout.unwrap().unwrap().remove();
2562												
2563												slide_data.wpvPaginatorFilter.html( slide_data.responseFilter );
2564												
2565												window.wpvPaginationAjaxLoaded[slide_data.view_number] = true;
2566												window.wpvPaginationAnimationFinished[slide_data.view_number] = true;
2567												slide_data.callback_next_func();
2568												self.manage_browser_history( data_for_history );
2569												$( document ).trigger( 'js_event_wpv_pagination_completed', [ data_for_events ] );
2570												self.pagination_queue_trigger( slide_data.view_number, slide_data.next, slide_data.wpvPaginatorFilter );
2571											});
2572								});
2573					}
2574				}
2575			},
2576			fade: function( slide_data ) {
2577				var old_height = slide_data.wpvPaginatorLayout.outerHeight(),
2578				new_height,
2579				data_for_events = {},
2580				data_for_history = {};
2581
2582				data_for_events.view_unique_id	= slide_data.view_number;
2583				data_for_events.effect			= 'fade';
2584				data_for_events.speed			= slide_data.speed;
2585				data_for_events.layout			= slide_data.responseView;
2586				
2587				data_for_history.view_number				= slide_data.view_number;
2588				data_for_history.page						= slide_data.page;
2589				data_for_history.effect						= 'fade';
2590				data_for_history.pagination_page_permalink	= slide_data.pagination_page_permalink;
2591				
2592				$( '.js-wpv_slide_loading_img_' + slide_data.view_number ).fadeOut( function() {
2593					$( this ).remove();
2594				});
2595
2596				slide_data.wpvPaginatorLayout
2597					.css( {'position': 'absolute', 'z-index': '5'} )
2598					.after( slide_data.responseView )
2599						.next()
2600						.css( 'position', 'static' );
2601				// We need to set a zero timeout here since the above modifications introduce a race condition that produces a wrong new_height 
2602				setTimeout( function() {
2603					new_height = slide_data.responseView.outerHeight();
2604					if ( old_height === new_height ) {
2605						slide_data.wpvPaginatorLayout.fadeOut( slide_data.speed, function() {
2606							slide_data.wpvPaginatorLayout.unwrap().remove();
2607
2608							slide_data.wpvPaginatorFilter.html( slide_data.responseFilter );
2609						});
2610						// In the case when the old height is equal to the new height, we need to perform the fade-out of the old container and the
2611						// fade in of the new container in parallel, at the same time. Even though, UX-wise, this is not 100% correct, this choice
2612						// was made because of some clients complaints. This is due to backwards compatibility
2613						slide_data.responseView
2614							.hide()
2615							.css( 'visibility', 'visible' )
2616							.fadeIn( slide_data.speed, function() {
2617								window.wpvPaginationAjaxLoaded[slide_data.view_number] = true;
2618								window.wpvPaginationAnimationFinished[slide_data.view_number] = true;
2619								slide_data.callback_next_func();
2620								self.manage_browser_history( data_for_history );
2621								$( document ).trigger( 'js_event_wpv_pagination_completed', [ data_for_events ] );
2622								WPViews.view_pagination.pagination_queue_trigger( slide_data.view_number, slide_data.next, slide_data.wpvPaginatorFilter );
2623							});
2624					} else {
2625						slide_data.wpvPaginatorLayout.fadeOut( slide_data.speed, function() {
2626							slide_data.wpvPaginatorLayout
2627								.parent()
2628									.animate( {height: new_height+'px'}, slide_data.speed, function() {
2629										slide_data.wpvPaginatorLayout.unwrap().remove();
2630										
2631										slide_data.wpvPaginatorFilter.html( slide_data.responseFilter );
2632
2633										slide_data.responseView
2634											.hide()
2635											.css( 'visibility', 'visible' )
2636											.fadeIn( slide_data.speed, function() {
2637												window.wpvPaginationAjaxLoaded[slide_data.view_number] = true;
2638												window.wpvPaginationAnimationFinished[slide_data.view_number] = true;
2639												slide_data.callback_next_func();
2640												self.manage_browser_history( data_for_history );
2641												$( document ).trigger( 'js_event_wpv_pagination_completed', [ data_for_events ] );
2642												WPViews.view_pagination.pagination_queue_trigger( slide_data.view_number, slide_data.next, slide_data.wpvPaginatorFilter );
2643											});
2644									});
2645						});
2646					}
2647				}, 0 );
2648			}
2649		};
2650	
2651	};
2652	
2653	/**
2654	* manage_browser_history
2655	*
2656	* Makes the history in the browser work with AJAX pagination, except infinite scrolling and sliders
2657	*
2658	* @param object data
2659	*
2660	* @since 1.11
2661	*/
2662	
2663	self.manage_browser_history = function( data ) {
2664		if ( 
2665			self.get_paged_view( data.view_number ).type != 'rollover'
2666		) {
2667			if ( self.get_paged_view( data.view_number ).manage_history == 'enabled' ) {
2668				if ( self.add_paginated_history == true ) {
2669					if ( ! _.contains( self.pagination_effect_state_keep, data.effect ) ) {
2670						if ( _.contains( self.pagination_effect_state_replace, data.effect ) ) {
2671							history.replaceState( null, '', data.pagination_page_permalink );
2672						} else {
2673							self.last_paginated_view.push( data.view_number );
2674							state_obj = { 
2675								view_number: data.view_number, 
2676								page: data.page
2677							};
2678							history.pushState( state_obj, '', data.pagination_page_permalink );
2679							// http://scrollsample.appspot.com/items
2680							// http://html5.gingerhost.com/
2681							self.paginated_history_reach = self.paginated_history_reach + 1;
2682						}
2683					}
2684				} else {
2685					self.add_paginated_history = true;
2686				}
2687			}
2688		}
2689	};
2690	
2691	/**
2692	* window.onpopstate
2693	*
2694	* Manages the browser back button click based on daya added by Views pagination
2695	*
2696	* @since 1.11
2697	*/
2698	
2699	window.onpopstate = function( event ) {
2700		if ( event.state == null ) {
2701			var last_paginated_view_number = self.last_paginated_view.pop();
2702			if ( last_paginated_view_number != undefined ) {
2703				self.add_paginated_history = false;
2704				self.paged_views_initial_page[ last_paginated_view_number ] = self.paged_views_initial_page[ last_paginated_view_number ] || 1;
2705				self.trigger_pagination( last_paginated_view_number, self.paged_views_initial_page[ last_paginated_view_number ] );
2706			}
2707		} else {
2708			if (
2709				_.has( event.state, 'view_number' )
2710				&& _.has( event.state, 'page' )
2711			) {
2712				self.add_paginated_history = false;
2713				self.trigger_pagination( event.state.view_number, event.state.page );
2714			}
2715		}
2716	};
2717	
2718	/**
2719	* When the parametric search with automatic results has been completed, reset the pagination history and add a state with the current URL
2720	*
2721	* @since 1.11
2722	*/
2723	
2724	$( document ).on( 'js_event_wpv_parametric_search_results_updated', function( event, data ) {
2725		window.wpvCachedPages[ data.view_unique_id ] = [];
2726		self.last_paginated_view = [];
2727		if ( self.paginated_history_reach > 0 ) {
2728			window.history.go( -Math.abs( self.paginated_history_reach ) );
2729			self.paginated_history_reach = 0;
2730		}
2731		// HACK! HACK! HACK!
2732		// Chrome and Safari execute history.replaceState before history.go so we end up with a mess
2733		// That is why we need to set a timeout here
2734		// See https://code.google.com/p/chromium/issues/detail?id=529810
2735		setTimeout( function() {
2736			history.replaceState( null, '', data.permalink );
2737		}, 100 );
2738	});
2739	
2740	/**
2741	* init_effects_conditions
2742	*
2743	* Lets you define a condition that an effect must meet to be applied, doing nothing otherwise.
2744	* Each callback gets the following parameters:
2745	* @param object	view_pagination_data
2746	* @param int	page
2747	*
2748	* @since 1.11
2749	*/
2750	
2751	self.init_effects_conditions = function() {
2752		self.pagination_effects_conditions = {
2753			infinite: function( view_pagination_data, page ) {
2754				if ( page != ( view_pagination_data.page + 1 ) ) {
2755					return false;
2756				}
2757				return true;				
2758			}
2759		};
2760	};
2761	
2762	/**
2763	* init_effects_conditions
2764	*
2765	* Lets you define a condition that an effect must meet to be applied, doing nothing otherwise.
2766	* Each callback gets the following parameters:
2767	* @param string	view_number
2768	* @param object	wpvPaginatorLayout
2769	*
2770	* @since 1.11
2771	*/
2772	
2773	self.init_effects_spinner = function() {
2774		self.pagination_effects_spinner['fade']			= 
2775		self.pagination_effects_spinner['slideleft']	= 
2776		self.pagination_effects_spinner['slideright']	= 
2777		self.pagination_effects_spinner['sliderightforward']	= 
2778		self.pagination_effects_spinner['slideh']		= 
2779		self.pagination_effects_spinner['slideup']		=
2780		self.pagination_effects_spinner['slidedown']	= 
2781		self.pagination_effects_spinner['slidedownforward']	= 
2782		self.pagination_effects_spinner['slidev']		= function( view_number, wpvPaginatorLayout ) {
2783			var img = new Image();
2784			img.src = self.get_paged_view( view_number ).spinner_image;
2785			img.onload = function() {
2786				var wpvPaginatorLayoutOffset = wpvPaginatorLayout.position(),
2787				wpvPaginatorSpinner = '<div style="'
2788					+ 'width:' + img.width + 'px;'
2789					+ 'height:' + img.height + 'px;'
2790					+ 'border:none;'
2791					+ 'background:transparent 50% 50% no-repeat url(' + self.get_paged_view( view_number ).spinner_image + ');'
2792					+ 'position:absolute;'
2793					+ 'z-index:99;'
2794					+ 'top:' + ( Math.round( wpvPaginatorLayoutOffset.top ) + ( Math.round( wpvPaginatorLayout.height()/2 ) ) - ( Math.round( img.height/2 ) ) ) + 'px;'
2795					+ 'left:' + ( Math.round( wpvPaginatorLayoutOffset.left ) + ( Math.round( wpvPaginatorLayout.width()/2 ) ) - ( Math.round( img.width/2 ) ) ) + 'px;'
2796					+ '" '
2797					+ 'class="wpv_slide_loading_img js-wpv_slide_loading_img_' + view_number + '"'
2798					+ '>'
2799					+ '</div>';
2800				wpvPaginatorLayout
2801					.before( wpvPaginatorSpinner )
2802						.animate( { opacity: 0.5 }, 300 );
2803			};
2804		};
2805		self.pagination_effects_spinner['infinite'] = function( view_number, wpvPaginatorLayout ) {
2806			var img = new Image();
2807			img.src = self.get_paged_view( view_number ).spinner_image;
2808			img.onload = function() {
2809				var wpvPaginatorLayoutOffset = wpvPaginatorLayout.position(),
2810				wpvPaginatorSpinner = '<div style="'
2811					+ 'width:' + img.width + 'px;'
2812					+ 'height:' + img.height + 'px;'
2813					+ 'border:none;'
2814					+ 'background:transparent 50% 50% no-repeat url(' + self.get_paged_view( view_number ).spinner_image + ');'
2815					+ 'position:absolute;'
2816					+ 'z-index:99;'
2817					+ 'top:' + ( Math.round( wpvPaginatorLayoutOffset.top ) + ( wpvPaginatorLayout.height() ) - ( Math.round( img.height/2 ) ) ) + 'px;'
2818					+ 'left:' + ( Math.round( wpvPaginatorLayoutOffset.left ) + ( Math.round( wpvPaginatorLayout.width()/2 ) ) - ( Math.round( img.width/2 ) ) ) + 'px;'
2819					+ '" '
2820					+ 'class="wpv_slide_loading_img js-wpv_slide_loading_img_' + view_number + '"'
2821					+ '>'
2822					+ '</div>';
2823				wpvPaginatorLayout
2824					.before( wpvPaginatorSpinner )
2825						.animate( { opacity: 0.5 }, 300 );
2826			};
2827		};
2828	};
2829	
2830	/**
2831	* init_paged_views
2832	*
2833	* Gather the data for paginating each of the Views rendered in a page
2834	*
2835	* @since 1.11
2836	*/
2837	
2838	self.init_paged_views = function( container ) {
2839		var init_scrolling_event = false,
2840		init_rollover_timing = false;
2841		this.historyP = this.historyP || [];
2842		window.wpvCachedPages = window.wpvCachedPages || [];
2843		window.wpvCachedImages = window.wpvCachedImages || [];
2844		$( '.js-wpv-view-layout', container ).each( function() {
2845			var thiz = $( this ),
2846			view_number = thiz.data( 'viewnumber' );
2847			self.init_paged_view( view_number );
2848			if (
2849				self.paged_views[ view_number ].effect == 'infinite' 
2850				&& self.paged_views[ view_number ].page == 1
2851			) {
2852				init_scrolling_event = true;
2853			}
2854			if ( 
2855				self.paged_views[ view_number ].type == 'rollover' 
2856				&& ! wpv_stop_rollover.hasOwnProperty( view_number ) 
2857			) {
2858				init_rollover_timing	= true;
2859				rollover_has_index		= _.findIndex( self.rollover_running, function( item ) { 
2860					return item.view_number == view_number; 
2861				});
2862				if ( rollover_has_index < 0 ) {
2863					// This rollover was not there, so trigger it
2864					var thiz_rollover_data = { 
2865						view_number:	view_number, 
2866						page:			1,
2867						force_reset:	false
2868					};
2869					self.rollover_running.push( thiz_rollover_data );
2870					if ( self.init_rollover_timing_fired ) {
2871						self.trigger_rollover( thiz_rollover_data );
2872					}
2873				} else {
2874					self.rollover_running[ rollover_has_index ] = {
2875						view_number:	view_number,
2876						page:			1,
2877						force_reset:	true
2878					};
2879				}
2880			}
2881		});
2882		if ( 
2883			! self.init_scrolling_event_fired 
2884			&& init_scrolling_event 
2885		) {
2886			self.init_scrolling_event_callback();
2887		}
2888		
2889		if ( 
2890			! self.init_rollover_timing_fired
2891			&& init_rollover_timing
2892		) {
2893			self.init_rollover_timing_callback();
2894		}
2895		return self;
2896	};
2897	
2898	/**
2899	* init_paged_view
2900	*
2901	* Gather pagination info for a specific View rendered in a page.
2902	* Note that this is also used to init the View pagination data after a parametric search change.
2903	*
2904	* @todo check the existence of $( '#wpv-view-layout-' + view_number ) and set defauls otherwise. 
2905	*
2906	* @since 1.11
2907	*/
2908	
2909	self.init_paged_view = function( view_number ) {
2910		this.historyP = this.historyP || [];
2911		self.paged_views[ view_number ] = $( '#wpv-view-layout-' + view_number ).data( 'pagination' );
2912		self.paged_views_initial_page[ view_number ] = self.paged_views[ view_number ].page;
2913		this.historyP[ view_number ] = self.paged_views[ view_number ].page;
2914		window.wpvCachedPages[ view_number ] = [];
2915		if ( 
2916			self.paged_views[ view_number ].type != 'disabled' 
2917			&& self.paged_views[ view_number ].type != 'paged' 
2918			&& self.paged_views[ view_number ].page > 1 
2919		) {
2920			// Infinite scrolling only can be triggered from the first page - individual URLs can not have that effect
2921			$( '#wpv-view-layout-' + view_number ).removeClass( 'js-wpv-layout-infinite-scrolling' );
2922		}
2923		if ( $( '#wpv-view-layout-' + view_number ).parents( '.js-wpv-view-layout' ).length > 0 ) {
2924			// Disable history management in inner Views in nested structures
2925			self.paged_views[ view_number ].manage_history = 'disabled';
2926		}
2927	};
2928	
2929	/**
2930	 * Generate the View pagintion data, on demand.
2931	 *
2932	 * This method will ensure that we can generate the pagination data for a View JIT 
2933	 * when it is needed for a View which was dynamically added to the page, by a 
2934	 * third party provider.
2935	 *
2936	 * @param view_number string The View unique hash.
2937	 *
2938	 * @since 2.3.1
2939	 */
2940	
2941	self.get_paged_view = function( view_number ) {
2942		if ( ! _.has( self.paged_views, view_number ) ) {
2943			self.init_paged_view( view_number );
2944		}
2945		return self.paged_views[ view_number ];
2946	}
2947	
2948	/**
2949	* is_infinite_triggable
2950	*
2951	* Auxiliar method to check whether the scroll got to a point where a pagination event should be triggered
2952	*
2953	* @param object	view_layout
2954	*
2955	* @since 1.11
2956	* @since 2.0	Add a tolerance setting
2957	* @since 2.0	Trigger the pagination when scrolling to the bottom of the page
2958	*/
2959	
2960	self.is_infinite_triggable = function( view_layout ) {
2961		var flag_element = view_layout,
2962		view_number = view_layout.data( 'viewnumber' );
2963		infinite_tolerance = self.get_paged_view( view_number ).infinite_tolerance;
2964		infinite_tolerance = ( isNaN( infinite_tolerance ) ) ? 0 : + infinite_tolerance;
2965		if ( view_layout.find( '.js-wpv-loop' ).length > 0 ) {
2966			flag_element = view_layout.find( '.js-wpv-loop' );
2967		}
2968		return (
2969			( flag_element.offset().top + flag_element.outerHeight() ) <= ( $( window ).scrollTop() + $( window ).height() + infinite_tolerance )
2970			|| ( $( window ).scrollTop() + $(window).height() ) == $( document ).height()
2971		);
2972	};
2973	
2974	/**
2975	* init_scrolling_event_callback
2976	*
2977	* Init the scrolling event callback, only when there is a View with infinite scrolling in a page
2978	*
2979	* @since 1.11
2980	*/
2981	
2982	self.init_scrolling_event_callback = function() {
2983		$( window ).on( 'scroll', _.debounce( 
2984			_.throttle( 
2985				function() {
2986					$( '.js-wpv-layout-infinite-scrolling' ).each( function() {
2987						var thiz = $( this ),
2988						thiz_view_number = thiz.data( 'viewnumber' ),
2989						thiz_paged_view_data = self.get_paged_view( thiz_view_number );
2990						if ( 
2991							thiz_paged_view_data.page < thiz_paged_view_data.max_pages 
2992							&& self.is_infinite_triggable( thiz )
2993						) {
2994							self.trigger_pagination( thiz_view_number, thiz_paged_view_data.page + 1 );
2995						}
2996					});
2997				},
2998				1000
2999			),
3000			1000
3001		));
3002		self.init_scrolling_event_fired = true;
3003	};
3004
3005	/**
3006	* trigger_rollover
3007	*
3008	* Trigger the rollover on a given View, using timeout
3009	*
3010	* @since 2.2
3011	*/
3012	
3013	self.trigger_rollover = function( view_data ) {
3014		var rollover_data	= $.extend( {}, { view_number: '', page: 1, force_reset: false }, view_data ),
3015		view_number			= rollover_data.view_number,
3016		paged_view_data		= self.get_paged_view( view_number );
3017		
3018		if ( 
3019			paged_view_data.max_pages > 1
3020			&& $("#wpv-view-layout-" + view_number ).length > 0 
3021		) {
3022			setTimeout( function() {
3023				var rollover_index = _.findIndex( self.rollover_paused, function ( item ) {
3024                    return item.view_number == view_number;
3025                } );
3026                if ( self.rollover_paused[ rollover_index ]
3027                	&& self.rollover_paused[ rollover_index ].view_number
3028					&& self.rollover_paused[ rollover_index ].view_number == view_number
3029				) {
3030                    setTimeout( function() { self.trigger_rollover( view_data ) }, 100 );
3031                } else {
3032                    if (
3033                        ! wpv_stop_rollover.hasOwnProperty( view_number ) &&
3034						$( "#wpv-view-layout-" + view_number ).length > 0
3035                    ) {
3036                        // Get native current page and index on the rollovers array
3037                        var view_page = rollover_data.page,
3038                            rollover_index = _.findIndex( self.rollover_running, function ( item ) {
3039                                return item.view_number == view_number;
3040                            } );
3041                        // If reset is force, set the current page to 1 and stop the force
3042                        if ( self.rollover_running[ rollover_index ].force_reset ) {
3043                            self.rollover_running[ rollover_index ].force_reset = false;
3044                            view_page = 1;
3045                        }
3046                        // Calculate the page to rollover to
3047                        if (
3048                            paged_view_data.effect === 'slideright'
3049                            || paged_view_data.effect === 'slidedown'
3050                        ) {
3051                            // Note that this was deprecated in 2.2, keep for backwards compatibility
3052                            if ( view_page <= 1 ) {
3053                                view_page = paged_view_data.max_pages;
3054                            } else {
3055                                view_page = view_page - 1;
3056                            }
3057                        } else {
3058                            if ( view_page === paged_view_data.max_pages ) {
3059                                view_page = 1;
3060                            } else {
3061                                view_page = view_page + 1;
3062                            }
3063                        }
3064                        // Set the new current page
3065                        self.rollover_running[ rollover_index ].page = view_page;
3066                        WPViews.view_pagination.trigger_pagination( view_number, view_page );
3067                    } else {
3068                        var rollover_index = _.findIndex( self.rollover_running, function ( item ) {
3069                            return item.view_number == view_number;
3070                        });
3071                        self.rollover_running.splice( rollover_index, 1 );
3072                    }
3073                }
3074			}, paged_view_data.speed * 1000 );
3075		} else {
3076			var rollover_index	= _.findIndex( self.rollover_running, function( item ) { 
3077				return item.view_number == view_number; 
3078			});
3079			self.rollover_running.splice( rollover_index, 1 );
3080		}
3081	};
3082	
3083	/**
3084	* init_rollover_timing_callback
3085	*
3086	* Init the rollover event callback, only when there is a View with rollover in a page
3087	*
3088	* @since 2.2
3089	* @since 2.3 Switched from iterating self.rollover_running to iterating a clone of it
3090	*			in order to avoid modification of the iterated array.
3091	*/
3092	
3093	self.init_rollover_timing_callback = function() {
3094		// We are cloning the self.rollover_running array and iterating the clone as we want to avoid modifying
3095		// the array that is been iterated. Remember that self.trigger_rollover removes views from the self.rollover_running
3096		// array, that don't need to be initiated as a rollover, for example when the view has only one page of results.
3097		var rollover_running = self.rollover_running.slice(0);
3098		_.each( rollover_running, function( view_data, index, list ) {
3099			self.trigger_rollover( view_data );
3100		});
3101		self.init_rollover_timing_fired = true;
3102	};
3103	
3104	$( document ).on( 'js_event_wpv_pagination_completed', function( event, data ) {
3105		if ( 
3106			self.get_paged_view( data.view_unique_id ).type == 'rollover' 
3107			&& ! wpv_stop_rollover.hasOwnProperty( data.view_unique_id ) 
3108		) {
3109			var rollover_index = _.findIndex( self.rollover_running, function( item ) { 
3110				return item.view_number == data.view_unique_id; 
3111			});
3112			self.trigger_rollover( self.rollover_running[ rollover_index ] );
3113		}
3114	});
3115	
3116	$( document ).on( 'js_event_wpv_parametric_search_results_updated', function( event, data ) {
3117		if ( 
3118			self.get_paged_view( data.view_unique_id ).type == 'rollover' 
3119			&& ! wpv_stop_rollover.hasOwnProperty( data.view_unique_id ) 
3120		) {
3121			var rollover_index = _.findIndex( self.rollover_running, function( item ) { 
3122				return item.view_number == data.view_unique_id; 
3123			});
3124			self.trigger_rollover( self.rollover_running[ rollover_index ] );
3125		}
3126	});
3127
3128    $( document ).on( 'mouseenter', '.js-wpv-view-layout', function() {
3129        var view_number = $( this ).data( 'viewnumber' );
3130        if ( self.get_paged_view( view_number ).pause_on_hover == 'enabled' ) {
3131            var thiz_rollover_data = {
3132                view_number:	view_number,
3133            };
3134            self.rollover_paused.push( thiz_rollover_data );
3135        }
3136
3137    });
3138
3139    $( document ).on( 'mouseleave', '.js-wpv-view-layout', function() {
3140        var view_number = $( this ).data( 'viewnumber' );
3141        var rollover_index = _.findIndex( self.rollover_paused, function ( item ) {
3142            return item.view_number == view_number;
3143        });
3144        self.rollover_paused.splice( rollover_index, 1 );
3145    });
3146	
3147	/**
3148	* pagination_init_preload_images
3149	*
3150	* Init-preload images.
3151	*
3152	* @since 1.9
3153	*/
3154	
3155	self.init_preload_images = function( container ) {
3156		$( '.js-wpv-layout-preload-images', container ).css( 'visibility', 'hidden' ); // TODO move it to the CSS file and test
3157		$( '.js-wpv-layout-preload-images', container ).each( function() {
3158			var preloadedImages = [],
3159			element = $( this ),
3160			images = element.find( 'img' );
3161			if ( images.length < 1 ) {
3162				element.css( 'visibility', 'visible' );
3163			} else {
3164				images.one( 'load', function() {
3165					preloadedImages.push( $( this ).attr( 'src' ) );
3166					if ( preloadedImages.length === images.length ) {
3167						element.css( 'visibility', 'visible' );
3168					}
3169				}).each( function() {
3170					if( this.complete ) {
3171						$( this ).load();
3172					}
3173				});
3174				setTimeout( function() {
3175					element.css( 'visibility', 'visible' );
3176				}, 3000 );
3177			}
3178		});
3179	};
3180	
3181	self.init_preload_pages = function( container ) {
3182		$( '.js-wpv-layout-preload-pages', container ).each( function() {
3183			var thiz = $( this ),
3184			view_number = thiz.data( 'viewnumber' ),
3185			paged_view_data = self.get_paged_view( view_number ),
3186			max_pages = parseInt( paged_view_data.max_pages, 10 ),
3187			max_reach = parseInt( paged_view_data.preload_reach, 10 ) + 1;
3188			
3189			self.pagination_preload_pages({
3190				view_number:	view_number, 
3191				cache_pages:	'disabled', 
3192				preload_pages:	'enabled', 
3193				page:			1, 
3194				max_reach:		max_reach,
3195				max_pages:		max_pages 
3196			});
3197		});
3198	};
3199	
3200	self.init = function() {
3201		self.init_effects();
3202		self.init_effects_conditions();
3203		self.init_effects_spinner();
3204		// Init Views inside the html
3205		var init_html = $( 'html' );
3206		self.init_paged_views( init_html );
3207		self.init_preload_images( init_html );
3208		self.init_preload_pages( init_html );
3209	}
3210	
3211	self.init();
3212
3213};
3214
3215WPViews.ViewParametricSearch = function( $ ) {
3216	
3217	// ------------------------------------
3218	// Constants and variables
3219	// ------------------------------------
3220	
3221	var self = this;
3222	
3223	// ------------------------------------
3224	// Methods
3225	// ------------------------------------
3226	
3227	self.manage_update_results = function( data ) {
3228		if ( data.ajax_before !== '' ) {
3229			var ajax_before_func = window[data.ajax_before];
3230			if ( typeof ajax_before_func === "function" ) {
3231				ajax_before_func( data.view_num );
3232			}
3233		}
3234		var data_for_events = {};
3235		data_for_events.view_unique_id	= data.view_num;
3236		data_for_events.permalink	= data.permalink;
3237		data.layout.fadeOut( 200, function() {
3238			data.layout.html( data.new_layout.html() )
3239				.attr( 'data-pagination', data.new_layout.attr( 'data-pagination' ) )
3240				.data( 'pagination', data.new_layout.data( 'pagination' ) )
3241				.fadeIn( 'fast', function() {
3242					var ajax_after_func = window[data.ajax_after];
3243					if ( typeof ajax_after_func === "function" ) {
3244						ajax_after_func( data.view_num );
3245					}
3246					data_for_events.layout = data.layout;
3247					$( document ).trigger( 'js_event_wpv_parametric_search_results_updated', [ data_for_events ] );
3248				});		
3249		});
3250	};
3251	
3252	/**
3253	* manage_changed_form
3254	*
3255	* @param settings	object
3256	* 	{
3257	*		view_unique_id:			string			View unique ID
3258	*		form:					collection		Filter jQuery object
3259	* 		force_form_update:		boolean			
3260	* 		update_form				boolean			Whether the form will be updated, either because forced or native
3261	* 		force_results_update:	boolean			
3262	* 		update_results			boolean			Whether the results wil be updated, either because forced or native
3263	*	};
3264	*
3265	* @todo Switch .js-wpv-filter-data-for-this-form into a form data attribute that we can init on document.ready and refresh when neeeded
3266	*
3267	* @since 1.9
3268	* @since 2.1	Merge a group of parameters into an object
3269	*/
3270	
3271	self.manage_changed_form = function( settings ) {
3272		
3273		var fil				= settings.form,
3274		view_num			= settings.view_unique_id,
3275		lay					= $( '#wpv-view-layout-' + view_num ),
3276		full_data			= fil.find( '.js-wpv-filter-data-for-this-form' ),
3277		ajax_pre_before		= full_data.data( 'ajaxprebefore' ),
3278		view_type			= 'full',
3279		additional_forms	= $( '.js-wpv-filter-form-' + view_num ).not( fil ),
3280		additional_forms_only,
3281		additional_forms_full,
3282		ajax_get			= 'both',
3283		new_content_form,
3284		new_content_form_filter,
3285		new_content_full,
3286		new_content_full_filter,
3287		new_content_full_layout,
3288		spinnerContainer	= fil.find( '.js-wpv-dps-spinner' ).add( additional_forms.find( '.js-wpv-dps-spinner' ) ),
3289		spinnerItems		= spinnerContainer.length
3290		data_for_events		= {},
3291		data_for_manage_updated_results	= {};
3292		
3293		data_for_events.view_unique_id	= view_num;
3294		
3295		data_for_manage_updated_results.view_num		= view_num;
3296		data_for_manage_updated_results.ajax_before		= full_data.data( 'ajaxbefore' );
3297		data_for_manage_updated_results.ajax_after		= full_data.data( 'ajaxafter' );
3298		
3299		if ( fil.hasClass( 'js-wpv-form-only' ) ) {
3300			view_type = 'form';
3301		}
3302		if ( settings.update_form ) {
3303			if ( additional_forms.length > 0 ) {
3304				additional_forms_only = additional_forms.not( '.js-wpv-form-full' );
3305				additional_forms_full = additional_forms.not( '.js-wpv-form-only' );
3306				if ( view_type == 'form' ) {
3307					if ( additional_forms_full.length > 0 || settings.update_results ) {
3308						ajax_get = 'both';					
3309					} else {
3310						ajax_get = 'form';
3311					}
3312					if ( settings.update_results ) {
3313						if ( ajax_pre_before !== '' ) {
3314							var ajax_pre_before_func = window[ajax_pre_before];
3315							if ( typeof ajax_pre_before_func === "function" ) {
3316								ajax_pre_before_func( view_num );
3317							}
3318						}
3319						$( document ).trigger( 'js_event_wpv_parametric_search_started', [ data_for_events ] );
3320					}
3321					if ( spinnerItems ) {// TODO maybe only when updating results
3322						$( spinnerContainer ).fadeIn( 'fast' );
3323					}
3324					
3325					wpv_stop_rollover[ view_num ] = true;
3326					
3327					WPViews.view_frontend_utils.get_updated_query_results( view_num, 1, fil, ajax_get )
3328						.done( function( response ) {
3329							if ( response.success ) {
3330								new_content_form = $( '<div></div>' ).append( response.data.form );
3331								new_content_full = $( '<div></div>' ).append( response.data.full );
3332								new_content_form_filter = new_content_form.find( '.js-wpv-filter-form-' + view_num );
3333								new_content_full_filter = new_content_full.find( '.js-wpv-filter-form-' + view_num );
3334								new_content_full_layout = new_content_full.find( '.js-wpv-view-layout-' + view_num );
3335								
3336								fil.html( new_content_form_filter.html() );
3337								WPViews.view_frontend_utils.destroy_frontend_datepicker();
3338								WPViews.view_frontend_utils.clone_form( fil, additional_forms_only );
3339								additional_forms_full.each( function() {
3340									$( this ).html( new_content_full_filter.html() );
3341								});
3342								data_for_events.view_changed_form						= fil;
3343								data_for_events.view_changed_form_additional_forms_only	= additional_forms_only;
3344								data_for_events.view_changed_form_additional_forms_full	= additional_forms_full;
3345								$( document ).trigger( 'js_event_wpv_parametric_search_form_updated', [ data_for_events ] );
3346								if ( settings.update_results ) {
3347									data_for_manage_updated_results.layout			= lay;
3348									data_for_manage_updated_results.new_layout		= new_content_full_layout;
3349									data_for_manage_updated_results.permalink		= response.data['parametric_permalink'];
3350									self.manage_update_results( data_for_manage_updated_results );
3351								}
3352								spinnerContainer.hide();
3353							}
3354						});
3355				} else {
3356					if ( additional_forms_only.length > 0 ) {
3357						ajax_get = 'both';
3358					} else {
3359						ajax_get = 'full';
3360					}
3361					if ( settings.update_results ) {
3362						if ( ajax_pre_before !== '' ) {
3363							var ajax_pre_before_func = window[ajax_pre_before];
3364							if ( typeof ajax_pre_before_func === "function" ) {
3365								ajax_pre_before_func( view_num );
3366							}
3367						}
3368						$( document ).trigger( 'js_event_wpv_parametric_search_started', [ data_for_events ] );
3369					}
3370					if ( spinnerItems ) {// TODO maybe only when updating results
3371						$( spinnerContainer ).fadeIn( 'fast' );
3372					}
3373					
3374					wpv_stop_rollover[ view_num ] = true;
3375					
3376					WPViews.view_frontend_utils.get_updated_query_results( view_num, 1, fil, ajax_get )
3377						.done( function( response ) {
3378							if ( response.success ) {
3379								new_content_form = $( '<div></div>' ).append( response.data.form );
3380								new_content_full = $( '<div></div>' ).append( response.data.full );
3381								new_content_form_filter = new_content_form.find( '.js-wpv-filter-form-' + view_num );
3382								new_content_full_filter = new_content_full.find( '.js-wpv-filter-form-' + view_num );
3383								new_content_full_layout = new_content_full.find( '.js-wpv-view-layout-' + view_num );
3384								
3385								fil.html( new_content_full_filter.html() );
3386								WPViews.view_frontend_utils.destroy_frontend_datepicker();
3387								WPViews.view_frontend_utils.clone_form( fil, additional_forms_full );
3388								additional_forms_only.each( function() {
3389									$( this ).html( new_content_form_filter.html() );
3390								});
3391								data_for_events.view_changed_form						= fil;
3392								data_for_events.view_changed_form_additional_forms_only	= additional_forms_only;
3393								data_for_events.view_changed_form_additional_forms_full	= additional_forms_full;
3394								$( document ).trigger( 'js_event_wpv_parametric_search_form_updated', [ data_for_events ] );
3395								if ( settings.update_results ) {
3396									data_for_manage_updated_results.layout			= lay;
3397									data_for_manage_updated_results.new_layout		= new_content_full_layout;
3398									data_for_manage_updated_results.permalink		= response.data['parametric_permalink'];
3399									self.manage_update_results( data_for_manage_updated_results );
3400								}
3401								spinnerContainer.hide();
3402							}
3403						});
3404				}
3405			} else {
3406				if ( view_type == 'form' ) {
3407					if ( settings.update_results ) {
3408						ajax_get = 'both';
3409						// NOTE this should never happen:
3410						// If change is done on an only-form and there is no extra form, there is no full form thus there is no layout
3411						// WARNING this can be executed on an only-form form from a View with automatic results
3412						// I might want to avoid this branch completely
3413						// NOTE-2 might be a good idea to keep-on-clear// As we might be displaying the layout in non-standard ways
3414						// So keeping the check for lay.length should suffice
3415						
3416					} else {
3417						ajax_get = 'form';
3418					}
3419					
3420					if ( settings.update_results ) {
3421						if ( ajax_pre_before !== '' ) {
3422							var ajax_pre_before_func = window[ajax_pre_before];
3423							if ( typeof ajax_pre_before_func === "function" ) {
3424								ajax_pre_before_func( view_num );
3425							}
3426						}
3427						$( document ).trigger( 'js_event_wpv_parametric_search_started', [ data_for_events ] );
3428					}
3429					if ( spinnerItems ) {// TODO maybe only when updating results
3430						$( spinnerContainer ).fadeIn( 'fast' );
3431					}
3432					
3433					wpv_stop_rollover[ view_num ] = true;
3434					
3435					WPViews.view_frontend_utils.get_updated_query_results( view_num, 1, fil, ajax_get )
3436						.done( function( response ) {
3437							if ( response.success ) {
3438								new_content_form = $( '<div></div>' ).append( response.data.form );
3439								new_content_full = $( '<div></div>' ).append( response.data.full );
3440								new_content_form_filter = new_content_form.find( '.js-wpv-filter-form-' + view_num );
3441								//new_content_full_filter = new_content_full.find( '.js-wpv-filter-form' ).html();
3442								new_content_full_layout = new_content_full.find( '.js-wpv-view-layout-' + view_num );
3443								fil.html( new_content_form_filter.html() );
3444								data_for_events.view_changed_form						= fil;
3445								data_for_events.view_changed_form_additional_forms_only	= additional_forms_only;
3446								data_for_events.view_changed_form_additional_forms_full	= additional_forms_full;
3447								$( document ).trigger( 'js_event_wpv_parametric_search_form_updated', [ data_for_events ] );
3448								if ( settings.update_results ) {
3449									data_for_manage_updated_results.layout			= lay;
3450									data_for_manage_updated_results.new_layout		= new_content_full_layout;
3451									data_for_manage_updated_results.permalink		= response.data['parametric_permalink'];
3452									self.manage_update_results( data_for_manage_updated_results );
3453								}
3454								spinnerContainer.hide();
3455							}
3456						});
3457				} else {
3458					if ( settings.update_results ) {
3459						if ( ajax_pre_before !== '' ) {
3460							var ajax_pre_before_func = window[ajax_pre_before];
3461							if ( typeof ajax_pre_before_func === "function" ) {
3462								ajax_pre_before_func( view_num );
3463							}
3464						}
3465						$( document ).trigger( 'js_event_wpv_parametric_search_started', [ data_for_events ] );
3466					}
3467					if ( spinnerItems ) {// TODO maybe only when updating results
3468						$( spinnerContainer ).fadeIn( 'fast' );
3469					}
3470					
3471					wpv_stop_rollover[ view_num ] = true;
3472					
3473					WPViews.view_frontend_utils.get_updated_query_results( view_num, 1, fil, 'full' )
3474						.done( function( response ) {
3475							if ( response.success ) {
3476								//new_content_form = $( '<div></div>' ).append( ajax_result.form );
3477								new_content_full = $( '<div></div>' ).append( response.data.full );
3478								//new_content_form_filter = new_content_form.find( '.js-wpv-filter-form' ).html();
3479								new_content_full_filter = new_content_full.find( '.js-wpv-filter-form-' + view_num );
3480								new_content_full_layout = new_content_full.find( '.js-wpv-view-layout-' + view_num );
3481								fil.html( new_content_full_filter.html() );
3482								data_for_events.view_changed_form						= fil;
3483								data_for_events.view_changed_form_additional_forms_only	= additional_forms_only;
3484								data_for_events.view_changed_form_additional_forms_full	= additional_forms_full;
3485								$( document ).trigger( 'js_event_wpv_parametric_search_form_updated', [ data_for_events ] );
3486								if ( settings.update_results ) {
3487									data_for_manage_updated_results.layout			= lay;
3488									data_for_manage_updated_results.new_layout		= new_content_full_layout;
3489									data_for_manage_updated_results.permalink		= response.data['parametric_permalink'];
3490									self.manage_update_results( data_for_manage_updated_results );
3491								}
3492								spinnerContainer.hide();
3493							}
3494						});
3495				}
3496			}
3497		} else {
3498			if ( additional_forms.length > 0 ) {
3499				additional_forms_only = additional_forms.not( '.js-wpv-form-full' );
3500				additional_forms_full = additional_forms.not( '.js-wpv-form-only' );
3501				if ( view_type == 'form' ) {
3502					WPViews.view_frontend_utils.destroy_frontend_datepicker();
3503					WPViews.view_frontend_utils.clone_form( fil, additional_forms_only );
3504					if ( additional_forms_full.length > 0 || settings.update_results ) {
3505						if ( settings.update_results ) {
3506							if ( ajax_pre_before !== '' ) {
3507								var ajax_pre_before_func = window[ajax_pre_before];
3508								if ( typeof ajax_pre_before_func === "function" ) {
3509									ajax_pre_before_func( view_num );
3510								}
3511							}
3512							$( document ).trigger( 'js_event_wpv_parametric_search_started', [ data_for_events ] );
3513						}
3514						if ( spinnerItems ) {// TODO maybe only when updating results
3515							$( spinnerContainer ).fadeIn( 'fast' );
3516						}
3517						
3518						wpv_stop_rollover[ view_num ] = true;
3519						
3520						WPViews.view_frontend_utils.get_updated_query_results( view_num, 1, fil, 'full' )
3521							.done( function( response ) {
3522								if ( response.success ) {
3523									//new_content_form = $( '<div></div>' ).append( response.data.form );
3524									new_content_full = $( '<div></div>' ).append( response.data.full );
3525									//new_content_form_filter = new_content_form.find( '.js-wpv-filter-form' ).html();
3526									new_content_full_filter = new_content_full.find( '.js-wpv-filter-form-' + view_num );
3527									new_content_full_layout = new_content_full.find( '.js-wpv-view-layout-' + view_num );
3528									
3529									additional_forms_full.each( function() {
3530										$( this ).html( new_content_full_filter.html() );
3531									});
3532									data_for_events.view_changed_form						= fil;
3533									data_for_events.view_changed_form_additional_forms_only	= additional_forms_only;
3534									data_for_events.view_changed_form_additional_forms_full	= additional_forms_full;
3535									$( document ).trigger( 'js_event_wpv_parametric_search_form_updated', [ data_for_events ] );
3536									if ( settings.update_results ) {
3537										data_for_manage_updated_results.layout			= lay;
3538										data_for_manage_updated_results.new_layout		= new_content_full_layout;
3539										data_for_manage_updated_results.permalink		= response.data['parametric_permalink'];
3540										self.manage_update_results( data_for_manage_updated_results );
3541									}
3542									spinnerContainer.hide();
3543								}
3544							});
3545					} else {
3546						data_for_events.view_changed_form						= fil;
3547						data_for_events.v
3547iew_changed_form_additional_forms_only	= additional_forms_only;
3548						data_for_events.view_changed_form_additional_forms_full	= additional_forms_full;
3549						$( document ).trigger( 'js_event_wpv_parametric_search_form_updated', [ data_for_events ] );
3550					}
3551				} else {
3552					WPViews.view_frontend_utils.destroy_frontend_datepicker();
3553					WPViews.view_frontend_utils.clone_form( fil, additional_forms_full );
3554					WPViews.view_frontend_utils.render_frontend_datepicker();
3555					if ( additional_forms_only.length > 0 || settings.update_results ) {
3556						if ( additional_forms_only.length > 0 ) {
3557							ajax_get = 'both';
3558						} else {
3559							ajax_get = 'full';
3560						}
3561						
3562						if ( settings.update_results ) {
3563							if ( ajax_pre_before !== '' ) {
3564								var ajax_pre_before_func = window[ajax_pre_before];
3565								if ( typeof ajax_pre_before_func === "function" ) {
3566									ajax_pre_before_func( view_num );
3567								}
3568							}
3569							$( document ).trigger( 'js_event_wpv_parametric_search_started', [ data_for_events ] );
3570						}
3571						if ( spinnerItems ) {// TODO maybe only when updating results
3572							$( spinnerContainer ).fadeIn( 'fast' );
3573						}
3574						
3575						wpv_stop_rollover[ view_num ] = true;
3576						
3577						WPViews.view_frontend_utils.get_updated_query_results( view_num, 1, fil, ajax_get )
3578							.done( function( response ) {
3579								if ( response.success ) {
3580									new_content_form = $( '<div></div>' ).append( response.data.form );
3581									new_content_full = $( '<div></div>' ).append( response.data.full );
3582									new_content_form_filter = new_content_form.find( '.js-wpv-filter-form-' + view_num );
3583									//new_content_full_filter = new_content_full.find( '.js-wpv-filter-form' ).html();
3584									new_content_full_layout = new_content_full.find( '.js-wpv-view-layout-' + view_num );
3585									additional_forms_only.each( function() {
3586										$( this ).html( new_content_form_filter.html() );
3587									});
3588									data_for_events.view_changed_form						= fil;
3589									data_for_events.view_changed_form_additional_forms_only	= additional_forms_only;
3590									data_for_events.view_changed_form_additional_forms_full	= additional_forms_full;
3591									$( document ).trigger( 'js_event_wpv_parametric_search_form_updated', [ data_for_events ] );
3592									if ( settings.update_results ) {
3593										data_for_manage_updated_results.layout			= lay;
3594										data_for_manage_updated_results.new_layout		= new_content_full_layout;
3595										data_for_manage_updated_results.permalink		= response.data['parametric_permalink'];
3596										self.manage_update_results( data_for_manage_updated_results );
3597									}
3598									spinnerContainer.hide();
3599								}
3600							});
3601					}
3602				}
3603			} else {
3604				if ( settings.update_results ) {
3605					if ( ajax_pre_before !== '' ) {
3606						var ajax_pre_before_func = window[ajax_pre_before];
3607						if ( typeof ajax_pre_before_func === "function" ) {
3608							ajax_pre_before_func( view_num );
3609						}
3610					}
3611					$( document ).trigger( 'js_event_wpv_parametric_search_started', [ data_for_events ] );
3612					if ( spinnerItems ) {// TODO maybe only when updating results
3613						$( spinnerContainer ).fadeIn( 'fast' );
3614					}
3615					
3616					wpv_stop_rollover[ view_num ] = true;
3617					
3618					WPViews.view_frontend_utils.get_updated_query_results( view_num, 1, fil, 'full' )
3619						.done( function( response ) {
3620							if ( response.success ) {
3621								//new_content_form = $( '<div></div>' ).append( response.data.form );
3622								new_content_full = $( '<div></div>' ).append( response.data.full );
3623								//new_content_form_filter = new_content_form.find( '.js-wpv-filter-form' ).html();
3624								//new_content_full_filter = new_content_full.find( '.js-wpv-filter-form' ).html();
3625								new_content_full_layout = new_content_full.find( '.js-wpv-view-layout-' + view_num );
3626								data_for_manage_updated_results.layout			= lay;
3627								data_for_manage_updated_results.new_layout		= new_content_full_layout;
3628								data_for_manage_updated_results.permalink		= response.data['parametric_permalink'];
3629								self.manage_update_results( data_for_manage_updated_results );
3630								spinnerContainer.hide();
3631							}
3632						});
3633				}
3634			}
3635		}
3636	};
3637	
3638	/**
3639	* Normalize the data passed to the js_event_wpv_parametric_search_triggered event.
3640	*
3641	* @para data	Object
3642	* 	{
3643	*		view_unique_id:			string			View unique ID
3644	*		form:					collection		Filter jQuery object
3645	* 		force_form_update:		boolean			Optional
3646	* 		force_results_update:	boolean			Optional
3647	*	};
3648	*
3649	* @return settings	Object
3650	* 	{
3651	*		view_unique_id:			string			View unique ID
3652	*		form:					collection		Filter jQuery object
3653	* 		force_form_update:		boolean			
3654	* 		update_form				boolean			Whether the form will be updated, either because forced or native
3655	* 		force_results_update:	boolean			
3656	* 		update_results			boolean			Whether the results wil be updated, either because forced or native
3657	*	};
3658	*
3659	* @since 2.1
3660	*/
3661	
3662	self.extend_wpv_parametric_search_triggered_data = function( data ) {
3663		var defaults	= { 
3664			force_form_update:		false, 
3665			force_results_update:	false
3666		},
3667		settings		= $.extend( {}, defaults, data ),
3668		view_loop		= $( '#wpv-view-layout-' + settings.view_unique_id );
3669		
3670		if (
3671			settings.force_form_update == false 
3672			&& (
3673				// The form contains a post relationship filter, hence it really needs to be updated
3674				settings.form.find( '.js-wpv-post-relationship-update' ).length > 0
3675				|| (
3676					// The form contains pagination settings and the results are set to be updated
3677					(
3678						settings.force_results_update == true 
3679						|| settings.form.hasClass( 'js-wpv-ajax-results-enabled' ) 
3680					) && _.has( WPViews.view_pagination.paged_views, settings.view_unique_id ) 
3681					&& _.has( WPViews.view_pagination.paged_views[ settings.view_unique_id ], 'has_controls_in_form' )
3682			&& WPViews.view_pagination.paged_views[ settings.view_unique_id ].has_controls_in_form == 'enabled'
3683				)
3684			)
3685		) {
3686			settings.force_form_update = true;
3687		}
3688		
3689		settings.update_form	= ( settings.force_form_update || settings.form.hasClass( 'js-wpv-dps-enabled' ) );
3690		settings.update_results	= ( view_loop.length > 0 && ( settings.force_results_update || settings.form.hasClass( 'js-wpv-ajax-results-enabled' ) ) );
3691		
3692		return settings;
3693	};
3694	
3695	// ------------------------------------
3696	// Events
3697	// ------------------------------------
3698	
3699	// Show datepicker on date string click
3700	$( document ).on( 'click', '.js-wpv-date-display', function() {
3701		var url_param = $( this ).data( 'param' );
3702		$( '.js-wpv-date-front-end-' + url_param ).datepicker( 'show' );
3703	});
3704
3705	// Remove current selected date
3706	$( document ).on( 'click', '.js-wpv-date-front-end-clear', function(e) {
3707		e.preventDefault();
3708		var thiz = $( this ),
3709		url_param = thiz.data( 'param' ),
3710		form = thiz.closest( 'form' );
3711		form.find( '.js-wpv-date-param-' + url_param ).html( '' );
3712		form.find( '.js-wpv-date-front-end-' + url_param ).val( '' );
3713		thiz.hide();
3714		form.find('.js-wpv-date-param-' + url_param + '-value' )
3715			.val( '' )
3716			.trigger( 'change' );
3717	});
3718	
3719	$( document ).on( 'change', '.js-wpv-post-relationship-update', function() {
3720		var thiz = $( this ),
3721		fil = thiz.closest( 'form' ),
3722		view_number = fil.data( 'viewnumber' ),
3723		additional_forms = $( '.js-wpv-filter-form-' + view_number ).not( fil ),
3724		currentposttype = thiz.data( 'currentposttype' ),
3725		watchers = fil.find( '.js-wpv-' + currentposttype + '-watch' ).add( additional_forms.find( '.js-wpv-' + currentposttype + '-watch' ) ),
3726		watcherslength = watchers.length,
3727		i;
3728		if ( watcherslength ) {
3729			for( i = 0; i < watcherslength; i++ ) {
3730				$( watchers[i] )
3731					.attr( 'disabled', true )
3732					.removeAttr( 'checked' )
3733					.removeAttr( 'selected' )
3734					.not( ':button, :submit, :reset, :hidden, :radio, :checkbox' )
3735					.val( '0' );
3736			}
3737		}
3738		
3739		var data_for_events = {
3740			view_unique_id:		view_number,
3741			form:				fil,
3742			force_form_update:	true
3743		};
3744		
3745		data_for_events = self.extend_wpv_parametric_search_triggered_data( data_for_events );
3746		
3747		$( document ).trigger( 'js_event_wpv_parametric_search_triggered', [ data_for_events ] );
3748	});
3749
3750	$( document ).on( 'change', '.js-wpv-filter-trigger', function() {
3751		var thiz = $( this ),
3752		fil = thiz.closest( 'form' ),
3753		view_number = fil.data( 'viewnumber' );
3754		
3755		var data_for_events = {
3756			view_unique_id:	view_number,
3757			form:			fil
3758		};
3759		
3760		data_for_events = self.extend_wpv_parametric_search_triggered_data( data_for_events );
3761		
3762		$( document ).trigger( 'js_event_wpv_parametric_search_triggered', [ data_for_events ] );
3763	});
3764
3765	$( document ).on( 'click', '.js-wpv-ajax-results-enabled .js-wpv-submit-trigger, .js-wpv-ajax-results-submit-enabled .js-wpv-submit-trigger', function( e ) {
3766		e.preventDefault();
3767		var thiz = $( this ),
3768		fil = thiz.closest( 'form' ),
3769		view_number = fil.data( 'viewnumber' );
3770		
3771		var data_for_events = {
3772			view_unique_id:			view_number,
3773			form:					fil,
3774			force_form_update:		false,
3775			force_results_update:	true
3776		};
3777		
3778		data_for_events = self.extend_wpv_parametric_search_triggered_data( data_for_events );
3779		
3780		$( document ).trigger( 'js_event_wpv_parametric_search_triggered', [ data_for_events ] );
3781	});
3782
3783	$( document).on( 'keypress', '.js-wpv-ajax-results-enabled .js-wpv-filter-trigger-delayed, .js-wpv-ajax-results-submit-enabled .js-wpv-filter-trigger-delayed', function( e ) {
3784		// Enter pressed?
3785		if ( e.which == 13 ) {
3786			e.preventDefault();
3787			var thiz = $( this ),
3788			fil = thiz.closest( 'form' ),
3789			view_number = fil.data( 'viewnumber' );
3790			
3791			var data_for_events = {
3792				view_unique_id:			view_number,
3793				form:					fil,
3794				force_results_update:	true
3795			};
3796			
3797			data_for_events = self.extend_wpv_parametric_search_triggered_data( data_for_events );
3798			
3799			$( document ).trigger( 'js_event_wpv_parametric_search_triggered', [ data_for_events ] );
3800		}
3801	});
3802
3803	$( document ).on( 'click', '.js-wpv-reset-trigger', function( e ) {
3804		e.preventDefault();
3805		var thiz = $( this ),
3806		fil = thiz.closest( 'form' ),
3807		view_number = fil.data( 'viewnumber' ),
3808		additional_forms = $( '.js-wpv-filter-form-' + view_number ).not( fil ),
3809		watchers,
3810		watcherslength,
3811		i,
3812		target = fil.attr( 'action' ),
3813		form_only_force_update = false,
3814		form_only_results_force_update = false;
3815		
3816		if ( fil.hasClass( 'js-wpv-form-only' ) ) {
3817			watchers = fil.find( 'input, select' ).add( additional_forms.find( 'input, select' ) );
3818			watcherslength = watchers.length;
3819			form_only_force_update = ( fil.hasClass( 'js-wpv-dps-enabled' ) || ( fil.find( '.js-wpv-post-relationship-update' ).length > 0 ) );
3820			if (
3821				fil.hasClass( 'js-wpv-ajax-results-enabled' ) 
3822				|| fil.hasClass( 'js-wpv-ajax-results-submit-enabled' )
3823			) {
3824				form_only_results_force_update = true;
3825			}
3826			
3827			if ( watcherslength ) {
3828				for ( i = 0; i < watcherslength; i++ ) {
3829					if ( ! $( watchers[i] ).hasClass( 'js-wpv-keep-on-clear' ) ) {
3830						$( watchers[i] )
3831							.attr( 'disabled', form_only_force_update )
3832							.removeAttr( 'checked' )
3833							.removeAttr( 'selected' )
3834							.not( ':button, :submit, :reset, :hidden, :radio, :checkbox' )
3835							.val( '' );
3836					}
3837				}
3838			}
3839			
3840			var data_for_events = {
3841				view_unique_id:			view_number,
3842				form:					fil,
3843				force_form_update:		form_only_force_update,
3844				force_results_update:	form_only_results_force_update
3845			};
3846			
3847			data_for_events = self.extend_wpv_parametric_search_triggered_data( data_for_events );
3848			
3849			if( ! form_only_results_force_update && $( '#wpv-view-layout-' + fil.data( 'viewnumber' ) ).length > 0 ) {
3850                window.location.href = target;
3851			}
3852			else {
3853                $( document ).trigger( 'js_event_wpv_parametric_search_triggered', [ data_for_events ] );
3854			}
3855
3856		} else if ( fil.hasClass( 'js-wpv-ajax-results-enabled' ) || fil.hasClass( 'js-wpv-ajax-results-submit-enabled' ) ) {
3857			watchers = fil.find( 'input, select' ).add( additional_forms.find( 'input, select' ) );
3858			watcherslength = watchers.length;
3859			if ( watcherslength ) {
3860				for ( i = 0; i < watcherslength; i++ ) {
3861					if ( ! $( watchers[i] ).hasClass( 'js-wpv-keep-on-clear' ) ) {
3862						$( watchers[i] )
3863							.attr( 'disabled', true )
3864							.removeAttr( 'checked' )
3865							.removeAttr( 'selected' )
3866							.not( ':button, :submit, :reset, :hidden, :radio, :checkbox' )
3867							.val( '' );
3868					}
3869				}
3870			}
3871			
3872			var data_for_events = {
3873				view_unique_id:			view_number,
3874				form:					fil,
3875				force_form_update:		true,
3876				force_results_update:	true
3877			};
3878			
3879			data_for_events = self.extend_wpv_parametric_search_triggered_data( data_for_events );
3880			
3881			$( document ).trigger( 'js_event_wpv_parametric_search_triggered', [ data_for_events ] );
3882		} else {
3883            window.location.href = WPViews.view_frontend_utils.updateUrlQuery( 'wpv_view_count', null, target );
3884		}
3885	});
3886	
3887	$( document ).on( 'js_event_wpv_parametric_search_triggered', function( event, settings ) {
3888		self.manage_changed_form( settings );
3889	});
3890
3891	// Also, stop the rollover if we do any modification on the parametric search form
3892
3893	$( document ).on( 'change', '.js-wpv-filter-trigger, .js-wpv-filter-trigger-delayed', function() {
3894		var thiz = $( this ),
3895		fil = thiz.closest( 'form' ),
3896		view_num = fil.data( 'viewnumber' );
3897		wpv_stop_rollover[view_num] = true;
3898	});
3899	
3900	// ------------------------------------
3901	// Custom events
3902	// ------------------------------------
3903	
3904	/**
3905	* js_event_wpv_parametric_search_started
3906	*
3907	* Event fired before updating the parametric search forms and results.
3908	*
3909	* @param data
3910	* 	- view_unique_id
3911	*
3912	* @since 1.9
3913	*/
3914	
3915	$( document ).on( 'js_event_wpv_parametric_search_started', function( event, data ) {
3916		
3917	});
3918	
3919	
3920	/**
3921	* js_event_wpv_parametric_search_form_updated
3922	*
3923	* Event fired after updating the parametric search forms.
3924	*
3925	* @param data
3926	* 	- view_unique_id
3927	* 	- view_changed_form
3928	* 	- view_changed_form_additional_forms_only
3929	* 	- view_changed_form_additional_forms_full
3930	*
3931	* @since 1.9
3932	*/
3933	
3934	$( document ).on( 'js_event_wpv_parametric_search_form_updated', function( event, data ) {
3935		WPViews.view_frontend_utils.render_frontend_datepicker();
3936	});
3937	
3938	/**
3939	* js_event_wpv_parametric_search_results_updated
3940	*
3941	* Event fired after updating the parametric search results.
3942	*
3943	* @param data
3944	* 	- view_unique_id
3945	* 	- layout
3946	*
3947	* @since 1.9
3948	*/
3949	
3950	$( document ).on( 'js_event_wpv_parametric_search_results_updated', function( event, data ) {
3951		WPViews.view_frontend_utils.render_frontend_media_shortcodes( data.layout );
3952	});
3953	
3954	// ------------------------------------
3955	// Init
3956	// ------------------------------------
3957	
3958	self.init = function() {
3959		
3960	}
3961	
3962	self.init();
3963
3964};
3965
3966jQuery( document ).ready( function( $ ) {
3967	WPViews.view_frontend_utils = new WPViews.ViewFrontendUtils( $ );
3968	WPViews.view_sorting = new WPViews.ViewSorting( $ );
3969	WPViews.view_pagination = new WPViews.ViewPagination( $ );
3970    WPViews.view_parametric_search = new WPViews.ViewParametricSearch( $ );
3971});

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.