PageSourceSearch

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

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

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.