/home/fdhrevqn/public_html/wp-content/themes/fox/inc/customizer/assets/js/customizer.js
/**
 * @since 1.0
 */
( function( $, api ) {
    
    var css = {};
        
    // MULTICHECKBOX
    // ========================
	api.controlConstructor.multicheckbox = api.Control.extend({
		ready: function() {
            var control = this,
                container = this.container,
                hidden = this.container.find( '.checkbox-result' ),
				inputs = this.container.find( 'input[type="checkbox"]' ),
                values = control.setting();
            
            if ( 'string' === typeof values ) values = values.split( ',' );
            
            /**
             * sum up the changes
             */
            var sumup = function() {
                
                var checkbox_values = container.find( 'input[type="checkbox"]:checked' ).map(
                    function(){
                        return this.value;
                    }
                ).get().join( ',' );
                
                control.setting.set( checkbox_values );
                
            }
            
            inputs.each(function(){
                var checked = values.indexOf( $(this).attr( 'value' ) ) > -1;
                $( this ).prop( 'checked', checked );
                $( this ).on( 'change', sumup );
            });
            
            // set default
            if ( 'string' !== typeof values ) values = values.join( ',' );
            hidden.val( values );
            
		}
	});
    
    // MULTISELECT
    // ========================
	api.controlConstructor.multiselect = api.Control.extend({
		ready: function() {
            var control = this,
                container = this.container,
                select = this.container.find( 'select' ),
                values = control.setting();
            
            if ( 'string' === typeof values ) values = values.split( ',' );
            
            select.on( 'change', function() {
                if ( ! select.val() ) {
                    values = []
                } else {
                    values = select.val()
                }
                control.setting.set( values );
                console.log( values )
            })
            
		}
	});
    
    // MULTIPLE TEXT
    // since 4.0
    // ========================
    api.controlConstructor.multiple_text = api.Control.extend({
        
        ready: function() {
            
            var control = this,
                value = control.setting(),
                container = this.container,
                wrap = container.find( '.fox-multiple-text-control' );
            
            try {
                
                value = JSON.parse( value );
                
            } catch( err ) {
                
                value = {}
                
            }
            
            /**
             * sum up the changes
             */
            var sumup = function() {
                
                var sum = {};
                wrap.find('[data-id]').each(function() {
                    
                    var input = $( this ),
                        id = input.data( 'id' ),
                        val = input.val();
                    
                    sum[ id ] = val;
                    
                });
                
                control.setting.set( JSON.stringify( sum ) );
                
            }
            
            /**
             * initial set up and bind change event
             */
            wrap.find('[data-id]').each(function() {
                
                var input = $( this ),
                    id = input.data( 'id' ),
                    val = value[ id ];
                
                input.val( val );
                input.on( 'change', sumup );
                
            });
            
        }
        
    });
    
    // BACKGROUND
    // since 4.0
    // ========================
    api.controlConstructor.fox_background = api.Control.extend({
        
        ready: function() {
            
            var control = this,
                value = control.setting(),
                container = this.container,
                wrap = container.find( '.fox-background-control' );
            
            try {
                
                value = JSON.parse( value );
                
            } catch( err ) {
                
                value = {}
                
            }
            
            /**
             * sum up the changes
             */
            var sumup = function() {
                
                var sum = {};
                wrap.find('[data-prop]').each(function() {
                    
                    var input = $( this ),
                        prop = input.data( 'prop' ),
                        val = input.val();
                    
                    sum[ prop ] = val;
                    
                });
                
                control.setting.set( JSON.stringify( sum ) );
                
            }
            
            /**
             * initial set up and bind change event
             */
            wrap.find('[data-prop]').each(function() {
                
                var input = $( this ),
                    prop = input.data( 'prop' ),
                    val = value[ prop ];
                
                input.val( val );
                input.on( 'change', sumup );
                
                /**
                 * color
                 */
                if ( input.is( '.background-input-color' ) ) {
                    
                    input.wpColorPicker({
                        change: function( event, ui ) {
                            input.val( ui.color.toString() );
                            input.trigger( 'change' );
                        },
                    });
                    
                }
                
                /**
                 * thickbox media
                 */
                if ( input.is( '.background-input-image' ) ) {
                    
                    var uploadWrapper = input.closest( '.wi-upload-wrapper' ),
                        holder = uploadWrapper.find( '.image-holder' ),
                        button = uploadWrapper.find( '.upload-image-button' );
                    
                    if ( val ) {
                        
                        wp.media.attachment( val ).fetch().then(function (data) {
                          // preloading finished
                          // after this you can use your attachment normally
                          var url = wp.media.attachment( val ).get('url');
                            holder.prepend( '<img src="' + url + '" />' );
                        });
                        
                        var change_text = 'Change Image'
                        if ( WITHEMES_ADMIN ) {
                            change_text = WITHEMES_ADMIN.l10n.change_image
                        }
                        
                        if ( button.is( 'button' ) ) {
                            button.text( change_text );
                        } else {
                            button.val( change_text );
                        }
                        
                    }
                    
                }
                
            });
            
        }
        
    });
    
    // BOX
    // since 4.0
    // ========================
    api.controlConstructor.box = api.Control.extend({
        
        ready: function() {
            
            var control = this,
                value = control.setting(),
                container = this.container,
                wrap = container.find( '.fox-box-control-wrapper' );
            
            try {
                
                value = JSON.parse( value );
                
            } catch( err ) {
                
                value = {}
                
            }
            
            /**
             * sum up the changes
             */
            var sumup = function() {
                
                var sum = {};
                wrap.find('[data-prop]').each(function() {
                    
                    var input = $( this ),
                        prop = input.data( 'prop' ),
                        val = input.val();
                    
                    sum[ prop ] = val;
                    
                });
                
                control.setting.set( JSON.stringify( sum ) );
                
            }
            
            /**
             * initial set up and bind change event
             */
            wrap.find('[data-prop]').each(function() {
                
                var input = $( this ),
                    prop = input.data( 'prop' ),
                    val = value[ prop ];
                
                input.val( val );
                input.on( 'change', sumup );
                
                /**
                 * color
                 */
                if ( input.is( '.box-input-color' ) ) {
                    
                    input.wpColorPicker({
                        change: function( event, ui ) {
                            input.val( ui.color.toString() );
                            input.trigger( 'change' );
                        },
                    });
                    
                }
                
            });
            
            /**
             * tab control
             */
            wrap.find( '.fox-box-control-tabs' ).find( 'li' ).on( 'click', function( e ) {
                
                e.preventDefault();
                
                var li = $( this ),
                    tab = li.data( 'tab' );
                
                wrap.find( '.fox-box-control-tabs' ).find( 'li' ).removeClass( 'active' );
                wrap.find( '.fox-box-control' ).removeClass( 'active' );
                
                li.addClass( 'active' );
                wrap.find( '.fox-box-control[data-tab="' + tab + '"]' ).addClass( 'active' );
                
            });
            
        }
        
    });
    
    // TYPOGRAPHY
    // since 4.0
    // ========================
    api.controlConstructor.typography = api.Control.extend({
        
        ready: function() {
            
            var control = this,
                value = control.setting(),
                container = this.container,
                wrap = container.find( '.fox-typography' );
            
            try {
                
                value = JSON.parse( value );
                
            } catch( err ) {
                
                value = {}
                
            }
            
            /**
             * sum up the changes
             */
            var sumup = function() {
                
                var sum = {};
                wrap.find('[data-prop]').each(function() {
                    
                    var input = $( this ),
                        prop = input.data( 'prop' ),
                        val = input.val();
                    
                    sum[ prop ] = val;
                    
                });
                
                control.setting.set( JSON.stringify( sum ) );
                
            }
            
            /**
             * initial set up and bind change event
             */
            wrap.find('[data-prop]').each(function() {
                
                var input = $( this ),
                    prop = input.data( 'prop' ),
                    val = value[ prop ];
                
                input.val( val );
                input.on( 'change', sumup );
                
            });
                
        }
        
    });
    
    // SELECT FONT
    // since 4.0
    // ========================
    api.controlConstructor.select_font = api.Control.extend({
        
        ready: function() {
            
            var control = this,
                value = control.setting(),
                container = this.container,
                wrap = container.find( '.fox-select-font-wrapper' ),
                select = wrap.find( 'select' ),
                div = container.find( '.fox-select-font' ),
                input = div.find( '.font-input' ),
                params = this.params,
                type = params.type,
                source = Object.keys( FOX_CUSTOMIZER.fonts );
            
            /**
             * we're given data from theme settings
             * in this, we use that data to display corresponding weights
             * value is like Open+Sans:400,400italic
             */
            var dataToDisplay = function( value ) {
                
                if ( ! value ) return;
                
                let explode = value.split( ':' ),
                    face = explode[0], // Open+Sans
                    styles = explode[1]; // 400,400italic
                
                // first hide all
                div
                .find( '.font-weight' )
                .removeClass( 'show' );
                
                // empty face
                if ( ! face ) return;
                
                // replace + by ' '
                face = face.replace( '+', '' );
                
                // if face is not in the font array
                // then don't care about weights
                if ( undefined === FOX_CUSTOMIZER.fonts[ face ] ) {
                    input.val( face );
                    return;
                }
                
                var availableStyles = FOX_CUSTOMIZER.fonts[ face ];
                
                // put the face to input first
                input.val( face );
                
                // case regular font
                if ( ! availableStyles.length ) {
                    return;
                }
                
                if ( styles ) {
                    styles = styles.split( ',' ).map(function(e){return e.trim();});
                }
                
                // show all available styles
                $.each( availableStyles, function( k, val ) {
                    
                    // the w_val is 400 while val is 'regular'
                    let w_val = val.toLowerCase();
                    
                    if ( 'regular' == w_val ) {
                        w_val = '400';
                    } else if ( 'italic' == w_val ) {
                        w_val = '400italic'
                    }
                    
                    // show the available style
                    let availableW = div.find( '.font-weight[data-weight="' + w_val + '"]' );
                    
                    // for some reason
                    if ( ! availableW.length ) return;
                    
                    availableW.addClass( 'show' );
                    
                    // then check to the style in the value
                    if ( ! styles ) return;
                    if ( styles.includes( val ) || styles.includes( w_val ) ) {
                        availableW.find( 'input[type="checkbox"]' ).prop( 'checked', true );
                    }
                    
                
                });
                
            }
            
            // capitalize
            // why JS doesn't have this function?
            var capitalize = function( s ) {
                if ( typeof s !== 'string' ) return '';
                return s.charAt(0).toUpperCase() + s.slice(1);
            }
            var toTitleCase = function( str ) {
                let explode = str.split( ' ' );
                $.each( explode, function( k, v ) {
                    explode[k] = capitalize( v );
                });
                return explode.join( ' ' );
            }
            
            /**
             * From displays to data, set final value to control
             */
            var displayToData = function() {
                
                // collect all available data
                let value = input.val(),
                    finalValue = '',
                    weights = [];
                
                // first hide all
                div
                .find( '.font-weight' )
                .removeClass( 'show' );
                
                // no value for some reason
                if ( ! value ) {
                    input.val( '' );
                    control.setting.set('');
                    return;
                }
                
                // to capitalize, like open sans --> Open Sans
                value = toTitleCase( value );
                
                let availableStyles = FOX_CUSTOMIZER.fonts[ value ];
                
                // set final value first
                finalValue = value;
                
                // case Google Font
                if ( undefined !== availableStyles ) {
                    
                    $.each( availableStyles, function( k, val ) {
                        
                        // the w_val is 400 while val is 'regular'
                        let w_val = val.toLowerCase();

                        if ( 'regular' == w_val ) {
                            w_val = '400';
                        } else if ( 'italic' == w_val ) {
                            w_val = '400italic'
                        }

                        // show the available style
                        let availableW = div.find( '.font-weight[data-weight="' + w_val + '"]' );
                        
                        // for some reason it's not found
                        if ( ! availableW.length ) return;
                        
                        // show it
                        availableW.addClass( 'show' );
                        
                        // if this is checked
                        // add this to weights array
                        if ( availableW.find( 'input[type="checkbox"]' ).prop( 'checked' ) ) {
                            weights.push( val );
                        }
                    
                    });
                    
                }
                
                if ( weights.length ) {
                    finalValue += ( ':' + weights.join( ',' ) );
                }
                
                // finally, set the value
                control.setting.set( finalValue );
                
            }
            
            // when input changed or checkbox changed, refresh it
            div.find( '.font-weight input[type="checkbox"]' ).on( 'change', displayToData );
            input.on( 'change', displayToData );
            
            input.autocomplete({
                source: source,
                // delay: 100,
                minLength: 1,
                autoFocus: false,
                select: function( event, ui ) {
                    
                    input.val( ui.item.value );
                    setTimeout( displayToData, 50 );
                    
                },
            });
            
            // if we have select, ie. it's inherit font mode
            if ( select.length ) {
                
                // onchange
                select.on( 'change', function() {

                    let value = $( this ).val();

                    // show the custom div
                    if ( ! FOX_CUSTOMIZER.primary_fonts.includes( value ) ) {

                        div.addClass( 'show' );

                        // run to take value from input
                        displayToData();

                    // hide the custom div
                    } else {

                        // and just set it as a regular select
                        div.removeClass( 'show' );
                        control.setting.set( value );

                    }

                });

                // if not in 3 values, it's a custom font
                // then run dataToDisplay of value
                if ( ! FOX_CUSTOMIZER.primary_fonts.includes( value ) ) {

                    div.addClass( 'show' );
                    select.val( 'font_custom' );
                    dataToDisplay( value );

                // otherwise, it's just a normal font
                // set it to select
                } else {

                    select.val( value );
                    div.removeClass( 'show' );

                }
            
            // otherwise, just run dataToDisplay of initial value
            } else {
            
                div.addClass( 'show' );
                dataToDisplay( value );
                
            }
            
		}
        
    });
    
    // IMAGE RADIO
    // ========================
    api.controlConstructor.image_radio = api.Control.extend({
        
        ready: function() {
            var control = this,
                container = this.container,
                params = this.params,
                type = params.type,
                input;
            
            input = container.find( 'input[type="radio"]' );
            input.filter('[value=\'' + control.setting() + '\']').prop( 'checked', true );

            input.on( 'change', function() {
                var value = container.find( 'input[type="radio"]:checked' ).val();
                control.setting.set( value );
            });

            // when setting changes
            this.setting.bind( function ( value ) {

                input.filter('[value=\'' + value + '\']').prop( 'checked', true );

            });
		}
        
    });
    
    // HOME BUILDER
    // since 4.5
    // ========================
    api.controlConstructor.home_builder = api.Control.extend({
        
        ready: function() {
            var control = this,
                container = this.container,
                params = this.params,
                type = params.type,
                input;
            
            
            /* ------------------------------------------------------------------------------------------------------------------------
            /* Homepage Builder
            /* @since 4.5
            ------------------------------------------------------------------------------------------------------------------------ */
            var builder = $( '#builder' )
            
            // -------------------- CONDITIONAL SHOW/HIDE
            // --------------------
            var run_conditional = function( self ) {
                
                // worst case
                if ( ! self || ! self.length ) {
                    return
                }
                
                var val = self.val(),
                    field = self.closest( '.section-field' ),
                    id = field.data( 'id' ),
                    section = field.closest( '.builder-section' )
                
                // we do not do conditional for section norm
                if ( section.hasClass( 'section-norm' ) ) {
                    return
                }
                
                // case 1: value change
                if ( FOX_CUSTOMIZER.builder_fields[ id ] && 'toggle' in FOX_CUSTOMIZER.builder_fields[ id ] ) {
                    
                    toggle = FOX_CUSTOMIZER.builder_fields[ id ][ 'toggle' ]
                    
                    // hide all fields in all values
                    for ( value in toggle ) {
                        affected_ids = toggle[ value ] // array of ids
                        
                        // only check this if field is visible
                        if ( ! field.hasClass( 'outvalue' ) ) {
                            if ( value == val ) {
                                continue
                            }
                        }
                        
                        for ( var j = 0; j < affected_ids.length; j++ ) {
                            affected_id = affected_ids[ j ]
                            section.find( '.section-field[data-id="' + affected_id + '"]' ).addClass( 'outvalue' )
                        }
                    }
                    
                    // now only show fields with value val
                    // only check this if field is visible
                    if ( ! field.hasClass( 'outvalue' ) ) {
                        affected_ids = toggle[ val ] // array of ids
                        if ( affected_ids ) {
                            for ( j = 0; j < affected_ids.length; j++ ) {
                                affected_id = affected_ids[ j ]
                                section.find( '.section-field[data-id="' + affected_id + '"]' ).removeClass( 'outvalue' )
                            }
                        }
                    }
                    
                }
                
            }
            
            // -------------------- POPULATE DATA
            // --------------------
            for ( var k = 0; k < FOX_CUSTOMIZER.builder_data.length; k++ ) {
                
                var section_data = FOX_CUSTOMIZER.builder_data[ k ],
                    section_id = section_data[ 'id' ]
                
                if ( ! section_id ) {
                    section_id = k + 1
                }
                
                var is_norm = ( section_id == 'norm' )
                
                html_section = $( '.section-sample' ).clone()
                html_section.removeClass( 'section-sample' )
                
                /**
                 * adjust radio name
                 */
                html_section.find( 'input[type="radio"]' ).each(function(){
                    var self = $( this ),
                        self_name = self.attr( 'name' )
                    
                    self.attr( 'name', 'radio-' + section_id + '-' + self_name )
                })
                
                if ( is_norm ) {
                    
                    html_section.addClass( 'section-norm' )
                    
                    // remove actions from norm
                    html_section.find( '.section-action-menu' ).remove() // remove actions
                    
                    // remove unnecessary tabs
                    html_section.find( '.section-tabs' ).find( 'li[data-tab="layout"]' ).remove()
                    html_section.find( '.section-tabs' ).find( 'li[data-tab="query"]' ).remove()
                    html_section.find( '.section-tabs' ).find( 'li[data-tab="heading"]' ).addClass( 'active' )
                    
                    // remove unneccesary fields
                    html_section.find( '.section-field[data-tab="layout"]' ).remove()
                    html_section.find( '.section-field[data-tab="query"]' ).remove()
                    html_section.find( '.section-field[data-tab="heading"]' ).addClass( 'intab' )
                    
                    html_section.find( '.section-field[data-id="sidebar"]' ).remove()
                    html_section.find( '.section-field[data-id="sidebar_position"]' ).remove()
                    
                } else {
                    
                    html_section.addClass( 'section-normal' )
                    
                }
                
                // set the key
                html_section.data( 'id', section_id )
                
                html_section.appendTo( builder )
                
                // populate data
                html_section.find( '.section-field' ).each( function() {
                    
                    var field = $( this ),
                        id = field.data( 'id' ),
                        input = field.find( '.changable-field' ),
                        type = field.data( 'type' ),
                        val = section_data[ id ]
                    
                    // ie. this field doesn't have input field
                    if ( ! input.length ) {
                        return
                    }
                    
                    // case section_data doesn't have value for id
                    if ( undefined === val ) {
                        return
                    }
                    
                    if ( 'text' == type || 'textarea' == type || 'select' == type || 'multiselect' == type ) {

                        input.val( val )

                    } else if ( 'checkbox' == type ) {

                        if ( val ) {
                            input.prop('checked', true)
                        } else {
                            input.prop('checked', false)
                        }

                    } else if ( 'multicheckbox' == type ) {
                        
                        if ( ! val ) {
                            val = []
                        }

                        input.each( function() {
                            if ( val.includes( $( this ).val() ) ) {
                                $( this ).prop('checked', true)
                            } else {
                                $( this ).prop('checked', false )
                            }
                        })

                    } else if ( 'radio' == type || 'image_radio' == type ) {

                        input.each( function() {
                            if ( val == $( this ).val() ) {
                                $( this ).prop('checked', true)
                            }
                        })

                    // all worst cases    
                    } else {

                        input.val( val )

                    }

                    run_conditional( input )
                    
                })

            }
            
            // -------------------- EDIT SECTION NAME
            // --------------------
            $( document ).on( 'click', '.section-edit-name', function( e ) {
                
                var self = $( this )
                
                e.preventDefault()
                self.closest( '.section-name' ).addClass( 'inedit' )
                
                // close menu
                $( '.section-action-menu ul' ).hide()
                
                setTimeout(function(){
                    self.closest( '.section-name' ).find( '.section-name-h' ).focus()
                }, 100 )
                
            })
            
            $( document ).on( 'click', function( e ) {
                if ( ! $( e.target ).is( '.section-name' ) && ! $( e.target ).closest( '.section-name' ).length ) {
                    $( '.section-name' ).removeClass( 'inedit' )
                }
            })
            
            // -------------------- SECTION ACTION MENU
            // --------------------
            $( document ).on( 'click', '.section-action-menu-btn', function( e ) {
                
                e.preventDefault()
                
                // close everything
                $( '.section-action-menu ul' ).hide()
                $( '.builder-section' ).css( 'z-index', '' )
                
                var a = $( this )
                a.closest( '.builder-section').css( 'z-index', '100' );
                a.next( 'ul' ).toggle()
                
            })
            
            $( document ).on( 'click', function( e ) {
                
                if ( ! $( e.target ).is( '.section-action-menu' ) && ! $( e.target ).closest( '.section-action-menu' ).length ) {
                    $( '.section-action-menu ul' ).hide()
                    $( '.builder-section' ).css( 'z-index', '' )
                }
                
            })
            
            // -------------------- HEADER TOGGLE
            // --------------------
            $( document ).on( 'click', '.section-name', function( e ) {
                e.preventDefault()
                
                // except the edit button
                if ( $( e.target ).is( '.section-action-menu' ) || $( e.target ).closest( '.section-action-menu' ).length ) {
                    return
                }
                
                var title = $( this ),
                    next_content = title.parent().next( '.section-content' ),
                    section = title.closest( '.builder-section' )
                
                if ( next_content.hasClass( 'active' ) ) {
                    next_content.slideUp( 'fast' ).removeClass( 'active' )
                    section.removeClass( 'active' )
                } else {
                    $( '.builder-section' ).removeClass( 'active' )
                    $( '.section-content.active' ).slideUp( 'fast' ).removeClass( 'active' )
                    next_content.slideDown( 'fast' ).addClass( 'active' )
                    section.addClass( 'active' )
                }
                
            });
            
            // -------------------- TABS
            // --------------------
            $( document ).on( 'click', '.section-tabs a', function( e ) {
                
                e.preventDefault()
                var a = $( this ),
                    tab = a.parent().data( 'tab' ),
                    tabs = a.closest( '.section-tabs' ),
                    section = a.closest( '.builder-section' )
                
                // tabs
                tabs.find( 'li' ).removeClass( 'active' )
                a.parent().addClass( 'active' )
                
                // fields
                section.find( '.section-field' ).removeClass( 'intab' )
                
                section.find( '.section-field[data-tab="' + tab + '"]' ).addClass( 'intab' )
                
            })
            
            // -------------------- TRIGGER CHANGE WHEN ANY FIELD CHANGED
            // --------------------
            $( document ).on( 'change', '.changable-field', function( e ) {
                
                var self = $( this )
                
                // don't trigger for name change
                if ( self.hasClass( 'section-name-h' ) ) {
                    return
                }
                
                run_conditional( self )
                sumup()
                
            })
            
            // -------------------- ADD SECTION
            // --------------------
            $( document ).on( 'click', '.add-section', function( e ) {
                
                e.preventDefault()
                
                var btn = $( this ),
                    position = btn.data( 'position' ),
                    currentSection = btn.closest( '.section-norm' ) // we only work with norm section
                
                if ( ! currentSection.length ) {
                    return
                }
                
                html_section = $( '.section-sample' ).clone()
                html_section.removeClass( 'section-sample' )
                
                /**
                 * adjust radio name
                 */
                var section_id = $( '.builder-section' ).length + 1
                html_section.find( 'input[type="radio"]' ).each(function(){
                    var self = $( this ),
                        self_name = self.attr( 'name' )
                    
                    self.attr( 'name', 'radio-' + section_id + '-' + self_name )
                })
                
                if ( 'after' == position ) {
                    html_section.insertAfter( currentSection )
                } else {
                    html_section.insertBefore( currentSection )
                }
                
                /* this code is to close all sections and open the newly added section
                $( '.builder-section' ).removeClass( 'active' )
                $( '.section-content.active' ).slideUp( 'fast' ).removeClass( 'active' )
                
                html_section.find( '.section-content' ).slideDown( 'fast' ).addClass( 'active' )
                html_section.addClass( 'active' )
                */
                
                // run conditional
                html_section.find( '.section-field' ).each( function() {
                    
                    var field = $( this ),
                        input = field.find( '.changable-field' )
                    
                    run_conditional( input )
                })
                
                // refresh the sortable function
                $( '#builder' ).sortable( 'refresh' )
                
                // activate sumup
                sumup()
                
                // -------------------- COLOR PICKER
                // --------------------
                // since 4.6.2.3
                $( '.builder-section:not(.section-sample) .color-picker' ).wpColorPicker({
                    change: _.throttle( function() { // For Customizer
                        $(this).trigger( 'change' );
                    }, 3000 )
                });
                
            })
            
            // -------------------- DUPLICATE / REMOVE SECTION
            // --------------------
            $( document ).on( 'click', '.section-action-menu a[data-action]', function( e ) {
                
                e.preventDefault()
                
                // close menu
                $( '.section-action-menu ul' ).hide()
                
                var self = $( this ),
                    section = self.closest( '.builder-section' ),
                    action = self.data( 'action' )
                
                switch( action ) {
                        
                    case 'duplicate' :
                        
                        // just in case
                        if ( section.hasClass( 'section-norm' ) ) {
                            return
                        }
                        
                        html_section = section.clone()
                        html_section.insertAfter( section )
                        
                        // copy all field values
                        html_section.find( '.changable-field' ).each( function() {
                            
                            var field = $( this ).closest( '.section-field' ),
                                field_id = field.data( 'id' )
                            
                            if ( $( this ).attr( 'type' ) == 'checkbox' ) {
                                
                                var thisvalue = $(this).attr( 'value')
                                
                                $( this ).prop('checked', section.find( '.section-field[data-id="' + field_id + '"] .changable-field[value="' + thisvalue + '"]' ).prop( 'checked') )
                            } else {
                                var original_value = section.find( '.section-field[data-id="' + field_id + '"] .changable-field' ).val()
                                $( this ).val( original_value )
                            }
                            
                        })
                        
                        // multicheckboxes
                        
                        // clone section name
                        html_section.find( '.section-name-h' ).val( section.find( '.section-name-h' ).val() + '[Clone]' )
                        
                        // close all sections
                        // open new section
                        $( '.builder-section' ).removeClass( 'active' )
                        // $( '.section-content.active' ).slideUp( 'fast' ).removeClass( 'active' )
                        
                        // close the new section in case it's open
                        html_section.find( '.section-content' ).hide().removeClass( 'active' )
                        html_section.removeClass( 'active' )
                        
                        // close menu
                        $( '.section-action-menu ul' ).hide()
                        
                        break;
                        
                    case 'delete' :
                        
                        // just in case
                        if ( section.hasClass( 'section-norm' ) ) {
                            return
                        }
                        
                        // close menu
                        $( '.section-action-menu ul' ).hide()
                        
                        var section_name = section.find( '.section-name-h' ).val()
                        if ( '' == section_name ) {
                            section_name = 'this section'
                        }
                        answer = confirm( 'Do you want to remove "' + section_name + '"? If you need to disable it temporarity, you can go to tab "Design" to change its visibility.' );
                        
                        if ( answer)  {
                            
                            section.slideUp( 'fast', function() {
                                section.remove()
                                sumup()
                            } )
                            
                        }
                        
                        break;
                        
                        default :
                        break;
                }
                
                // activate sumup
                sumup()
                
            });
            
            // -------------------- REORDER SORTABLE SECTIONS
            // --------------------
            var section_sortable = function() {
                
                $( '#builder' ).sortable({
                    
                    items : '> .builder-section',
                    placeholder: "sortable-placeholder",
                    handle: ".section-name",
                    
                    // when it changed, it changes the sections_order element
                    update: function( event, ui ) {
                        sumup()
                    }

                });

                $( '.section-content' ).disableSelection();
                
            }
            section_sortable()

            // -------------------- SUMUP CHANGES
            // --------------------
            var sumup = function() {

                var sum = []
                
                $( '.builder-section' ).each( function() {
                    
                    var section = $( this ),
                        section_data = {}
                    if ( section.hasClass( 'section-sample' ) ) return
                    
                    if ( section.hasClass( 'section-norm' ) ) {
                        section_data[ 'id' ] = 'norm'
                        section_data[ 'section_name' ] = 'Main Blog'
                    }
                    
                    // collect section fields
                    section.find( '.section-field' ).each( function() {
                        
                        var field = $( this ),
                            id = field.data( 'id' ),
                            input = field.find( '.changable-field' ),
                            type = field.data( 'type' ),
                            val = ''
                        
                        // ie. this field doesn't have input field
                        if ( ! input.length ) {
                            return
                        }
                        
                        if ( 'text' == type || 'textarea' == type || 'select' == type || 'multiselect' == type ) {
                            
                            val = input.val()
                            
                        } else if ( 'checkbox' == type ) {
                            
                            val = input.is(":checked") ? true : false;
                            
                        } else if ( 'multicheckbox' == type ) {
                            
                            val = []
                            field.find( '.changable-field:checked' ).each( function( ) {
                                var val_collect = $( this ).val()
                                val.push( val_collect )
                            })
                            
                        } else if ( 'radio' == type || 'image_radio' == type ) {
                            
                            input = field.find( '.changable-field:checked' )
                            if ( input.length ) {
                                val = input.val()
                            }
                            
                        // all worst cases    
                        } else {
                            
                            val = input.val()
                            
                        }
                        
                        section_data[ id ] = val
                        
                    })
                    
                    sum.push( section_data )
                    
                })
                
                control.setting.set( JSON.stringify( sum ) );

            }
            
            // -------------------- COLOR PICKER
            // --------------------
            $( '.builder-section:not(.section-sample) .color-picker' ).wpColorPicker({
                change: _.throttle( function() { // For Customizer
                    $(this).trigger( 'change' );
                }, 3000 )
            });
            
		}
        
    });
    
    /**
     * Control Toggle shows & hides optons conditionally for better UX
     *
     * @since 1.0
     */ 
    window.control_toggle = function( id, option ) {
            
        // TOGGLE OPTIONS
        //
        // Take some examples to illustrate
        // option = fox_logo_type
        // toggle = { 'text': [ 'fox_logo_size', 'fox_logo_face'], 'image' : [ 'fox_logo_width', 'fox_logo_height' ] }
        
        api.control( id, function( control ) {
        
            // Ignore options with display none state
            // Or has no toggle
            if ( 'none' == control.container.css( 'display' ) || undefined === option.toggle )
                return;

            // id = fox_logo_type
            api( id, function( setting ) {

                // value = 'text'
                // elements = [ 'fox_logo_size', 'fox_logo_face' ]
                $.each( option.toggle, function( value, elements ) {

                    // elementID = fox_logo_size
                    // each element ID should appear only once
                    $.each( elements, function( j, elementID ) {

                        api.control( elementID, function( control ) {
                            // to = current setting
                            var visibility = function ( to ) {
                                
                                // true and 'true'
                                if ( true === to ) {
                                    to = '1';
                                } else if ( false === to ) {
                                    to = '0';
                                }

                                // Hide everything except elements in current value
                                var toggle_Bool = ( to === value || ( undefined !== option.toggle[ to ] && option.toggle[ to ].indexOf( elementID ) > -1 ) );

                                var triggerEvent = toggle_Bool ? 'control_show' : 'control_hide';
                                
                                control.container
                                .toggle( toggle_Bool )
                                .trigger( triggerEvent );

                            };

                            visibility( setting.get() );

                            setting.bind( visibility );

                        }); // control

                    }); // each elements

                }); // option.toggle

            });

        }); // control

    } // funtion control_toggle
    
    /**
     * live CSS Update
     *
     * @since 1.0
     */
    window.liveCSS = function() {
        
        var cssdata = '';
        
        $.each(css, function( selector, cssComponents ) {
            
            cssdata += selector + '{';
                
            $.each( cssComponents, function( id, pair ) {
            
                // Check if this option is visible or not
                // It's pretty tricky, may we'll need better solution
                if ( $( '#customize-control-' + id ).css( 'display' ) == 'none' ) {
                    return;
                }
                
                cssdata += pair.property + ':' + pair.value + ';';
                
            });
            
            cssdata += '}';
            
        });
        
        api.previewer.send( 'update-fox-theme-style', cssdata );
        
    }
    
    /**
     * Live Preview and Conditionalize
     *
     * @since 1.0
     */
    api.bind( 'ready', function() {
        
        var settings = api.settings.settings;
        
        // Update the CSS whenever a setting is changed.
        _.each( api.settings.controls, function( option ) {
            
            var id = option.settings.default,
                transport = 'undefined' != typeof settings[id] ? settings[id].transport : '',
                selector = option.selector,
                property = option.property;
            
            // We're only interested colors
            if ( 'postMessage' == transport && 'color' == option.type && selector && property ) {
                
                if ( undefined == css[ selector ] ) {
                    css[ selector ] = {}
                }
                
                css[ selector ][ id ] = {
                    property : property,
                    value : api( id )()
                }
                
                api( id, function( value ) {
                    value.bind( function( to ) {

                        css[ selector ][ id ].value = to;
                        liveCSS();

                    });
                    
                });
                
            }
            
            /**
             * Toggle options for a better UX
             *
             * @since 1.0
             */
            api.control( id, function( control ) {
                
                if ( ! option.toggle ) return;
                
                control.container.on( 'control_show', function() {
                    control_toggle( id, option );
                }); // on show
                
                control.container.on( 'control_hide', function() {
                    
                    // value: leftright
                    // elements: left_1, left_2, right_1, right_2
                    $.each( option.toggle, function( value, elements ) {
                        
                        // elementID: // left_1
                        $.each( elements, function( j, elementID ) {
                        
                            api.control( elementID, function( control2 ) {
                                
                                control2.container
                                .hide()
                                .trigger( 'control_hide' );

                            }); // control
                            
                        });
                        
                    }); // each
                    
                }); // on show
            
            });
            
        }); // each
        
        // trigger control_toggle onload
        _.each( api.settings.controls, function( option ) {
            
            var id = option.settings.default;
            control_toggle( id, option );
            
        }); // each
        
        /**
         * homepage builder select change label
         * @since 4.3
         */
        $( 'select' ).each(function(){

            var self = $( this ),
                id = self.attr( 'id' ),
                section = self.closest( '.control-section' ),
                section_meta = section.find( '.section-meta' )
            
            // ie. the cat
            if ( id && id.match( /^_customize-input-bf_\d+_cat$/g ) ) {

                var i = id.replace( '_customize-input-bf_', '' );
                i = i.replace( '_cat', '' )
                
                self.on( 'change', function() {
                    
                    var key = self.val(),
                        val = self.find( 'option[value="'+ key+'"]' ).html()
                    
                    if ( '...' == val ) {
                        val = '---'
                    }
                    
                    var currentTitleSpan = section_meta.find( 'h3 span' ).html()

                    section_meta.find( 'h3' ).html( '<span class="customize-action">' + currentTitleSpan + '</span>: ' + val )
                    
                    var parentLi = $( 'li.control-section[aria-owns="sub-accordion-section-wi_bf_' + i + '"]')
                    parentLi.find( 'h3' ).html( val );

                });
            }


        })
        
        /**
         * Group homepage builder options into group
         * @since 4.3
         */
        $( '.customize-pane-child' ).each( function() {

            var ul = $( this ),
                id = ul.attr( 'id' )

            // page builder panel
            if ( id && id.match( /sub-accordion-section-wi_bf_\d$/g ) ) {

                var i = id.replace( 'sub-accordion-section-wi_bf_', '' )
                
                var hide_all_li = function() {
                    ul.find( 'li.customize-control:not(.customize-control-heading,.section-meta)' ).each(function(){
                        var li_id = $( this ).attr( 'id' )
                        
                        if ( li_id && li_id.match( /^customize-control-bf_\d+_cat$/g ) ) {
                            return;
                        }
                        if ( li_id && li_id.match( /^customize-control-bf_\d+_shortcode/g ) ) {
                            return;
                        }
                        if ( li_id && li_id.match( /^customize-control-bf_\d+_main_sidebar/g ) ) {
                            return;
                        }
                        if ( li_id && li_id.match( /^customize-control-bf_\d+_sidebar_layout/g ) ) {
                            return;
                        }
                        
                        $( this ).addClass( 'li-hide' )
                        
                    });
                }
                
                hide_all_li();

                ul.find( 'li.customize-control-heading' ).each( function(){

                    var li = $( this )
                    li.css( 'cursor', 'pointer' )

                    li.on( 'click', function() {

                        // hide all
                        hide_all_li();
                        
                        // active class
                        if ( li.hasClass( 'active') ) {
                            li.removeClass( 'active' )
                        } else {
                            ul.find( 'li.customize-control-heading' ).removeClass( 'active' )
                            li.addClass( 'active' )
                        }

                        var nextLi = li

                        while ( nextLi ) {

                            nextLi = nextLi.next()
                            if ( ! nextLi || ! nextLi.length || nextLi.hasClass( 'customize-control-heading' ) ) {
                                nextLi = false
                            } else {
                                if ( li.hasClass( 'active') ) {
                                    nextLi.removeClass( 'li-hide' )
                                } else {
                                    nextLi.addClass( 'li-hide' )
                                }
                            }
                        }

                    });

                })

            }


        });
        
        /**
         * Drag & Drop Builder Sections
         * @since 4.4
         */
        var sections = $( "#sub-accordion-panel-wi_homepage" ),
            sections_order_control = api( 'wi_sections_order' );
        
        // 01 - label the sections
        sections.find( '>li' ).each( function(){
            
            var li = $( this ),
                id = li.attr( 'id' )
            if ( ! id || id == undefined ) {
                return
            }
            
            var index = id.replace( 'accordion-section-wi_bf_', '' )
            if ( isNaN( index ) ) {
                if ( id == 'accordion-section-wi_main_stream' ) {
                    index = 'main'
                } else {
                    return
                }
            }
            
            // ok, now we have the index
            li.attr( 'data-index', index )
            li.find( '.accordion-section-title' ).attr( 'title', 'Drag & drop to change section orders' )
            
        });
        
        var index_result = function() {
            var indexes = []
            sections.find( '>li[data-index]' ).each(function(){
                indexes.push( $( this ).data('index') )
            })
            
            return indexes.join(',')
        }
        
        // 02 - sortable them
        sections.sortable({
            items : '>li[data-index]',
            
            axis: "y",
            
            // when it changed, it changes the sections_order element
            update: function( event, ui ) {
                
                sections.find( '>li[data-index]' ).each(function( order ) {
                    
                    var index = $( this ).data('index'),
                        section_id = 'wi_bf_' + index
                    if ( isNaN( index ) ) {
                        section_id = 'wi_main_stream'
                    }
                    
                    api.section( section_id ).priority( 10 * ( order + 1 ) )
                })
                
                setTimeout(function() {
                    sections_order_control.set( index_result() )
                }, 100 );
                
            }
            
        });
        
        // yes, dont need it
        // sections.disableSelection();
        
        /**
         * Option Search
         * @since 4.4
         */
        
        function swap( json ){
            var ret = {};
            for(var key in json){
            ret[json[key]] = key;
            }
            return ret;
        }
        
        $( '#customize-header-actions' ).append( '<input type="search" placeholder="Search option.." class="goto" tabindex="1" onfocus="this.select()" />' );
        
        var goto_input = $( '.goto' ),
            keywords = Object.values( FOX_CUSTOMIZER.hint ),
            hint_reverse = swap( FOX_CUSTOMIZER.hint ),
            args = {
                minLength: 1,
                delay: 0,
                autoFocus: false,
                select: function( event, ui ) {
                    
                    if ( hint_reverse[ ui.item.value ] ) {
                        
                        // go to the option
                        api.control( hint_reverse[ ui.item.value ] ).focus()
                        
                        // reset the text
                        this.value = "";
                        return false;
                        
                    }
                    
                },
                classes: {
                    "ui-autocomplete": "blah"
                }
            }
        
        args.source = keywords
        
        goto_input.autocomplete( args )
        
        // cmd F bind
        window.onkeydown = function( event ) {
            
            if((event.ctrlKey || event.metaKey) && event.which == 70) {
                event.preventDefault();
                
                goto_input.focus()
            }
            
        }
        
        /**
         * Append a Documentation Link in the header
         * @since 4.5
         */
        $( '#customize-info .preview-notice' ).after( '<a href="https://foxdocs.withemes.com/" target="_blank" class="foxdocs-link">Fox\'s Documentation <i class="dashicons dashicons-external"></i></a>' )
        
    });
    
} )( jQuery, wp.customize );