/***************************************************************************
 *
 * 	----------------------------------------------------------------------
 * 						DO NOT EDIT THIS FILE
 *	----------------------------------------------------------------------
 *                      Theme Customizer Scripts
 *  				    Copyright (C) Themify
 *
 *	----------------------------------------------------------------------
 *
 ***************************************************************************/
(function (exports, $) {

	'use strict';
	/**
	 * Parse JSON string and returns object.
	 *
	 * If parse fails returns an empty object instead of throwing errors.
	 */
	function parseJSON( data ) {
		try {
			data = JSON.parse( data );
		}
		catch( error ) {
			data = {};
		}

		return data;
	}


	// Google Font Loader for fonts preview
	var wf = document.createElement('script'),
            s = document.getElementsByTagName('script')[0];
	wf.src = ('https:' == document.location.protocol ? 'https' : 'http') + '://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js';
	wf.type = 'text/javascript';
	wf.async = 'true';
	s.parentNode.insertBefore(wf, s);
	var api = wp.customize,
		initialLoad = true;

	window.onbeforeunload = function () {
		if (!wp.customize.state('saved')()) {
			return themifyCustomizerControls.confirm_on_unload;
		}
	};

	function GetPrev( $this ) {
		var $prev = $this.prev( 'li' );
		return $prev.length > 0 && $prev.children( '.themify-control-title' ).length === 0
			? GetPrev($prev)
			: $prev.index();
	}

	api.bind( 'pane-contents-reflowed', function() {
		$( '.themify-subaccordion' ).each( function() {
			var $self = $( this ),
			thisGroup = $self.data( 'accordion' ),
			$li = $( '.' + thisGroup + '-group' );

			if( $li.is( '#customize-control-customcss_ctrl' ) ) {
				var scrollTop = $li.find( '.CodeMirror-scroll' ).scrollTop(),
					cm = $li.find( '.CodeMirror' ).get(0);
				$li.appendTo( $self );

				if( 'undefined' !== typeof cm && 'CodeMirror' in cm ) {
					cm.CodeMirror.focus();
					cm.CodeMirror.scrollTo( 0, scrollTop );
				}
			} else {
				$li.appendTo( $self );
			}
			
			var reverse = $( $li.get().reverse() );
			reverse.each( function() {
				if( $(this).children( '.themify-control-title' ).length === 0 ) {
					var $start_index = GetPrev( $( this ) );
					$( this ).appendTo( $li.eq( $start_index )
						.children( '.themify-control-sub-accordeon' ).first() );
				}
			});
		});

		$( 'li[id*="nav_menu_locations"]' ).each( function() {
			$( this ).appendTo( $( this ).prev().find( '.themify-subaccordion' ) );
		});

		if( initialLoad ) {
			$( '#accordion-section-themify_options:visible' ).find( '.accordion-section-title' ).trigger( 'click' );

			$( '.themify-suba-toggle.themify-control-title' ).off( 'click' ).on( 'click', function( e ) {
				e.preventDefault();
				var $sub_accordeon = $( this ).closest( 'li' ).find( '.themify-control-sub-accordeon' );
				if( $( this ).hasClass( 'topen' ) ) {
					$( this ).removeClass( 'topen' );
					$sub_accordeon.slideUp();
				} else {
					$( this ).addClass( 'topen' );
					$sub_accordeon.slideDown();
				}
			} );

			$('.themify-control-sub-accordeon').hide();

			$( 'body' ).on( 'mouseover', '.devices [data-device]', function( e ) {
				var $title = '' + $( this ).data( 'device' ).replace( '_', ' ' );
				$( this ).append( '<span class="themify_customize_tooltip">' + $title + '</span>' );
			} ).on( 'mouseout', '.devices [data-device]', function( e ) {
				$(this).children('.themify_customize_tooltip').remove();
			});

			$.event.trigger( "themify_customizer_ready" );

			initialLoad = false;
		}
	} );

	////////////////////////////////////////////////////////////////////////////
	// Accordion Start
	////////////////////////////////////////////////////////////////////////////
	api.ThemifySubAccordion = api.Control.extend({
		ready() {
			var control = this,
					$a = $('.themify-suba-toggle', control.container),
					$ul = $a.next();

			$('.customize-control.customize-control-themify_subaccordion_end').remove();

			$a.on('click', function (e) {
				e.preventDefault();
				$(this).parent().toggleClass('topen');
				$ul.toggleClass('tpanelopen');
				
				if($ul.hasClass('tpanelopen')){ 
					$ul.slideDown();
				}
				else{ 
					$ul.slideUp();
				}
			});

			var $navMenu = $('select[data-customize-setting-link^="nav_menu_locations"]', control.container);
			$navMenu.closest('label').map(function () {
				$(this).replaceWith($(this).contents());
			});
			$navMenu.wrap('<div class="themify-customizer-brick" />').wrap('<div class="custom-select nav-menu-select" />');
		}
	});
	api.controlConstructor.themify_subaccordion_start = api.ThemifySubAccordion;
	////////////////////////////////////////////////////////////////////////////
	// Accordion End
	////////////////////////////////////////////////////////////////////////////

	/***************************************************************************
	 *                      ThemifyControl Start
	 *
	 * This Model serves as a foundation to derive the other controls.
	 * When initializing an inherited Model, the ready() method must be defined.
	 ***************************************************************************/
	api.ThemifyControl = api.Control.extend({
		value: {},
		/**
		 * This property must be defined in inherited models.
		 * Must be set to the class of the hidden text field that stores the settings.
		 * Example: .themify_background_control
		 */
		field: '',
		openMedia() {
			var control = this, $field = $(control.field, control.container),
					file_frame = '';

			$('.open-media', control.container).on('click', function (e) {
				e.preventDefault();

				file_frame = wp.media.frames.file_frame = wp.media({
					title: $(this).data('uploader-title'),
					library: {
						type: ['image']
					},
					button: {
						text: $(this).data('uploader-button-text')
					},
					multiple: false
				});

				file_frame.on('select', function () {
					var attachment = file_frame.state().get('selection').first().toJSON(),

                                        $imgPreview = $('<a href="#" class="remove-image tf_close"></a><img src="' + attachment.url + '" />').css('display', 'inline-block'),

                                        $preview = $('.themify_control_preview', control.container),
							$close = $('a', $preview),
							$imgPre = $('img', $preview);

					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()].id = attachment.id;
						control.value[control.id][control.getCurrentDevice()].src = attachment.url;
					} else {
						control.value[control.id].id = attachment.id;
						control.value[control.id].src = attachment.url;
					}

					$field.val(JSON.stringify(control.value[control.id])).trigger('change');

					if ($close.length > 0) {
						$close.remove();
					}
					if ($imgPre.length > 0) {
						$imgPre.remove();
					}

					$preview.append($imgPreview).fadeIn();
				});

				file_frame.open();
			});

			// Remove image
			$('.open-media-wrap', control.container).on('click', '.remove-image', function (e) {
				e.preventDefault();

				if ( control.isResponsiveStyling() ) {
					if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
						control.value[control.id][control.getCurrentDevice()] = {};
					
					//control.value[control.id][control.getCurrentDevice()] = _.omit( control.value[control.id][control.getCurrentDevice()], ['id', 'src'] );
					control.value[control.id][control.getCurrentDevice()].id = '';
					control.value[control.id][control.getCurrentDevice()].src = '';
				} else {
					control.value[control.id].id = '';
					control.value[control.id].src = '';
				}
				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
				$(this).next().remove();
				$(this).remove();
			});
		},
		pickColor() {
			const control = this, $field = $(control.field, control.container),
					$color = $('.color-select', control.container),
					$removeColor = $('.remove-color', control.container);
            let index = 0; 
			// Color Picker
			$color.tfminicolors({
				defaultValue: '',
				letterCase: 'lowercase',
				opacity: true,
				swatches: themifyColorManager.toColorsArray(),
				show() {
					themifyColorManager.initColorPicker(this);
					const $self = $(this);
					if ($self.closest('li').is(':last-child')) {
						$self.closest('.color-picker').addClass('color-picker-visible');
					}
				},
				change(hex, opacity) {
                                        if(control.id==='headerwrap_background_ctrl' && themifyCustomizerControls.header_transparnet && index<1){
                                            alert(themifyCustomizerControls.header_transparnet);
                                            index++;
                                        }
					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()].color = hex.replace('#', '');
						control.value[control.id][control.getCurrentDevice()].opacity = opacity;
					} else {
						control.value[control.id].color = hex.replace('#', '');
						control.value[control.id].opacity = opacity;
					}
					$field.val(JSON.stringify(control.value[control.id])).trigger('change');
					$removeColor.show();
                                        
				},
				hide() {
					if ('' != $(this).val()) {
						if ( control.isResponsiveStyling() ) {
							if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
								control.value[control.id][control.getCurrentDevice()] = {};

							control.value[control.id][control.getCurrentDevice()].color = $(this).val().replace('#', '');
						} else {
							control.value[control.id].color = $(this).val().replace('#', '');
						}
						$field.val(JSON.stringify(control.value[control.id])).trigger('change');
						$removeColor.show();
					}
					const $self = $(this);
					if ($self.closest('li').is(':last-child')) {
						$self.closest('.color-picker').removeClass('color-picker-visible');
					}
				}
			});
			// Clear color field
			$removeColor.on('click', function (e) {
				e.preventDefault();
				if ( control.isResponsiveStyling() ) {
					if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
						control.value[control.id][control.getCurrentDevice()] = {};

					control.value[control.id][control.getCurrentDevice()] = _.omit( control.value[control.id][control.getCurrentDevice()], 'color' );
					control.value[control.id][control.getCurrentDevice()] = _.omit( control.value[control.id][control.getCurrentDevice()], 'opacity' );
				} else {
					control.value[control.id] = _.omit( control.value[control.id], 'color' );
					control.value[control.id] = _.omit( control.value[control.id], 'opacity' );  
				}
				
				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
				$color.tfminicolors('value', '');
				$color.tfminicolors('opacity', '');
				$removeColor.hide();
			});
		},
		pickBorderColor() {
			const control = this, $field = $(control.field, control.container),
					$color = $('.color-select', control.container),
					$removeColor = $('.remove-color', control.container),
					$same = $('.same', control.container);

			// Color Picker
			$color.tfminicolors({
				defaultValue: '',
				letterCase: 'lowercase',
				opacity: true,
				swatches: themifyColorManager.toColorsArray(),
				change(hex, opacity) {
					var side = $(this).data('side'),
							color = hex.replace('#', '');
					if ($same.prop('checked')) {
						if ( control.isResponsiveStyling() ) {
							if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
								control.value[control.id][control.getCurrentDevice()] = {};

							control.value[control.id][control.getCurrentDevice()].color = color;
							control.value[control.id][control.getCurrentDevice()].opacity = opacity;
							control.value[control.id][control.getCurrentDevice()].same = 'same';
						} else {
							control.value[control.id].color = color;
							control.value[control.id].opacity = opacity;
							control.value[control.id].same = 'same';
						}
					} else {

						if ( control.isResponsiveStyling() ) {
							if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
								control.value[control.id][control.getCurrentDevice()] = {};

							control.value[control.id][control.getCurrentDevice()][side] = _.extend({}, control.value[control.id][control.getCurrentDevice()][side], {
								'color': color,
								'opacity': opacity
							});
							if ('top' === side) {
								control.value[control.id][control.getCurrentDevice()].color = color;
								control.value[control.id][control.getCurrentDevice()].opacity = opacity;
							}
							control.value[control.id][control.getCurrentDevice()].same = '';
						} else {

							control.value[control.id][side] = _.extend({}, control.value[control.id][side], {
								'color': color,
								'opacity': opacity
							});
							if ('top' === side) {
								control.value[control.id].color = color;
								control.value[control.id].opacity = opacity;
							}
							control.value[control.id].same = '';
						}
					}
					control.setting.set('{}', {silent: true});
					$field.val(JSON.stringify(control.value[control.id])).trigger('change');
					$(this).parent().next().show();
				},
				hide() {
					if ($(this).val()) {
						var hex = $(this).val(),
								side = $(this).data('side'),
								color = hex.replace('#', '');
						if ($same.prop('checked')) {
							if ( control.isResponsiveStyling() ) {
								if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
									control.value[control.id][control.getCurrentDevice()] = {};

								control.value[control.id][control.getCurrentDevice()].color = color;
								control.value[control.id][control.getCurrentDevice()].same = 'same';
							} else {
								control.value[control.id].color = color;
								control.value[control.id].same = 'same';
							}
						} else {
							if ( control.isResponsiveStyling() ) {
								if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
									control.value[control.id][control.getCurrentDevice()] = {};

								control.value[control.id][control.getCurrentDevice()][side] = _.extend({}, control.value[control.id][control.getCurrentDevice()][side], {
									'color': color
								});
								if ('top' === side) {
									control.value[control.id][control.getCurrentDevice()].color = color;
								}
								control.value[control.id][control.getCurrentDevice()].same = '';
							} else {
								control.value[control.id][side] = _.extend({}, control.value[control.id][side], {
									'color': color
								});
								if ('top' === side) {
									control.value[control.id].color = color;
								}
								control.value[control.id].same = '';
							}
						}
						$field.val(JSON.stringify(control.value[control.id])).trigger('change');
						$(this).parent().next().show();
					}
				},
				show(){
					themifyColorManager.initColorPicker(this);
				}
			});
			// Clear color field
			$removeColor.on('click', function (e) {
				e.preventDefault();
				const side = $(this).data('side');

				if ($same.prop('checked')) {
					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};

						control.value[control.id][control.getCurrentDevice()] = _.omit( control.value[control.id][control.getCurrentDevice()], ['color', 'opacity'] ); 
						control.value[control.id][control.getCurrentDevice()].same = 'same';
					} else {
						control.value[control.id].color = '';
						control.value[control.id].opacity = '';
						control.value[control.id].same = 'same';
					}
				} else {

					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};

						control.value[control.id][control.getCurrentDevice()][side] = _.extend({}, control.value[control.id][control.getCurrentDevice()][side], {
							'color': '',
							'opacity': ''
						});
						if ('top' === side) {
							control.value[control.id][control.getCurrentDevice()] = _.omit( control.value[control.id][control.getCurrentDevice()], ['color', 'opacity']);
						}
						control.value[control.id][control.getCurrentDevice()].same = '';
					} else {
						control.value[control.id][side] = _.extend({}, control.value[control.id][side], {
							'color': '',
							'opacity': ''
						});
						if ('top' === side) {
							control.value[control.id].color = '';
							control.value[control.id].opacity = '';
						}
						control.value[control.id].same = '';
					}
				}
				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
				const $color = $(this).siblings('.tfminicolors').children('.color-select');
				$color.tfminicolors('value', '');
				$color.tfminicolors('opacity', '');
				$(this).hide();
			});
		},
		transparent($obj) {
			const control = this, $field = $(control.field, control.container);

			$obj.on('click', function () {
				const $self = $(this);
				if ($self.prop('checked')) {

					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()].transparent = 'transparent';
					} else {
						control.value[control.id].transparent = 'transparent';
					}
					$self.parent().prev().addClass('transparent');
				} else {
					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()].transparent = '';
					} else {
						control.value[control.id].transparent = '';
					}
					$self.parent().prev().removeClass('transparent');
				}
				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
			});
			if ($obj.prop('checked')) {
				$obj.parent().prev().addClass('transparent');
			}
		},
		dropdown($obj, key) {
			const control = this, $field = $(control.field, control.container);

			$obj.on('change', function () {
				const value = control.value[control.id],
					device = control.getCurrentDevice(),
					currentVal = $( 'option:selected', $(this) ).val();

				if ( control.isResponsiveStyling() ) {
					_.isUndefined( value[device] ) && ( value[device] = {} );
					value[device][key] = currentVal;
				} else {
					value[key] = currentVal;
				}

				$field.val( JSON.stringify( value ) ).trigger( 'change' );
			});
		},
		collapse($obj) {
			const control = this, $field = $(control.field, control.container);

			$obj.on('click', function () {
				const $self = $(this);
				if ($self.prop('checked')) {
					control.value[control.id].disabled = 'disabled';
					$self.parent().siblings('.themify-customizer-brick').stop().slideUp();
				} else {
					control.value[control.id].disabled = '';
					const $same = $self.parent().parent().find('input[type="checkbox"].same');
					if ($same.length > 0 && $same.prop('checked')) {
						$self.parent().siblings('.useforall, .collapse-same').stop().slideDown();
					} else {
						$self.parent().siblings('.themify-customizer-brick').stop().slideDown();
					}
				}
				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
			});
			if ($obj.prop('checked')) {
				$obj.parent().siblings('.themify-customizer-brick').hide();
			}
		},
		input($obj, key) {
			const control = this, $field = $(control.field, control.container);

			$obj.on('keyup', function () {
				if ( control.isResponsiveStyling() ) {
					if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
						control.value[control.id][control.getCurrentDevice()] = {};
					
					control.value[control.id][control.getCurrentDevice()][key] = $(this).val();
				} else {
					control.value[control.id][key] = $(this).val();
				}
				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
			});
		},
		dimension($obj) {
			const control = this, $field = $(control.field, control.container);

			$obj.on('keyup', function () {
				const value = control.value[control.id],
					device = control.getCurrentDevice(),
					width = $(this).val();

				if( control.isResponsiveStyling() ) {
					_.isUndefined( value[device] ) && ( value[device] = {} );
					value[device].width = width;
				} else {
					value.width = width;
				}

				$field.val( JSON.stringify( value ) ).trigger( 'change' );
			});
		},
		dimensionSame($obj) {
			const control = this, $field = $(control.field, control.container),
					$same = $('.same', control.container);

			$obj.on('keyup', function () {
				const side = $(this).data('side'),
						width = $(this).val();

				if ($same.prop('checked')) {
					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()].width = width;
						control.value[control.id][control.getCurrentDevice()].same = 'same';
					} else {
						control.value[control.id].width = width;
						control.value[control.id].same = 'same';
					}
				} else {
					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()][side] = _.extend({}, control.value[control.id][control.getCurrentDevice()][side], {
							'width': width
						});
						if ('top' === side) {
							control.value[control.id][control.getCurrentDevice()].width = width;
						}
						control.value[control.id][control.getCurrentDevice()].same = '';
					} else {
						control.value[control.id][side] = _.extend({}, control.value[control.id][side], {
							'width': width
						});
						if ('top' === side) {
							control.value[control.id].width = width;
						}
						control.value[control.id].same = '';
					}
				}
				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
			});
		},
		auto( $obj ) {
			const control = this, $field = $( control.field, control.container ),
				hideEl = $( control.container ).find( '.' +  $obj.data( 'hide' ) );

			$obj.on('click', function () {
				const $self = $(this),
					value = control.value[control.id],
					device = control.getCurrentDevice(),
					currentVal = $self.prop( 'checked' ) ? 'auto' : '';

				if( control.isResponsiveStyling() ) {
					_.isUndefined( value[device] ) && ( value[device] = {} );
					value[device].auto = currentVal;
				} else {
					value.auto = currentVal;
				}

				hideEl.stop().toggleClass( 'hide-horizontally', currentVal );
				$field.val( JSON.stringify( value ) ).trigger( 'change' );
			});

			$obj.prop( 'checked' ) && hideEl.addClass( 'hide-horizontally' );
		},
		autoSame($obj) {
			const control = this, $field = $(control.field, control.container),
					$same = $('.same', control.container);

			$obj.on('click', function () {
				const $self = $(this),
						hide = $self.data('hide'),
						side = $(this).data('side'),
						obj = {};

				if ($same.prop('checked')) {
					if ($self.prop('checked')) {
						obj.auto = 'auto';

						if ( control.isResponsiveStyling() ) {
							if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
								control.value[control.id][control.getCurrentDevice()] = {};
							
							control.value[control.id][control.getCurrentDevice()].auto = 'auto';
							control.value[control.id][control.getCurrentDevice()].top = _.extend({}, control.value[control.id][control.getCurrentDevice()].top, obj);
						} else {
							control.value[control.id].auto = 'auto';
							control.value[control.id].top = _.extend({}, control.value[control.id].top, obj);
						}
						$(control.container).find('.' + hide).stop().addClass('hide-horizontally');
					} else {
						obj.auto = '';

						if ( control.isResponsiveStyling() ) {
							if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
								control.value[control.id][control.getCurrentDevice()] = {};
							
							control.value[control.id][control.getCurrentDevice()].auto = '';
							control.value[control.id][control.getCurrentDevice()].top = _.extend({}, control.value[control.id][control.getCurrentDevice()].top, obj);
						} else {
							control.value[control.id].auto = '';
							control.value[control.id].top = _.extend({}, control.value[control.id].top, obj);
						}
						$(control.container).find('.' + hide).stop().removeClass('hide-horizontally');
					}

					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()].same = 'same';
					} else {
						control.value[control.id].same = 'same';
					}
				} else {
					if ($self.prop('checked')) {
						obj.auto = 'auto';
						
						if ( control.isResponsiveStyling() ) {
							if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
								control.value[control.id][control.getCurrentDevice()] = {};
							
							control.value[control.id][control.getCurrentDevice()][side] = _.extend({}, control.value[control.id][control.getCurrentDevice()][side], obj);
							if ('top' === side) {
								control.value[control.id][control.getCurrentDevice()].auto = 'auto';
							}
						} else {
							control.value[control.id][side] = _.extend({}, control.value[control.id][side], obj);
							if ('top' === side) {
								control.value[control.id].auto = 'auto';
							}
						}
						$(control.container).find('.' + hide).stop().addClass('hide-horizontally');
					} else {
						obj.auto = '';
						if ( control.isResponsiveStyling() ) {
							if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
								control.value[control.id][control.getCurrentDevice()] = {};
							
							control.value[control.id][control.getCurrentDevice()][side] = _.extend({}, control.value[control.id][control.getCurrentDevice()][side], obj);
							if ('top' === side) {
								control.value[control.id][control.getCurrentDevice()].auto = '';
							}
						} else {
							control.value[control.id][side] = _.extend({}, control.value[control.id][side], obj);
							if ('top' === side) {
								control.value[control.id].auto = '';
							}
						}
						$(control.container).find('.' + hide).stop().removeClass('hide-horizontally');
					}

					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()].same = '';
					} else {
						control.value[control.id].same = '';
					}
				}

				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
			});
			$obj.each(function () {
				let $self = $(this);
				if ($self.prop('checked')) {
					$(control.container).find('.' + $self.data('hide')).addClass('hide-horizontally');
				}
			});
		},
		dropdownSame($obj, key) {
			const control = this, $field = $(control.field, control.container),
					$same = $('.same', control.container);

			$obj.on('change', function () {
				const side = $(this).data('side'),
						val = $('option:selected', $(this)).val();
				if ($same.prop('checked')) {

					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()][key] = val;
						control.value[control.id][control.getCurrentDevice()].same = 'same';
					} else {
						control.value[control.id][key] = val;
						control.value[control.id].same = 'same';
					}
				} else {
					const obj = {};
					obj[key] = val;

					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()][side] = _.extend({}, control.value[control.id][control.getCurrentDevice()][side], obj);
						if ('top' === side) {
							control.value[control.id][control.getCurrentDevice()][key] = val;
						}
						control.value[control.id][control.getCurrentDevice()].same = '';
					} else {
						control.value[control.id][side] = _.extend({}, control.value[control.id][side], obj);
						if ('top' === side) {
							control.value[control.id][key] = val;
						}
						control.value[control.id].same = '';
					}
				}
				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
			});
		},
		dropdownBorderSame($obj) {
			const control = this, $field = $(control.field, control.container),
					$same = $('.same', control.container);

			$obj.on('change', function () {
				const $self = $(this),
						side = $self.data('side'),
						style = $('option:selected', $self).val();
				if ($same.prop('checked')) {

					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()].style = style;
						control.value[control.id][control.getCurrentDevice()].same = 'same';
					} else {
						control.value[control.id].style = style;
						control.value[control.id].same = 'same';
					}
				} else {

					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()][side] = _.extend({}, control.value[control.id][control.getCurrentDevice()][side], {
							'style': style
						});
						if ('top' === side) {
							control.value[control.id][control.getCurrentDevice()].style = style;
						}
						control.value[control.id][control.getCurrentDevice()].same = '';
					} else {
						control.value[control.id][side] = _.extend({}, control.value[control.id][side], {
							'style': style
						});
						if ('top' === side) {
							control.value[control.id].style = style;
						}
						control.value[control.id].same = '';
					}
				}
				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
				if ('none' === style) {
					$self.parent().siblings('.color-picker, .border-width, .dimension-unit-label').hide();
				} else {
					$self.parent().siblings('.color-picker, .border-width, .dimension-unit-label').show();
				}
			});

			$obj.each(function () {
				let $self = $(this);
				if ('none' ===  $('option:selected', $self).val()) {
					$self.parent().siblings('.color-picker, .border-width, .dimension-unit-label').hide();
				} else {
					$self.parent().siblings('.color-picker, .border-width, .dimension-unit-label').show();
				}
			});
		},
		hideComponentsSame($obj) {
			const control = this, $field = $(control.field, control.container),
					$components = $('.component', control.container),
					$rowLabel = $('.dimension-row-label:not(.same-label)', control.container),
					$sameLabel = $obj.parent().parent().find('.same-label');

			$obj.on('click', function () {
				const $self = $(this);
				if ($self.prop('checked')) {
					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()].same = 'same';
					} else {
						control.value[control.id].same = 'same';
					}
					$components.stop().slideUp();
					$rowLabel.hide();
					$sameLabel.text($sameLabel.data('same'));
				} else {
					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()].same = '';
					} else {
						control.value[control.id].same = '';
					}
					$components.stop().slideDown();
					$rowLabel.show();
					$sameLabel.text($sameLabel.data('notsame'));
				}
				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
			});
			if ($obj.prop('checked')) {
				$components.hide();
				$rowLabel.hide();
				$sameLabel.text($sameLabel.data('same'));
			}
		},
		getSelectedData($obj, data, std) {
			const dataget =  $('.selected', $obj).data(data);
			return dataget ? dataget : std;
		},
		fontStyle($style) {
			const control = this, $field = $(control.field, control.container);
			// Font style
			$('.button', $style).on('click', function () {
				const clickedStyle = $(this).data('style');
				if ('underline' === clickedStyle) {
					$('.button.selected[data-style="linethrough"]', $style).removeClass('selected');
				}
				else if ('linethrough' === clickedStyle) {
					$('.button.selected[data-style="underline"]', $style).removeClass('selected');
				}
				else if ('italic' === clickedStyle) {
					$('.button.selected[data-style="normal"]', $style).removeClass('selected');
				}
				else if ('normal' === clickedStyle) {
					$('.button.selected[data-style="italic"]', $style).removeClass('selected');
				}
				else if ('nostyle' === clickedStyle) {
					$('.button:not([data-style="nostyle"])', $style).removeClass('selected');
				}
				else{
					$('.button[data-style="nostyle"]', $style).removeClass('selected');
				}
				// Mark this as selected
				$(this).toggleClass('selected');

				// Check which buttons are set
				if ( control.isResponsiveStyling() ) {
					if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
						control.value[control.id][control.getCurrentDevice()] = {};
					
					$('.button', $style).each(function () {
						control.value[control.id][control.getCurrentDevice()][$(this).data('style')] = $(this).hasClass('selected') ? $(this).data('style') : '';
					});
				} else {
					$('.button', $style).each(function () {
						control.value[control.id][$(this).data('style')] = $(this).hasClass('selected') ? $(this).data('style') : '';
					});
				}
				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
			});
		},
		textTransform($texttransform) {
			const control = this, $field = $(control.field, control.container);
			$('.button', $texttransform).on('click', function () {
				const clickedTextTrans = $(this).data('texttransform');
				// Mark this as selected
				$('.button', $texttransform).not(this).removeClass('selected');
				$(this).toggleClass('selected');

				if ('notexttransform' === clickedTextTrans) {
					$('.button:not([data-texttransform="notexttransform"])', $texttransform).removeClass('selected');
				}
				else {
					$('.button[data-texttransform="notexttransform"]', $texttransform).removeClass('selected');
				}

				if ( control.isResponsiveStyling() ) {
					if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
						control.value[control.id][control.getCurrentDevice()] = {};

					control.value[control.id][control.getCurrentDevice()].texttransform = control.getSelectedData($texttransform, 'texttransform');
				} else {
					control.value[control.id].texttransform = control.getSelectedData($texttransform, 'texttransform');
				}
				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
			});
		},
		textAlign($align) {
			const control = this, $field = $(control.field, control.container);
			$('.button', $align).on('click', function () {
				const clickedAlign = $(this).data('align');
				// Mark this as selected
				$('.button', $align).not(this).removeClass('selected');
				$(this).toggleClass('selected');

				if ('noalign' === clickedAlign) {
					$('.button:not([data-align="noalign"])', $align).removeClass('selected');
				}
				else  {
					$('.button[data-align="noalign"]', $align).removeClass('selected');
				}
				if ( control.isResponsiveStyling() ) {
					if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
						control.value[control.id][control.getCurrentDevice()] = {};

					control.value[control.id][control.getCurrentDevice()].align = control.getSelectedData($align, 'align');
				} else {
					control.value[control.id].align = control.getSelectedData($align, 'align');
				}
				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
			});
		},
		fontFamily($obj) {
			const control = this, $field = $(control.field, control.container);
			$obj.on({
				change() {
					var $font_weight = $(this).closest('li').find('.font_weight_select'),
						$variants = $font_weight.length>0?$(this).find('option:selected').data('variants'):false;
					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};

						control.value[control.id][control.getCurrentDevice()].family = parseJSON($('option:selected', $(this)).val());
					   
					} else {
						control.value[control.id].family = parseJSON($('option:selected', $(this)).val());
					}
					if($variants){
						$font_weight.closest( '.themify-customizer-brick' ).show();

						$variants = $.trim($variants).split(',');
						$font_weight.find('option').each(function(){
							if($.inArray($(this).val(),$variants)===-1){
								$(this).hide();
							}
							else{
								$(this).show();
							}
						});
						var $selected = $font_weight.find('option:selected');
						if(!$selected.is(':visible')){
							$selected.prop('selected',false);
							$font_weight.find('option').each(function(){
								if ($(this).css('display') != 'none') {
									$(this).prop("selected", true).trigger('change');
									return false;
								}
							});
						}
					} else if ( typeof $variants === 'string' ) {
						// empty data-variants, the font has no variant
						$font_weight.val( '' ).find( 'option' ).hide()
							.closest( '.themify-customizer-brick' ).hide();
					} else {
						// missing variation data (eg, web-safe fonts), show all available variants by default
						$font_weight.find( 'option' ).show()
							.closest( '.themify-customizer-brick' ).show();
					}
					$field.val(JSON.stringify(control.value[control.id])).trigger('change');
					$('#themify_font_preview').hide();
				},
				focusin() {
					var $selected = $(this).data('selected');
					if ($('.themify_add_fonts').length > 0) {
						var $html = $('.themify_add_fonts').html(),
							$options = $($html);
						$options.find('option').removeAttr('selected');
						if ($selected) {
							$options.find('option[data-value="' + $selected + '"]').attr('selected', 'selected');
						}
						$(this).html($options);
					}
					else {
						$('body').append('<span id="themify_font_preview"><span class="themify_font_wait"></span>Font Preview</span>');
						var $themify_fonts = parseJSON(decodeURI($('#themify_fonts_hidden').val())),
							$cf_fonts = $themify_fonts.cf,
							$google = $themify_fonts.google,
							$fonts = $themify_fonts.fonts,
							$html = '';
							$themify_fonts = null;
						if($cf_fonts.length>0){
							for (var $i in $cf_fonts) {
								var $name = $cf_fonts[$i].name,
                                                                    $value = $cf_fonts[$i].value,
                                                                    $val = '{"fonttype":"cf","name":"' + $value + '"}';
								$s = $selected && $selected == $value ? 'selected="selected"' : '';
								$name = control.escapeHtml($name);
								$html += "<option data-variants='"+$cf_fonts[$i].variants+"' data-value='" + $value + "' class='cf_font' " + $s + "  value='" + $val + "'>" + $name + "</option>";
							}
							$cf_fonts = null;
							$(this).children('optgroup').first().html($html);
							$html = '';
						}

						for (var $i in $fonts) {
							var $name = $fonts[$i].value,
								$s = $selected && $selected == $name ? 'selected="selected"' : '';
							$name = control.escapeHtml($name);
                                                        $val = '{"fonttype":"websafe","name":"' + $name + '"}';
							$html += "<option " + $s + " data-value='" + $name + "' value='" + $val + "'>" + $fonts[$i].name + "</option>";
						}
						$fonts = null;
						$(this).children('optgroup.themify_wsf_optgroup').html($html);
						$html = '';
						for (var $i in $google) {
							var $name = $google[$i].name,
                                                            $s = $selected && $selected == $name ? 'selected="selected"' : '',
                                                            $val = '{"fonttype":"google"';
							$name = control.escapeHtml($name);
							$val += ',"name":"' + $name + '"}';
							$html += "<option data-variants='"+$google[$i].variants+"' data-value='" + $name + "' class='google_font' " + $s + "  value='" + $val + "'>" + $google[$i].name + "</option>";
						}
						$google = null;
						$(this).children('optgroup').last().html($html);

						$(this).addClass('themify_add_fonts');
						$('#themify_fonts_hidden').remove();
						control.fontHover();
					}

					const $this = $(this);
					$this.off('focusin').scombobox({
						wrap: true,
						reassignId: false,
						empty: $selected ? false : true,
						showDropDown: true,
						beforeClose() {
							$('#themify_font_preview').hide();
						},
						afterClose() {
							var $input = $this.closest('.scombobox').find('.scombobox-display');
							if (!$.trim($input.val())) {
								$this.data('selected', '')
										.find('option:selected')
										.prop('selected', false)
										.trigger('change');
							}
							if($('#themify_font_preview').is(':visible') && !$this.find('.scombobox-list').is(':visible')){
								$('#themify_font_preview').hide();
							}
						}
					});

				}
			});
		},
		escapeHtml($string) {
			const map = {
				'&': '&amp;',
				'<': '&lt;',
				'>': '&gt;',
				'"': '&quot;',
				"'": '&#039;'
			};
			return $string.replace(/[&<>"']/g, function (m) {
				return map[m];
			});
		},
		fontHover() {
			$('.themify_combobox').delegate('.scombobox-list p', 'mouseover', function (e) {
				e.stopImmediatePropagation();
				var $preview = $('#themify_font_preview');
				if ($(this).data('value') && $(this).is(':visible')) {
					var $font = parseJSON($(this).data('value')),
						$pos = $(this).offset();
						$preview.css({'top': $pos.top - 7, 'left': $pos.left + 260});
					
					if ( ( 'google' === $font.fonttype || 'cf' === $font.fonttype ) && !$(this).hasClass('themify_font_loaded')) {
						$('.themify_combobox .scombobox-list p').removeClass('current');
						$(this).addClass('current');
						$preview.addClass('themify_show_wait');
						setTimeout(function () {
							var $this = $('.themify_combobox p.current');
							 if($this.closest('.scombobox-list').is(':visible')){
								var $font = parseJSON($this.data('value')),
									$pos = $this.offset(),
									webFontConfig = {
										fontloading(familyName, fvd) {
											$preview.css('font-family', familyName).removeClass('themify_show_wait');
											$this.addClass('themify_font_loaded');
										}
									};
								 $preview.css({'top': $pos.top - 7, 'left': $pos.left + 260}).show();
								if('google' === $font.fonttype){
									webFontConfig['google'] = {families: [$font.name]};
								}else{
									webFontConfig['custom'] = {families: [$font.name],urls:[themifyCustomizerControls.cf_api_url+$font.name]};
								}
								WebFont.load(webFontConfig);
							}
							else{
								$preview.hide();
							}

						}, 800);
					}
					else {
						 $preview.css('font-family', $font.name).removeClass('themify_show_wait').show();
					}
				}
				else {
					$preview.hide();
				}
			});
		},
		inputOption($obj, key) {
			const control = this, $field = $(control.field, control.container);
			let timer;

			$obj.on('keyup', function () {
				const value = $(this).val();
				if ('blogname' === key) {
					$('.customize-control-themify_logo').find('.site-name').each(function () {
						$(this).val(value);
					});
				}
				clearTimeout(timer);
				timer = setTimeout(function () {
					$.post(
							ajaxurl,
							{
								'action': 'themify_customizer_save_option',
								'option': key,
								'value': value,
								'nonce': themifyCustomizerControls.nonce
							},
					function (data) {
						if ('saved' === data) {
							// Set timestamp to force live preview reload
							control.value[control.id].stamp = new Date().getTime();
							$field.val(JSON.stringify(control.value[control.id])).trigger('change');
						}
					}
					);
				}, 750);
			});
		},
		saveOption(key, value) {
			const control = this;
			$.post(
					ajaxurl,
					{
						'action': 'themify_customizer_save_option',
						'option': key,
						'value': value,
						'nonce': themifyCustomizerControls.nonce
					},
			function (data) {
				if ('saved' === data) {
					control.saveOptionCallback();
				}
			}
			);
		},
		saveOptionCallback() {
			// if you use saveOption, redefine this callback in the extended object
		},
		changeMode(key) {
			const control = this, $field = $(control.field, control.container);
			$(key + '-mode', control.container).each(function () {
				$(this).on('click', function () {
					var $self = $(this);
					$(key + '-mode-wrap', control.container).hide();
					$(key + '-' + $self.val() + '-mode', control.container).show();
					
					control.value[control.id].mode = $self.val();
					$field.val(JSON.stringify(control.value[control.id])).trigger('change');
				});
			});
			$(key + '-mode-wrap', control.container).hide();
			$(key + '-' + $('input[type="radio"]' + key + '-mode:checked').val() + '-mode', control.container).show();
		},
		addQueryArg(e, n, l) {
			return Themify.UpdateQueryString(e,n,l);
		},
		getParameterByName(name, url) {
			if (!url) {
				url = window.location.href;
			}
			name = name.replace(/[\[\]]/g, "\\$&");
			const regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
			results = regex.exec(url);
			if (!results) return null;
			if (!results[2]) return '';
			return decodeURIComponent(results[2].replace(/\+/g, " "));
		},
		isResponsiveStyling() {
			return 'desktop' !== api.previewedDevice.get();
		},
		getCurrentDevice() {
			return api.previewedDevice.get();
		},
		radioChange( $obj, key ) {
			const control = this,
				$field = $(control.field, control.container),
				initVal = $obj.find( 'input[type="radio"]:checked' ).val();

			$obj.find( 'input[type="radio"]' ).on('click', function () {
				var val = $(this).val();

				if ( control.isResponsiveStyling() ) {
					if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
						control.value[control.id][control.getCurrentDevice()] = {};

					control.value[control.id][control.getCurrentDevice()][key] = val;
				} else {
					control.value[control.id][key] = val;
					$obj.closest( '.customize-control' ).data( 'deskValue', val );
				}

				$obj.nextAll( '[class*="-mode-wrap"]' ).hide();
				$obj.nextAll( '[class*="-' + val + '-mode"]' ).show();

				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
			});

			$obj.nextAll( '[class*="-mode-wrap"]' ).hide();
			$obj.nextAll( '[class*="-' + initVal + '-mode"]' ).show();
		}
	});
	/***************************************************************************
	 * ThemifyControl End
	 ***************************************************************************/

	////////////////////////////////////////////////////////////////////////////
	// Font Control Start
	////////////////////////////////////////////////////////////////////////////
	api.ThemifyFont = api.ThemifyControl.extend({
		field: '.themify_font_control',
		ready() {
			var control = this,
					$field = $(control.field, control.container);

			control.value[control.id] = $field.val() ? parseJSON($field.val()) : {};

			// Checkbox to hide controls
			control.collapse($('.disable-control', control.container));

			// Font family
			control.fontFamily($('.themify_font_family', control.container));

			// Font size numeric
			control.input($('.font_size_num', control.container), 'sizenum');

			// Font size unit
			control.dropdown($('.font_size_unit', control.container), 'sizeunit');

			// Letter spacing numeric
			control.input($('.letter_spacing', control.container), 'letterspacing');

			// Letter spacing unit
			control.dropdown($('.letter_spacing_unit', control.container), 'letterspacingunit');

			// Line height numeric
			control.input($('.font_line_num', control.container), 'linenum');

			// Line height unit
			control.dropdown($('.font_line_unit', control.container), 'lineunit');
			
			// Font Weight
			control.dropdown($('.font_weight_select', control.container), 'weight');

			// Font style
			control.fontStyle($('.themify_font_style', control.container));

			// Text transform
			control.textTransform($('.themify_text_transform', control.container));

			// Text align
			control.textAlign($('.themify_font_align', control.container));
		}
	});
	api.controlConstructor.themify_font = api.ThemifyFont;
	api.controlConstructor.themify_text_decoration = api.ThemifyFont;
	////////////////////////////////////////////////////////////////////////////
	// Font Control End
	////////////////////////////////////////////////////////////////////////////



	////////////////////////////////////////////////////////////////////////////
	// Logo Control Start
	////////////////////////////////////////////////////////////////////////////
	api.ThemifyLogo = api.ThemifyControl.extend({
		field: '.themify_logo_control',
		ready() {
			var control = this,
					$field = $(control.field, control.container);

			control.value[control.id] = $field.val() ? parseJSON($field.val()) : {};

			// Site title
			control.inputOption($('.site-name', control.container), 'blogname');

			// Site title link
			control.input($('.site-link', control.container), 'link');

			// Open Media Library
			control.openMedia();

			// Image width and height
			control.input($('.img-width', control.container), 'imgwidth');
			control.input($('.img-height', control.container), 'imgheight');

			// Checkbox to hide controls
			control.collapse($('.disable-control', control.container));

			// Font family
			control.fontFamily($('.themify_font_family', control.container));

			// Font size numeric
			control.input($('.font_size_num', control.container), 'sizenum');

			// Font size unit
			control.dropdown($('.font_size_unit', control.container), 'sizeunit');

			// Line height numeric
			control.input($('.font_line_num', control.container), 'linenum');

			// Line height unit
			control.dropdown($('.font_line_unit', control.container), 'lineunit');
			
			// Letter spacing numeric
			control.input($('.letter_spacing', control.container), 'letterspacing');

			// Letter spacing unit
			control.dropdown($('.letter_spacing_unit', control.container), 'letterspacingunit');
			
			// Font Weight
			control.dropdown($('.font_weight_select', control.container), 'weight');

			// Font style
			control.fontStyle($('.themify_font_style', control.container));

			// Text transform
			control.textTransform($('.themify_text_transform', control.container));

			// Text align
			control.textAlign($('.themify_font_align', control.container));

			// Color Picker
			control.pickColor();

			// Logo Mode Changer
			control.radioChange( $( '.logo-modes', control.container ), 'mode' )
		}
	});
	api.controlConstructor.themify_logo = api.ThemifyLogo;
	////////////////////////////////////////////////////////////////////////////
	// Logo Control End
	////////////////////////////////////////////////////////////////////////////

	////////////////////////////////////////////////////////////////////////////
	// Tagline Control Start
	////////////////////////////////////////////////////////////////////////////
	api.ThemifyTagline = api.ThemifyControl.extend({
		field: '.themify_tagline_control',
		ready() {
			var control = this,
					$field = $(control.field, control.container);

			control.value[control.id] = $field.val() ? parseJSON($field.val()) : {};

			// Logo Mode Changer
			control.changeMode('.tagline');

			// Site title
			control.inputOption($('.site-description', control.container), 'blogdescription');

			// Open Media Library
			control.openMedia();

			// Image width and height
			control.input($('.img-width', control.container), 'imgwidth');
			control.input($('.img-height', control.container), 'imgheight');

			// Checkbox to hide controls
			control.collapse($('.disable-control', control.container));

			// Font family
			control.fontFamily($('.themify_font_family', control.container));

			// Font size numeric
			control.input($('.font_size_num', control.container), 'sizenum');

			// Font size unit
			control.dropdown($('.font_size_unit', control.container), 'sizeunit');

			// Letter spacing numeric
			control.input($('.letter_spacing', control.container), 'letterspacing');

			// Letter spacing unit
			control.dropdown($('.letter_spacing_unit', control.container), 'letterspacingunit');

			// Line height numeric
			control.input($('.font_line_num', control.container), 'linenum');

			// Line height unit
			control.dropdown($('.font_line_unit', control.container), 'lineunit');
			
			// Font Weight
			control.dropdown($('.font_weight_select', control.container), 'weight');

			// Font style
			control.fontStyle($('.themify_font_style', control.container));

			// Text transform
			control.textTransform($('.themify_text_transform', control.container));

			// Text align
			control.textAlign($('.themify_font_align', control.container));

			// Color Picker
			control.pickColor();

			// Site title link
			control.input($('.site-description-link', control.container), 'link');
		}
	});
	api.controlConstructor.themify_tagline = api.ThemifyTagline;
	////////////////////////////////////////////////////////////////////////////
	// Logo Control End
	////////////////////////////////////////////////////////////////////////////

	////////////////////////////////////////////////////////////////////////////
	// Background Control Start
	////////////////////////////////////////////////////////////////////////////
	api.ThemifyBackground = api.ThemifyControl.extend({
		field: '.themify_background_control',
		noImage($obj) {
			var control = this, $field = $(control.field, control.container),
					$hideElements = $('.open-media-wrap, .image-label, .background-style, .background-position', control.container);

			$obj.on('click', function () {
				var $self = $(this);
				if ($self.prop('checked')) {
					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()].noimage = 'noimage';
					} else {
						control.value[control.id].noimage = 'noimage';
					}
					$hideElements.stop().slideUp();
				} else {
					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()].noimage = '';
					} else {
						control.value[control.id].noimage = '';
					}
					$hideElements.stop().slideDown();
				}
				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
			});
			if ($obj.prop('checked')) {
				$hideElements.hide();
			}
		},
		fixedBg( $obj ) {
			var control = this, $field = $(control.field, control.container);

			$obj.on('click', function () {
				var $self = $(this);
				if ($self.prop('checked')) {
					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()].fixedbg = 'fixed';
					} else {
						control.value[control.id].fixedbg = 'fixed';
					}
				} else {
					if ( control.isResponsiveStyling() ) {
						if ( _.isUndefined( control.value[control.id][control.getCurrentDevice()] ) ) 
							control.value[control.id][control.getCurrentDevice()] = {};
						
						control.value[control.id][control.getCurrentDevice()].fixedbg = '';
					} else {
						control.value[control.id].fixedbg = '';
					}
				}
				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
			});
		},
		ready() {
			var control = this,
					$field = $(control.field, control.container);

			control.value[control.id] = $field.val() ? parseJSON($field.val()) : {};

			// Checkbox to hide controls
			control.noImage($('.disable-control', control.container));

			// Fixed Background
			control.fixedBg( $( '.fixed-bg input[type="checkbox"]', control.container ) );

			// Open Media Library
			control.openMedia();

			// Image style
			control.dropdown($('.image-style', control.container), 'style');

			// Image position
			control.dropdown($('.position-style', control.container), 'position');

			// Color Picker
			control.pickColor();

			// Color Transparent
			control.transparent($('.color-transparent', control.container));
		}
	});
	api.controlConstructor.themify_background = api.ThemifyBackground;
	////////////////////////////////////////////////////////////////////////////
	// Background Control End
	////////////////////////////////////////////////////////////////////////////

	////////////////////////////////////////////////////////////////////////////
	// Color Control Start
	////////////////////////////////////////////////////////////////////////////
	api.ThemifyColor = api.ThemifyControl.extend({
		field: '.themify_color_control',
		ready() {
			var control = this,
					$field = $(control.field, control.container);

			control.value[control.id] = $field.val() ? parseJSON($field.val()) : {};

			// Color Picker
			control.pickColor();

			// Color Transparent
			control.transparent($('.color-transparent', control.container));
		}
	});
	api.controlConstructor.themify_color = api.ThemifyColor;
	////////////////////////////////////////////////////////////////////////////
	// Color Control End
	////////////////////////////////////////////////////////////////////////////

	////////////////////////////////////////////////////////////////////////////
	// Image Control Start
	////////////////////////////////////////////////////////////////////////////
	api.ThemifyImage = api.ThemifyBackground.extend({
		field: '.themify_image_control',
		ready() {
			var control = this,
					$field = $(control.field, control.container);

			control.value[control.id] = $field.val() ? parseJSON($field.val()) : {};

			// Image width and height
			control.input($('.img-width', control.container), 'imgwidth');
			control.input($('.img-height', control.container), 'imgheight');

			// Open Media Library
			control.openMedia();
		}
	});
	api.controlConstructor.themify_image = api.ThemifyImage;
	////////////////////////////////////////////////////////////////////////////
	// Image Control End
	////////////////////////////////////////////////////////////////////////////

	////////////////////////////////////////////////////////////////////////////
	// Border Control Start
	////////////////////////////////////////////////////////////////////////////
	api.ThemifyBorder = api.ThemifyControl.extend({
		field: '.themify_border_control',
		ready() {
			var control = this,
					$field = $(control.field, control.container);

			if ($field.val()) {
				control.value[control.id] = parseJSON($field.val());
			} else {
				var initObj = {
					'color': '',
					'opacity': '',
					'style': '',
					'width': ''
				};
				control.value[control.id] = {};
				control.value[control.id].top = initObj;
				control.value[control.id].left = initObj;
				control.value[control.id].bottom = initObj;
				control.value[control.id].right = initObj;
			}

			// Checkbox to hide controls
			control.collapse($('.disable-control', control.container));

			// Border color
			control.pickBorderColor();

			// Border style
			control.dropdownBorderSame($('.border-style', control.container));

			// Border width
			control.dimensionSame($('.dimension-width', control.container));

			// Hide components leaving only one
			control.hideComponentsSame($('.same', control.container));
		}
	});
	api.controlConstructor.themify_border = api.ThemifyBorder;
	////////////////////////////////////////////////////////////////////////////
	// Border Control End
	////////////////////////////////////////////////////////////////////////////

	////////////////////////////////////////////////////////////////////////////
	// Margin Control Start
	////////////////////////////////////////////////////////////////////////////
	api.ThemifyMargin = api.ThemifyControl.extend({
		field: '.themify_margin_control',
		ready() {
			var control = this,
					$field = $(control.field, control.container);

			if ($field.val()) {
				control.value[control.id] = parseJSON($field.val());
			} else {
				var initObj = {
					'width': '',
					'unit': 'px'
				};
				control.value[control.id] = {};
				control.value[control.id].top = initObj;
				control.value[control.id].left = initObj;
				control.value[control.id].bottom = initObj;
				control.value[control.id].right = initObj;
			}

			// Checkbox to hide controls
			control.collapse($('.disable-control', control.container));

			// Margin width
			control.dimensionSame($('.dimension-width', control.container));

			// Margin unit
			control.dropdownSame($('.dimension-unit', control.container), 'unit');

			// Auto
			control.autoSame($('.auto-prop', control.container));

			// Hide components leaving only one
			control.hideComponentsSame($('.same', control.container));
		}
	});
	api.controlConstructor.themify_margin = api.ThemifyMargin;
	////////////////////////////////////////////////////////////////////////////
	// Margin Control End
	////////////////////////////////////////////////////////////////////////////

	////////////////////////////////////////////////////////////////////////////
	// Padding Control Start
	////////////////////////////////////////////////////////////////////////////
	api.ThemifyPadding = api.ThemifyMargin.extend({
		field: '.themify_padding_control'

	});
	api.controlConstructor.themify_padding = api.ThemifyPadding;
	////////////////////////////////////////////////////////////////////////////
	// Padding Control End
	////////////////////////////////////////////////////////////////////////////

	////////////////////////////////////////////////////////////////////////////
	// Width Control Start
	////////////////////////////////////////////////////////////////////////////
	api.ThemifyWidth = api.ThemifyControl.extend({
		field: '.themify_width_control',
		ready() {
			var control = this,
					$field = $(control.field, control.container);

			if ($field.val()) {
				control.value[control.id] = parseJSON($field.val());
			} else {
				control.value[control.id] = {
					'width': '',
					'unit': 'px',
					'auto': ''
				};
			}

			// Width width
			control.dimension($('.dimension-width', control.container));

			// Width unit
			control.dropdown($('.dimension-unit', control.container), 'unit');

			// Auto
			control.auto($('.auto-prop', control.container));
		}
	});
	api.controlConstructor.themify_width = api.ThemifyWidth;
	////////////////////////////////////////////////////////////////////////////
	// Width Control End
	////////////////////////////////////////////////////////////////////////////

	////////////////////////////////////////////////////////////////////////////
	// Height Control Start
	////////////////////////////////////////////////////////////////////////////
	api.ThemifyHeight = api.ThemifyWidth.extend({
		field: '.themify_height_control'

	});
	api.controlConstructor.themify_height = api.ThemifyHeight;
	////////////////////////////////////////////////////////////////////////////
	// Height Control End
	////////////////////////////////////////////////////////////////////////////

	////////////////////////////////////////////////////////////////////////////
	// Position Control Start
	////////////////////////////////////////////////////////////////////////////
	api.ThemifyPosition = api.ThemifyControl.extend({
		field: '.themify_position_control',
		dropdownPosition($obj, key) {
			var control = this, $field = $(control.field, control.container),
					initial = $obj.find('option:selected').val();

			$obj.on('change', function () {
				var $select = $(this), value = $('option:selected', $select).val();
				control.value[control.id][key] = value;
				$field.val(JSON.stringify(control.value[control.id])).trigger('change');

				if (value && 'static' !== value) {
					$select.closest('.themify-customizer-brick').parent().find('.position-wrap').show();
				} else {
					$select.closest('.themify-customizer-brick').parent().find('.position-wrap').hide();
				}
			});

			if (initial && 'static' !== initial) {
				$obj.closest('.themify-customizer-brick').parent().find('.position-wrap').show();
			} else {
				$obj.closest('.themify-customizer-brick').parent().find('.position-wrap').hide();
			}
		},
		ready() {
			var control = this,
					$field = $(control.field, control.container);

			control.value[control.id] = $field.val() ? parseJSON($field.val()) : {'position': ''};

			// Position
			control.dropdownPosition($('.position', control.container), 'position');

			// Position value
			control.dimensionSame($('.dimension-width', control.container));

			// Position unit
			control.dropdownSame($('.dimension-unit', control.container), 'unit');

			// Auto
			control.autoSame($('.auto-prop', control.container));
		}
	});
	api.controlConstructor.themify_position = api.ThemifyPosition;
	////////////////////////////////////////////////////////////////////////////
	// Position Control End
	////////////////////////////////////////////////////////////////////////////

	////////////////////////////////////////////////////////////////////////////
	// CustomCSS Control Start
	////////////////////////////////////////////////////////////////////////////
	api.ThemifyCustomCSS = api.ThemifyControl.extend({
		field: '.themify_customcss_control',
		expand(container) {
			$('.themify-expand', container.container).on('click', function (e) {
				e.preventDefault();
				container.editor.codemirror.setOption('fullScreen', true);
				$('.close-custom-css-expanded').addClass('enable-expanded-area');

				$('.close-custom-css-expanded').on('click', function(){
					container.editor.codemirror.setOption('fullScreen', false);
					$('.close-custom-css-expanded').removeClass('enable-expanded-area')
				})
			});
		},
		ready() {
			var control = this,
				$field = $( control.field, control.container ),
				$customCSS = $( '.customcss', control.container );

			control.value[control.id] = $field.data('value') ? window.atob( $field.data( 'value' ) ) : '';
			$field.data( 'value', '' );
			$field.val( control.value[control.id] );
			
			control.initSyntaxHighlightingEditor();
			
			// Prevent scroll to top
			var currentVal = typeof control.editor !== 'undefined'
				? control.editor.codemirror.getValue()
				: control.container.find('textarea').val();

			// Initialize expand/contract action
			control.expand( control, $customCSS );
		},
		initSyntaxHighlightingEditor( context ) {
			if ( typeof wp.codeEditor === 'undefined' ) return;

			var control = this, $textarea, settings, suspendEditorUpdate = false;

			$textarea = context ? context.find( 'textarea' ) : control.container.find( 'textarea' );
			settings = wp.codeEditor.defaultSettings ? _.clone( wp.codeEditor.defaultSettings ) : {};
			settings.codemirror = _.extend( {}, settings.codemirror, { indentUnit: 2, tabSize: 2, mode: 'css' } );
			control.editor = wp.codeEditor.initialize( $textarea, settings );

			// Improve the editor accessibility.
			$( control.editor.codemirror.display.lineDiv )
				.attr({
					role: 'textbox',
					'aria-multiline': 'true',
					'aria-label': control.params.label,
					'aria-describedby': 'editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4'
				});

			/*
			 * When the CodeMirror instance changes, mirror to the textarea,
			 * where we have our "true" change event handler bound.
			 */
			control.editor.codemirror.on( 'change', function( codemirror ) {
				suspendEditorUpdate = true;
				control.container.find( 'textarea' ).val( codemirror.getValue() ).trigger( 'change' );
				suspendEditorUpdate = false;
			});

			control.editor.codemirror.on( 'keydown', function onKeydown( codemirror, event ) {
				27 == event.keyCode && event.stopPropagation();
			});

			// CSS validation
			api( 'customcss', function ( setting ) {
				setting.validate = function ( value ) {
					const err = wp.CodeMirror.lint.css(value,{errors:1}),
						code = 'invalid_css';
					if(err && err.length>0){
						setting.notifications.add( code, new wp.customize.Notification( code, {message: themifyCustomizerControls.invalid_css, type: 'warning'} ) );
					} else {
						setting.notifications.remove( code );
					}
					return value;
				};
			} );
		},
	});
	api.controlConstructor.themify_customcss = api.ThemifyCustomCSS;
	////////////////////////////////////////////////////////////////////////////
	// CustomCSS Control End
	////////////////////////////////////////////////////////////////////////////

	////////////////////////////////////////////////////////////////////////////
	// Image Select Control Start
	////////////////////////////////////////////////////////////////////////////
	api.ThemifyImageSelect = api.ThemifyControl.extend({
		field: '.themify_image_select_control',
		ready() {
			var control = this, $field = $(control.field, control.container);

			if ($field.val()) {
				control.value[control.id] = parseJSON($field.val());
			} else {
				control.value[control.id] = {
					'type': '',
					'selected': ''
				};
			}

			$('.image-select', control.container).on('click', function (e) {
				e.preventDefault();
				control.value[control.id].selected = $(this).data('option');
				$field.val(JSON.stringify(control.value[control.id])).trigger('change');
			});
		}
	});
	api.controlConstructor.themify_image_select = api.ThemifyImageSelect;
	////////////////////////////////////////////////////////////////////////////
	// Image Select Control End
	////////////////////////////////////////////////////////////////////////////

	////////////////////////////////////////////////////////////////////////////
	// Tools Control Start
	////////////////////////////////////////////////////////////////////////////
	api.ThemifyTools = api.ThemifyControl.extend({
		field: '.themify_tools_control',
		clearing: false,
		saveOptionCallback() {
			// Save and reload
			$('#customize-header-actions').find('.save').trigger('click');
		},
		ready() {
			var control = this;
			
			////////////////////////////////////////////////////////////////////////////
			// Clear Tool Start
			////////////////////////////////////////////////////////////////////////////
			api.bind('saved', function () {
				if (api.ThemifyTools.field) {
					if ( 'true' === control.getParameterByName('cleared') ) {
						window.location.reload();
					} else {
						var hashlink = window.top.location.href;
						hashlink = (hashlink[hashlink.length-1] == '#') ? hashlink.replace('#' , '') : hashlink;
						window.top.location = hashlink;
					}
					api.ThemifyTools.field = false;
				}
			});

			$('.clearall', control.container).on('click', function () {
				if (window.confirm(themifyCustomizerControls.clearMessage)) {
					// Tell the event hooked to 'saved' that we want to reload.
					api.ThemifyTools.field = true;

					// Clear all option fields
					$('.themify-customizer-value-field').each(function () {
						$(this).val('').trigger('change');
					});

					// Clear the preview stylesheet
					api.previewer.send('themify-customize-clearall');

					// Restore site name
					var sessionSiteName = $('.customize-control-themify_logo').find('.site-name').val(),
							sessionTagline = $('.customize-control-themify_tagline').find('.site-name').val(),
							currentSiteName = $(this).data('sitename'),
							currentTagline = $(this).data('tagline');

					if (sessionSiteName != currentSiteName || sessionTagline != currentTagline) {
						// Save will be triggered once the option saving succeeds
						control.saveOption('blogname', currentSiteName);
						control.saveOption('blogdescription', currentTagline);
					} else {
						// Trigger save button manually
						control.saveOptionCallback();
					}
				}
			});
			
			////////////////////////////////////////////////////////////////////////////
			// Clear Tool End
			////////////////////////////////////////////////////////////////////////////
			
			////////////////////////////////////////////////////////////////////////////
			// Export Tool Start
			////////////////////////////////////////////////////////////////////////////
			
			$('.customize-export', control.container).on('click', function (e) {
				if($('#customize-header-actions').find('.save').val() != 'Published'){
					if (!window.confirm(themifyCustomizerControls.exportMessage)) {
						e.preventDefault();
					}
				}
			});
			
			////////////////////////////////////////////////////////////////////////////
			// Export Tool End
			////////////////////////////////////////////////////////////////////////////
		}
	});
	api.controlConstructor.themify_tools = api.ThemifyTools;
	////////////////////////////////////////////////////////////////////////////
	// Tools Control End
	////////////////////////////////////////////////////////////////////////////

	// Responsive Switcher Helper

	function themifyResponsiveHelper() {
		var buttons = '#customize-footer-actions .devices button', width, css;

		$( 'body' ).on( 'click', buttons, function() {
			var device = $( this ).data( 'device' ),
				preview = $( '#customize-preview' );

			if( typeof themifyCustomizerControls.responsiveBreakpoints === 'object'
				&& ( width = themifyCustomizerControls.responsiveBreakpoints[ device ] ) ) {
				if ( device === 'tablet_landscape' ) width = 976; // use this value for preview only
				css = {
					width: width + 'px',
					marginLeft: -width / 2
				};
			} else {
				css = { width: '', marginLeft: '' };
			}

			preview.css( css );
		} );
	}
	
	themifyResponsiveHelper();

	// Mobile Menu Customizer
	$( 'body' )
	.on( 'click', '#customize-control-start_mobile_menu_acc_ctrl > .themify-suba-toggle', function ( e ) {
		var menuPreview = $('#customize-preview > iframe')[0].contentWindow;
		if ( $( this ).closest( '.customize-control' ).hasClass( 'topen' ) ) {
			/* when Mobile Menu toggle is opened, show the sidemenu panel, activate the Desktop breakpoint and resize the preview window */
			$('#customize-footer-actions .preview-desktop').click();
			// wait 1 second for resizing to desktop to finish
			setTimeout( function(){
				if( $( '#customize-preview' ).width() > themifyCustomizerControls.mobile_menu_trigger_point ) {
					$( '#customize-preview' ).css( {
						width: themifyCustomizerControls.mobile_menu_trigger_point + 'px',
						marginLeft: ( $( '#customize-preview' ).width() - themifyCustomizerControls.mobile_menu_trigger_point ) / 2
					} );
				}
				// open mobile menu
				setTimeout( function(){
					if ( ! menuPreview.jQuery( 'body' ).hasClass( 'mobile-menu-visible' ) ) {
						menuPreview.jQuery( '#menu-icon span' ).click();
					}
				}, 1000 );

			}, 1000 );
		} else {
			// on closing Mobile Menu settings, re-activate desktop breakpoint
			$('#customize-footer-actions .preview-desktop').click();
		}
	})
	/* when switching to a breakpoint other than desktop, close the Mobile Menu settings */
	.on( 'click', '#customize-footer-actions button', function(){
		if( ! $( this ).hasClass( 'preview-desktop' ) ) {
			$( '#customize-control-start_mobile_menu_acc_ctrl.topen .themify-suba-toggle' ).click();
		}
	} );

})(wp, jQuery);
