/*=============================================================== # 1. Init Customizer ===============================================================*/ var cscoCustomizer = { initialized: false, /** * Initialize the object. * * @since 3.0.17 * @returns {null} */ initialize: function() { var self = this; // We only need to initialize once. if ( self.initialized ) { return; } setTimeout( function() { cscoCustomizer.util.webfonts.standard.initialize(); cscoCustomizer.util.webfonts.google.initialize(); }, 150 ); // Mark as initialized. self.initialized = true; } }; cscoCustomizer.initialize(); var cscoCustomizer = cscoCustomizer || {}; cscoCustomizer = jQuery.extend( cscoCustomizer, { /** * A collection of utility methods. * * @since 3.0.17 */ util: { /** * A collection of utility methods for webfonts. * * @since 3.0.17 */ webfonts: { /** * Google-fonts related methods. * * @since 3.0.17 */ google: { /** * An object containing all Google fonts. * * to set this call this.setFonts(); * * @since 3.0.17 */ fonts: {}, /** * Init for google-fonts. * * @since 3.0.17 * @returns {null} */ initialize: function() { var self = this; self.setFonts(); }, /** * Set fonts in this.fonts * * @since 3.0.17 * @returns {null} */ setFonts: function() { var self = this; // No need to run if we already have the fonts. if ( !_.isEmpty( self.fonts ) ) { return; } // Make an AJAX call to set the fonts object (alpha). jQuery.post( ajaxurl, { 'action': 'csco_typography_fonts_google_all_get' }, function( response ) { // Get fonts from the JSON array. self.fonts = JSON.parse( response ); // Convert array to object. if ( Array.isArray( self.fonts.items ) ) { let fontsBuffer = {}; self.fonts.items.forEach(font => { fontsBuffer[font.family] = font; }); self.fonts.items = fontsBuffer; } } ); }, /** * Gets all properties of a font-family. * * @since 3.0.17 * @param {string} family - The font-family we're interested in. * @returns {Object} */ getFont: function( family ) { var self = this, fonts = self.getFonts(); if ( 'undefined' === typeof fonts[ family ] ) { return false; } return fonts[ family ]; }, /** * Gets all properties of a font-family. * * @since 3.0.17 * @param {string} order - How to order the fonts (alpha|popularity|trending). * @param {int} number - How many to get. 0 for all. * @returns {Object} */ getFonts: function( order, category, number ) { var self = this, ordered = {}, categorized = {}, plucked = {}; // Make sure order is correct. order = order || 'alpha'; order = ( 'alpha' !== order && 'popularity' !== order && 'trending' !== order ) ? 'alpha' : order; // Make sure number is correct. number = number || 0; number = parseInt( number, 10 ); // Order fonts by the 'order' argument. if ( 'alpha' === order ) { ordered = jQuery.extend( {}, self.fonts.items ); } else { _.each( self.fonts.order[ order ], function( family ) { ordered[ family ] = self.fonts.items[ family ]; } ); } // If we have a category defined get only the fonts in that category. if ( '' === category || !category ) { categorized = ordered; } else { _.each( ordered, function( font, family ) { if ( category === font.category ) { categorized[ family ] = font; } } ); } // If we only want a number of font-families get the 1st items from the results. if ( 0 < number ) { _.each( _.first( _.keys( categorized ), number ), function( family ) { plucked[ family ] = categorized[ family ]; } ); return plucked; } return categorized; }, /** * Gets the variants for a font-family. * * @since 3.0.17 * @param {string} family - The font-family we're interested in. * @returns {Array} */ getVariants: function( family ) { var self = this, font = self.getFont( family ); // Early exit if font was not found. if ( !font ) { return false; } // Early exit if font doesn't have variants. if ( _.isUndefined( font.variants ) ) { return false; } // Return the variants. return font.variants; } }, /** * Standard fonts related methods. * * @since 3.0.17 */ standard: { /** * An object containing all Standard fonts. * * to set this call this.setFonts(); * * @since 3.0.17 */ fonts: {}, /** * Init for google-fonts. * * @since 3.0.17 * @returns {null} */ initialize: function() { var self = this; self.setFonts(); }, /** * Set fonts in this.fonts * * @since 3.0.17 * @returns {null} */ setFonts: function() { var self = this; // No need to run if we already have the fonts. if ( !_.isEmpty( self.fonts ) ) { return; } // Make an AJAX call to set the fonts object. jQuery.post( ajaxurl, { 'action': 'csco_typography_fonts_standard_all_get' }, function( response ) { // Get fonts from the JSON array. self.fonts = JSON.parse( response ); } ); }, /** * Gets the variants for a font-family. * * @since 3.0.17 * @returns {Array} */ getVariants: function() { return [ 'regular', 'italic', '700', '700italic' ]; } }, /** * Figure out what this font-family is (google/standard) * * @since 3.0.20 * @param {string} family - The font-family. * @returns {string|false} - Returns string if found (google|standard) * and false in case the font-family is an arbitrary value * not found anywhere in our font definitions. */ getFontType: function( family ) { var self = this; // Check for standard fonts first. if ( 'undefined' !== typeof self.standard.fonts[ family ] || ( 'undefined' !== typeof self.standard.fonts.stack && 'undefined' !== typeof self.standard.fonts.stack[ family ] ) ) { return 'standard'; } // Check in googlefonts. if ( 'undefined' !== typeof self.google.fonts.items[ family ] ) { return 'google'; } return false; } }, /** * Parses HTML Entities. * * @since 3.0.34 * @param {string} str - The string we want to parse. * @returns {string} */ parseHtmlEntities: function( str ) { var parser = new DOMParser, dom = parser.parseFromString( '' + str, 'text/html' ); return dom.body.textContent; } } } ); /*=============================================================== # 2. Control Dimension ===============================================================*/ wp.customize.controlConstructor[ 'dimension' ] = wp.customize.Control.extend( { /** * Set up. * * @returns {void} */ ready: function() { var control = this; // Notifications. control.themeNotifications(); }, /** * Handles notifications. * * @returns {void} */ themeNotifications: function() { var control = this; wp.customize( control.id, function( setting ) { setting.bind( function( value ) { var code = 'long_title'; if ( false === control.validateCssValue( value ) ) { setting.notifications.add( code, new wp.customize.Notification( code, { type: 'error', message: 'Invalid Value' } ) ); } else { setting.notifications.remove( code ); } } ); } ); }, validateCssValue: function( value ) { var validUnits = [ 'fr', 'rem', 'em', 'ex', '%', 'px', 'cm', 'mm', 'in', 'pt', 'pc', 'ch', 'vh', 'vw', 'vmin', 'vmax' ], numericValue, unit; // Whitelist values. if ( !value || '' === value || 0 === value || '0' === value || 'auto' === value || 'inherit' === value || 'initial' === value ) { return true; } // Skip checking if calc(). if ( 0 <= value.indexOf( 'calc(' ) && 0 <= value.indexOf( ')' ) ) { return true; } // Get the numeric value. numericValue = parseFloat( value ); // Get the unit unit = value.replace( numericValue, '' ); // Allow unitless. if ( !unit ) { return true; } // Check the validity of the numeric value and units. return ( !isNaN( numericValue ) && -1 !== validUnits.indexOf( unit ) ); } } ); /*=============================================================== # 3. Control Multicheck ===============================================================*/ wp.customize.controlConstructor['multicheck'] = wp.customize.Control.extend( { /** * Set up. * * @returns {void} */ ready: function() { var control = this; // Save the value control.container.on( 'change', 'input', function() { var value = [], i = 0; // Build the value as an object using the sub-values from individual checkboxes. jQuery.each( control.params.choices, function( key ) { if ( control.container.find( 'input[value="' + key + '"]' ).is( ':checked' ) ) { control.container.find( 'input[value="' + key + '"]' ).parent().addClass( 'checked' ); value[ i ] = key; i++; } else { control.container.find( 'input[value="' + key + '"]' ).parent().removeClass( 'checked' ); } } ); // Update the value in the customizer. control.setting.set( value ); } ); } } ); /*=============================================================== # 4. Control Typography ===============================================================*/ wp.customize.controlConstructor[ 'typography' ] = wp.customize.Control.extend( { /** * Embed the control in the document. * * Override the embed() method to do nothing, * so that the control isn't embedded on load, * unless the containing section is already expanded. * * @returns {null} */ embed: function() { var control = this, sectionId = control.section(); if ( !sectionId ) { return; } wp.customize.section( sectionId, function( section ) { if ( section.expanded() || wp.customize.settings.autofocus.control === control.id ) { control.actuallyEmbed(); } else { section.expanded.bind( function( expanded ) { if ( expanded ) { control.actuallyEmbed(); } } ); } } ); }, /** * Deferred embedding of control when actually * * This function is called in Section.onChangeExpanded() so the control * will only get embedded when the Section is first expanded. * * @returns {null} */ actuallyEmbed: function() { var control = this; if ( 'resolved' === control.deferred.embedded.state() ) { return; } control.renderContent(); initControlCollapsible(); // This triggers control.ready(). control.deferred.embedded.resolve(); }, /** * Set up. * * @returns {void} */ ready: function() { var control = this, value = control.setting._value; control.deferred.embedded.done( function() { control.renderFontSelector(); control.renderVariantSelector(); // Font-size. if ( 'undefined' !== typeof control.params.default[ 'font-size' ] ) { control.container.on( 'change keyup paste', '.font-size input', function() { control.saveValue( 'font-size', jQuery( this ).val() ); } ); } // Line-height. if ( 'undefined' !== typeof control.params.default[ 'line-height' ] ) { control.container.on( 'change keyup paste', '.line-height input', function() { control.saveValue( 'line-height', jQuery( this ).val() ); } ); } // Letter-spacing. if ( 'undefined' !== typeof control.params.default[ 'letter-spacing' ] ) { value[ 'letter-spacing' ] = ( jQuery.isNumeric( value[ 'letter-spacing' ] ) ) ? value[ 'letter-spacing' ] + 'px' : value[ 'letter-spacing' ]; control.container.on( 'change keyup paste', '.letter-spacing input', function() { value[ 'letter-spacing' ] = ( jQuery.isNumeric( jQuery( this ).val() ) ) ? jQuery( this ).val() + 'px' : jQuery( this ).val(); control.saveValue( 'letter-spacing', value[ 'letter-spacing' ] ); } ); } // Word-spacing. if ( 'undefined' !== typeof control.params.default[ 'word-spacing' ] ) { control.container.on( 'change keyup paste', '.word-spacing input', function() { control.saveValue( 'word-spacing', jQuery( this ).val() ); } ); } // Text-align. if ( 'undefined' !== typeof control.params.default[ 'text-align' ] ) { control.container.on( 'change', '.text-align input', function() { control.saveValue( 'text-align', jQuery( this ).val() ); } ); } // Text-transform. if ( 'undefined' !== typeof control.params.default[ 'text-transform' ] ) { jQuery( control.selector + ' .text-transform select' ).selectWoo().on( 'change', function() { control.saveValue( 'text-transform', jQuery( this ).val() ); } ); } // Text-decoration. if ( 'undefined' !== typeof control.params.default[ 'text-decoration' ] ) { jQuery( control.selector + ' .text-decoration select' ).selectWoo().on( 'change', function() { control.saveValue( 'text-decoration', jQuery( this ).val() ); } ); } } ); }, /** * Adds the font-families to the font-family dropdown * and instantiates selectWoo. */ renderFontSelector: function() { var control = this, selector = control.selector + ' .font-family select', data = [], standardFonts = [], googleFonts = [], value = control.setting._value, fonts = control.getFonts(), fontSelect, controlFontFamilies; // Format standard fonts as an array. if ( !_.isUndefined( fonts.standard ) ) { _.each( fonts.standard, function( font ) { standardFonts.push( { id: font.family.replace( /"/g, ''' ), text: font.label } ); } ); } // Format google fonts as an array. if ( !_.isUndefined( fonts.google ) ) { _.each( fonts.google, function( font ) { googleFonts.push( { id: font.family, text: font.family } ); } ); } // Do we have custom fonts? controlFontFamilies = {}; if ( !_.isUndefined( control.params ) && !_.isUndefined( control.params.choices ) && !_.isUndefined( control.params.choices.fonts ) && !_.isUndefined( control.params.choices.fonts.families ) ) { controlFontFamilies = control.params.choices.fonts.families; } // Combine forces and build the final data. data = jQuery.extend( {}, controlFontFamilies, { default: { text: cscoCustomizerConfig.defaultCSSValues, children: [ { id: '', text: cscoCustomizerConfig.defaultBrowserFamily }, { id: 'initial', text: 'initial' }, { id: 'inherit', text: 'inherit' } ] }, standard: { text: cscoCustomizerConfig.standardFonts, children: standardFonts }, google: { text: cscoCustomizerConfig.googleFonts, children: googleFonts } } ); data = _.values( data ); // Instantiate selectWoo with the data. fontSelect = jQuery( selector ).selectWoo( { data: data } ); // Set the initial value. if ( value[ 'font-family' ] || '' === value[ 'font-family' ] ) { value[ 'font-family' ] = cscoCustomizer.util.parseHtmlEntities( value[ 'font-family' ].replace( /'/g, '"' ) ); fontSelect.val( value[ 'font-family' ] ).trigger( 'change' ); } // When the value changes fontSelect.on( 'change', function() { // Set the value. control.saveValue( 'font-family', jQuery( this ).val() ); // Re-init variants selector. control.renderVariantSelector(); } ); }, /** * Renders the variants selector using selectWoo * Displays font-variants for the currently selected font-family. */ renderVariantSelector: function() { var control = this, value = control.setting._value, fontFamily = value[ 'font-family' ], selector = control.selector + ' .variant select', data = [], isValid = false, fontType = cscoCustomizer.util.webfonts.getFontType( fontFamily ), variants = [ '', 'regular', 'italic', '700', '700italic' ], fontWeight, variantSelector, fontStyle; if ( 'google' === fontType ) { variants = cscoCustomizer.util.webfonts.google.getVariants( fontFamily ); } // Check if we've got custom variants defined for this font. if ( !_.isUndefined( control.params ) && !_.isUndefined( control.params.choices ) && !_.isUndefined( control.params.choices.fonts ) && !_.isUndefined( control.params.choices.fonts.variants ) ) { // Check if we have variants for this font-family. if ( !_.isUndefined( control.params.choices.fonts.variants[ fontFamily ] ) ) { variants = control.params.choices.fonts.variants[ fontFamily ]; } } if ( 'inherit' === fontFamily || 'initial' === fontFamily || '' === fontFamily ) { value.variant = 'inherit'; variants = [ '' ]; jQuery( control.selector + ' .variant' ).hide(); } if ( 1 >= variants.length ) { jQuery( control.selector + ' .variant' ).hide(); value.variant = variants[ 0 ]; control.saveValue( 'variant', value.variant ); if ( '' === value.variant || !value.variant ) { fontWeight = ''; fontStyle = ''; } else { fontWeight = ( !_.isString( value.variant ) ) ? '400' : value.variant.match( /\d/g ); fontWeight = ( !_.isObject( fontWeight ) ) ? '400' : fontWeight.join( '' ); fontStyle = ( value.variant && -1 !== value.variant.indexOf( 'italic' ) ) ? 'italic' : 'normal'; } control.saveValue( 'font-weight', fontWeight ); control.saveValue( 'font-style', fontStyle ); return; } jQuery( control.selector + ' .font-backup' ).show(); jQuery( control.selector + ' .variant' ).show(); _.each( variants, function( variant ) { if ( value.variant === variant ) { isValid = true; } data.push( { id: variant, text: variant } ); } ); if ( !isValid ) { value.variant = 'regular'; } if ( jQuery( selector ).hasClass( 'select2-hidden-accessible' ) ) { jQuery( selector ).selectWoo( 'destroy' ); jQuery( selector ).empty(); } // Instantiate selectWoo with the data. variantSelector = jQuery( selector ).selectWoo( { data: data } ); variantSelector.val( value.variant ).trigger( 'change' ); variantSelector.on( 'change', function() { control.saveValue( 'variant', jQuery( this ).val() ); if ( 'string' !== typeof value.variant ) { value.variant = variants[ 0 ]; } fontWeight = ( !_.isString( value.variant ) ) ? '400' : value.variant.match( /\d/g ); fontWeight = ( !_.isObject( fontWeight ) ) ? '400' : fontWeight.join( '' ); fontStyle = ( -1 !== value.variant.indexOf( 'italic' ) ) ? 'italic' : 'normal'; control.saveValue( 'font-weight', fontWeight ); control.saveValue( 'font-style', fontStyle ); } ); }, /** * Get fonts. */ getFonts: function() { var control = this, initialGoogleFonts = cscoCustomizer.util.webfonts.google.getFonts(), googleFonts = {}, googleFontsSort = 'alpha', googleFontsNumber = 0, standardFonts = {}; // Get google fonts. if ( !_.isEmpty( control.params.choices.fonts.google ) ) { if ( 'alpha' === control.params.choices.fonts.google[ 0 ] || 'popularity' === control.params.choices.fonts.google[ 0 ] || 'trending' === control.params.choices.fonts.google[ 0 ] ) { googleFontsSort = control.params.choices.fonts.google[ 0 ]; if ( !isNaN( control.params.choices.fonts.google[ 1 ] ) ) { googleFontsNumber = parseInt( control.params.choices.fonts.google[ 1 ], 10 ); } googleFonts = cscoCustomizer.util.webfonts.google.getFonts( googleFontsSort, '', googleFontsNumber ); } else { _.each( control.params.choices.fonts.google, function( fontName ) { if ( 'undefined' !== typeof initialGoogleFonts[ fontName ] && !_.isEmpty( initialGoogleFonts[ fontName ] ) ) { googleFonts[ fontName ] = initialGoogleFonts[ fontName ]; } } ); } } else { googleFonts = cscoCustomizer.util.webfonts.google.getFonts( googleFontsSort, '', googleFontsNumber ); } // Get standard fonts. if ( !_.isEmpty( control.params.choices.fonts.standard ) ) { _.each( control.params.choices.fonts.standard, function( fontName ) { if ( 'undefined' !== typeof cscoCustomizer.util.webfonts.standard.fonts[ fontName ] && !_.isEmpty( cscoCustomizer.util.webfonts.standard.fonts[ fontName ] ) ) { standardFonts[ fontName ] = {}; if ( 'undefined' !== cscoCustomizer.util.webfonts.standard.fonts[ fontName ].stack && !_.isEmpty( cscoCustomizer.util.webfonts.standard.fonts[ fontName ].stack ) ) { standardFonts[ fontName ].family = cscoCustomizer.util.webfonts.standard.fonts[ fontName ].stack; } else { standardFonts[ fontName ].family = googleFonts[ fontName ]; } if ( 'undefined' !== cscoCustomizer.util.webfonts.standard.fonts[ fontName ].label && !_.isEmpty( cscoCustomizer.util.webfonts.standard.fonts[ fontName ].label ) ) { standardFonts[ fontName ].label = cscoCustomizer.util.webfonts.standard.fonts[ fontName ].label; } else if ( !_.isEmpty( standardFonts[ fontName ] ) ) { standardFonts[ fontName ].label = standardFonts[ fontName ]; } } else { standardFonts[ fontName ] = { family: fontName, label: fontName }; } } ); } else { _.each( cscoCustomizer.util.webfonts.standard.fonts, function( font, id ) { standardFonts[ id ] = { family: font.stack, label: font.label }; } ); } return { google: googleFonts, standard: standardFonts }; }, /** * Saves the value. */ saveValue: function( property, value ) { var control = this, input = control.container.find( '.typography-hidden-value' ), val = control.setting._value; val[ property ] = value; jQuery( input ).attr( 'value', JSON.stringify( val ) ).trigger( 'change' ); control.setting.set( val ); } } ); /*=============================================================== # 5. Control Color and Color Alpha Dark ===============================================================*/ wp.customize.bind( 'ready', function() { var colors = document.querySelectorAll( '.customize-control-color[id*="is_dark"], .customize-control-color-alpha[id*="is_dark"]' ); [].forEach.call( colors, function( color ) { let expand = document.createElement( 'span' ); expand.classList.add( 'expand-setting' ); expand.setAttribute( 'title', cscoCustomizerConfig.advanced_settings ); expand.onclick = function() { if ( color.matches( '.customize-control-color-open' ) ) { color.classList.remove( 'customize-control-color-open' ); } else { color.classList.add( 'customize-control-color-open' ); } } color.prepend( expand ); } ); } ); /*=============================================================== # 6. Control Collapsible ===============================================================*/ function initControlCollapsible() { var collapsibles = document.querySelectorAll( '.customize-control-collapsible' ); [].forEach.call( collapsibles, function( collapsible ) { var subControls = collapsible.nextElementSibling; // Initialization. if ( !collapsible.contains( collapsible.querySelector( '.customize-collapsed' ) ) ) { collapsible.classList.add( 'customize-control-collapsed' ); while ( subControls ) { if ( subControls.matches( '.customize-control-collapsible' ) ) break; subControls.classList.add( 'customize-control-hidden' ); subControls = subControls.nextElementSibling; } } // Add event onclick to collapsible. collapsible.onclick = function() { var status = this.matches( '.customize-control-collapsed' ) ? 'visible' : 'hidden'; // Switch control collapsed. if ( 'visible' === status ) { this.classList.remove( 'customize-control-collapsed' ); } else { this.classList.add( 'customize-control-collapsed' ); } var subControls = this.nextElementSibling; // Switch visibility for subcontrols. while ( subControls ) { if ( subControls.matches( '.customize-control-collapsible' ) ) break; if ( 'visible' === status ) { subControls.classList.remove( 'customize-control-hidden' ); } else { subControls.classList.add( 'customize-control-hidden' ); } subControls = subControls.nextElementSibling; } }; } ); } wp.customize.bind( 'ready', initControlCollapsible ); /*=============================================================== # 7. Control Alpha Color ===============================================================*/ /** * Override the stock color.js toString() method to add support for * outputting RGBa or Hex. */ Color.prototype.toString = function( flag ) { // If our no-alpha flag has been passed in, output RGBa value with 100% opacity. // This is used to set the background color on the opacity slider during color changes. if ( 'no-alpha' == flag ) { return this.toCSS( 'rgba', '1' ).replace( /\s+/g, '' ); } // If we have a proper opacity value, output RGBa. if ( 1 > this._alpha ) { return this.toCSS( 'rgba', this._alpha ).replace( /\s+/g, '' ); } // Proceed with stock color.js hex output. var hex = parseInt( this._color, 10 ).toString( 16 ); if ( this.error ) { return ''; } if ( hex.length < 6 ) { for ( var i = 6 - hex.length - 1; i >= 0; i-- ) { hex = '0' + hex; } } return '#' + hex; }; /** * Given an RGBa, RGB, or hex color value, return the alpha channel value. */ function csco_get_alpha_value_from_color( value ) { var alphaVal; // Remove all spaces from the passed in value to help our RGBa regex. value = value.replace( / /g, '' ); if ( value.match( /rgba\(\d+\,\d+\,\d+\,([^\)]+)\)/ ) ) { alphaVal = parseFloat( value.match( /rgba\(\d+\,\d+\,\d+\,([^\)]+)\)/ )[1] ).toFixed(2) * 100; alphaVal = parseInt( alphaVal ); } else { alphaVal = 100; } return alphaVal; } /** * Force update the alpha value of the color picker object and maybe the alpha slider. */ function csco_update_alpha_value_on_color_control( alpha, $control, $alphaSlider, update_slider ) { var iris, colorPicker, color; iris = $control.data( 'a8cIris' ); colorPicker = $control.data( 'wpWpColorPicker' ); // Set the alpha value on the Iris object. iris._color._alpha = alpha; // Store the new color value. color = iris._color.toString(); // Set the value of the input. $control.val( color ); // Update the background color of the color picker. colorPicker.toggler.css({ 'background-color': color }); // Maybe update the alpha slider itself. if ( update_slider ) { csco_update_alpha_value_on_alpha_slider( alpha, $alphaSlider ); } // Update the color value of the color picker object. $control.wpColorPicker( 'color', color ); } /** * Update the slider handle position and label. */ function csco_update_alpha_value_on_alpha_slider( alpha, $alphaSlider ) { $alphaSlider.slider( 'value', alpha ); $alphaSlider.find( '.ui-slider-handle' ).text( alpha.toString() ); } /** * Initialization trigger. */ jQuery( document ).ready( function( $ ) { // Loop over each control and transform it into our color picker. $( '.color-alpha-control' ).each( function() { // Scope the vars. var $control, startingColor, paletteInput, showOpacity, defaultColor, palette, colorPickerOptions, $container, $alphaSlider, alphaVal, sliderOptions; // Store the control instance. $control = $( this ); // Get a clean starting value for the option. startingColor = $control.val().replace( /\s+/g, '' ); // Get some data off the control. paletteInput = $control.attr( 'data-palette' ); showOpacity = $control.attr( 'data-alpha' ); defaultColor = $control.attr( 'data-default-color' ); // Process the palette. if ( paletteInput.indexOf( '|' ) !== -1 ) { palette = paletteInput.split( '|' ); } else if ( 'false' == paletteInput ) { palette = false; } else { palette = true; } // Set up the options that we'll pass to wpColorPicker(). colorPickerOptions = { change: function( event, ui ) { var key, value, alpha, $transparency; key = $control.attr( 'data-customize-setting-link' ); value = $control.wpColorPicker( 'color' ); // Set the opacity value on the slider handle when the default color button is clicked. if ( defaultColor == value ) { alpha = csco_get_alpha_value_from_color( value ); $alphaSlider.find( '.ui-slider-handle' ).text( alpha ); } // Send ajax request to wp.customize to trigger the Save action. wp.customize( key, function( obj ) { obj.set( value ); }); $transparency = $container.find( '.transparency' ); // Always show the background color of the opacity slider at 100% opacity. $transparency.css( 'background-color', ui.color.toString( 'no-alpha' ) ); }, palettes: palette // Use the passed in palette. }; // Create the colorpicker. $control.wpColorPicker( colorPickerOptions ); $container = $control.parents( '.wp-picker-container:first' ); // Insert our opacity slider. $( '
' + '
' + '
' + '
' + '
' + '
' ).appendTo( $container.find( '.wp-picker-holder' ) ); $alphaSlider = $container.find( '.alpha-slider' ); // If starting value is in format RGBa, grab the alpha channel. alphaVal = csco_get_alpha_value_from_color( startingColor ); // Set up jQuery UI slider() options. sliderOptions = { create: function( event, ui ) { var value = $( this ).slider( 'value' ); // Set up initial values. $( this ).find( '.ui-slider-handle' ).text( value ); $( this ).siblings( '.transparency ').css( 'background-color', startingColor ); }, value: alphaVal, range: 'max', step: 1, min: 0, max: 100, animate: 300 }; // Initialize jQuery UI slider with our options. $alphaSlider.slider( sliderOptions ); // Maybe show the opacity on the handle. if ( 'true' == showOpacity ) { $alphaSlider.find( '.ui-slider-handle' ).addClass( 'alpha' ); } // Bind event handlers for the click zones. $container.find( '.min-click-zone' ).on( 'click', function() { csco_update_alpha_value_on_color_control( 0, $control, $alphaSlider, true ); }); $container.find( '.max-click-zone' ).on( 'click', function() { csco_update_alpha_value_on_color_control( 100, $control, $alphaSlider, true ); }); // Bind event handler for clicking on a palette color. $container.find( '.iris-palette' ).on( 'click', function() { var color, alpha; color = $( this ).css( 'background-color' ); alpha = csco_get_alpha_value_from_color( color ); csco_update_alpha_value_on_alpha_slider( alpha, $alphaSlider ); // Sometimes Iris doesn't set a perfect background-color on the palette, // for example rgba(20, 80, 100, 0.3) becomes rgba(20, 80, 100, 0.298039). // To compensante for this we round the opacity value on RGBa colors here // and save it a second time to the color picker object. if ( alpha != 100 ) { color = color.replace( /[^,]+(?=\))/, ( alpha / 100 ).toFixed( 2 ) ); } $control.wpColorPicker( 'color', color ); }); // Bind event handler for clicking on the 'Clear' button. $container.find( '.button.wp-picker-clear' ).on( 'click', function() { var key = $control.attr( 'data-customize-setting-link' ); // The #fff color is delibrate here. This sets the color picker to white instead of the // defult black, which puts the color picker in a better place to visually represent empty. $control.wpColorPicker( 'color', '#ffffff' ); // Set the actual option value to empty string. wp.customize( key, function( obj ) { obj.set( '' ); }); csco_update_alpha_value_on_alpha_slider( 100, $alphaSlider ); }); // Bind event handler for clicking on the 'Default' button. $container.find( '.button.wp-picker-default' ).on( 'click', function() { var alpha = csco_get_alpha_value_from_color( defaultColor ); csco_update_alpha_value_on_alpha_slider( alpha, $alphaSlider ); }); // Bind event handler for typing or pasting into the input. $control.on( 'input', function() { var value = $( this ).val(); var alpha = csco_get_alpha_value_from_color( value ); csco_update_alpha_value_on_alpha_slider( alpha, $alphaSlider ); }); // Update all the things when the slider is interacted with. $alphaSlider.slider().on( 'slide', function( event, ui ) { var alpha = parseFloat( ui.value ) / 100.0; csco_update_alpha_value_on_color_control( alpha, $control, $alphaSlider, false ); // Change value shown on slider handle. $( this ).find( '.ui-slider-handle' ).text( ui.value ); }); }); }); /*=============================================================== # 8. Active Callback ===============================================================*/ wp.customize.bind( 'ready', function() { var cscoCustomizerDependencies = { listenTo: {}, init: function() { var self = this; _.each( window.cscoCustomizerConfig.dependencies, function( requires, controlID ) { var control = wp.customize.control( controlID ); if ( control ) { wp.customize.control( controlID ).params.required = requires; self.showThemeCustomizerControl( control ); } } ); _.each( self.listenTo, function( slaves, master ) { _.each( slaves, function( slave ) { wp.customize( master, function( setting ) { var setupControl = function( control ) { var setActiveState, isDisplayed; isDisplayed = function() { return self.showThemeCustomizerControl( wp.customize.control( slave ) ); }; setActiveState = function() { control.active.set( isDisplayed() ); }; setActiveState(); setting.bind( setActiveState ); control.active.validate = isDisplayed; }; wp.customize.control( slave, setupControl ); } ); } ); } ); }, /** * Should we show the control? * * @since 3.0.17 * @param {string|object} control - The control-id or the control object. * @returns {bool} - Whether the control should be shown or not. */ showThemeCustomizerControl: function( control ) { var self = this, show = true, i; if ( _.isString( control ) ) { control = wp.customize.control( control ); } // Exit early if control not found or if "required" argument is not defined. if ( 'undefined' === typeof control || ( control.params && _.isEmpty( control.params.required ) ) ) { return true; } // Loop control requirements. for ( i = 0; i < control.params.required.length; i++ ) { if ( !self.checkCondition( control.params.required[ i ], control, 'AND' ) ) { show = false; } } return show; }, /** * Check a condition. * * @param {Object} requirement - The requirement, inherited from showThemeCustomizerControl. * @param {Object} control - The control object. * @param {string} relation - Can be one of 'AND' or 'OR'. * @returns {bool} - Returns the results of the condition checks. */ checkCondition: function( requirement, control, relation ) { var self = this, childRelation = ( 'AND' === relation ) ? 'OR' : 'AND', nestedItems, value, i; // If an array of other requirements nested, we need to process them separately. if ( 'undefined' !== typeof requirement[ 0 ] && 'undefined' === typeof requirement.setting ) { nestedItems = []; // Loop sub-requirements. for ( i = 0; i < requirement.length; i++ ) { nestedItems.push( self.checkCondition( requirement[ i ], control, childRelation ) ); } // OR relation. Check that true is part of the array. if ( 'OR' === childRelation ) { return ( -1 !== nestedItems.indexOf( true ) ); } // AND relation. Check that false is not part of the array. return ( -1 === nestedItems.indexOf( false ) ); } // Early exit if setting is not defined. if ( 'undefined' === typeof wp.customize.control( requirement.setting ) ) { return true; } self.listenTo[ requirement.setting ] = self.listenTo[ requirement.setting ] || []; if ( -1 === self.listenTo[ requirement.setting ].indexOf( control.id ) ) { self.listenTo[ requirement.setting ].push( control.id ); } value = wp.customize( requirement.setting ).get(); if ( wp.customize.control( requirement.setting ).setting ) { value = wp.customize.control( requirement.setting ).setting._value; } return self.evaluate( requirement.value, value, requirement.operator, requirement.choice ); }, /** * Figure out if the 2 values have the relation we want. * * @since 3.0.17 * @param {mixed} value1 - The 1st value. * @param {mixed} value2 - The 2nd value. * @param {string} operator - The comparison to use. * @param {string} choice - If we want to check an item in an object value. * @returns {bool} - Returns the evaluation result. */ evaluate: function( value1, value2, operator, choice ) { var found = false; if ( choice && 'object' === typeof value2 ) { value2 = value2[ choice ]; } if ( '===' === operator ) { return value1 === value2; } if ( '==' === operator || '=' === operator || 'equals' === operator || 'equal' === operator ) { return value1 == value2; } if ( '!==' === operator ) { return value1 !== value2; } if ( '!=' === operator || 'not equal' === operator ) { return value1 != value2; } if ( '>=' === operator || 'greater or equal' === operator || 'equal or greater' === operator ) { return value2 >= value1; } if ( '<=' === operator || 'smaller or equal' === operator || 'equal or smaller' === operator ) { return value2 <= value1; } if ( '>' === operator || 'greater' === operator ) { return value2 > value1; } if ( '<' === operator || 'smaller' === operator ) { return value2 < value1; } if ( 'contains' === operator || 'in' === operator ) { if ( _.isArray( value1 ) && _.isArray( value2 ) ) { _.each( value2, function( value ) { if ( value1.includes( value ) ) { found = true; return false; } } ); return found; } if ( _.isArray( value2 ) ) { _.each( value2, function( value ) { if ( value == value1 ) { // jshint ignore:line found = true; } } ); return found; } if ( _.isObject( value2 ) ) { if ( !_.isUndefined( value2[ value1 ] ) ) { found = true; } _.each( value2, function( subValue ) { if ( value1 === subValue ) { found = true; } } ); return found; } if ( _.isString( value2 ) ) { if ( _.isString( value1 ) ) { return ( -1 < value1.indexOf( value2 ) && -1 < value2.indexOf( value1 ) ); } return -1 < value1.indexOf( value2 ); } } if ( 'does not contain' === operator || 'not in' === operator ) { return ( !this.evaluate( value1, value2, 'contains', choice ) ); } return value1 == value2; } }; cscoCustomizerDependencies.init(); } );