diff --git a/Gruntfile.js b/Gruntfile.js
index e92bb6e70..d651fdb66 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -18,6 +18,7 @@ module.exports = function( grunt ) {
'modules/tooltips/tooltip.css': 'modules/tooltips/tooltip.scss',
'modules/custom-sections/sections.css': 'modules/custom-sections/sections.scss',
+ 'controls/background/background.css': 'controls/background/background.scss',
'controls/code/code.css': 'controls/code/code.scss',
'controls/color/color.css': 'controls/color/color.scss',
'controls/color-palette/color-palette.css': 'controls/color-palette/color-palette.scss',
diff --git a/controls/background/background.css b/controls/background/background.css
new file mode 100644
index 000000000..5320568f0
--- /dev/null
+++ b/controls/background/background.css
@@ -0,0 +1,25 @@
+.customize-control-kirki-background .background-attachment h4,
+.customize-control-kirki-background .background-color h4,
+.customize-control-kirki-background .background-position h4,
+.customize-control-kirki-background .background-repeat h4,
+.customize-control-kirki-background .background-size h4 {
+ margin-bottom: 5px; }
+.customize-control-kirki-background .background-attachment .buttonset,
+.customize-control-kirki-background .background-size .buttonset {
+ display: flex;
+ flex-wrap: wrap; }
+ .customize-control-kirki-background .background-attachment .buttonset .switch-label,
+ .customize-control-kirki-background .background-size .buttonset .switch-label {
+ background: rgba(0, 0, 0, 0.05);
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ color: #555;
+ padding: 0.5em 1em;
+ margin: 0;
+ text-align: center;
+ flex-grow: 1; }
+ .customize-control-kirki-background .background-attachment .buttonset .switch-input:checked + .switch-label,
+ .customize-control-kirki-background .background-size .buttonset .switch-input:checked + .switch-label {
+ background-color: #3498DB;
+ color: #fff; }
+
+/*# sourceMappingURL=background.css.map */
diff --git a/controls/background/background.css.map b/controls/background/background.css.map
new file mode 100644
index 000000000..59105a73a
--- /dev/null
+++ b/controls/background/background.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "AAMI;;;;uDAAG;EACD,aAAa,EAAE,GAAG;AAMpB;+DAAW;EACT,OAAO,EAAE,IAAI;EACb,SAAS,EAAE,IAAI;EAEf;+EAAc;IACZ,UAAU,EAAE,mBAAe;IAC3B,MAAM,EAAE,4BAAwB;IAChC,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,CAAC;IACT,UAAU,EAAE,MAAM;IAClB,SAAS,EAAE,CAAC;EAOV;uGAAgB;IACd,gBAAgB,EAAE,OAAO;IACzB,KAAK,EAAE,IAAI",
+"sources": ["background.scss"],
+"names": [],
+"file": "background.css"
+}
diff --git a/controls/background/background.js b/controls/background/background.js
new file mode 100644
index 000000000..1beb1da5b
--- /dev/null
+++ b/controls/background/background.js
@@ -0,0 +1,148 @@
+wp.customize.controlConstructor['kirki-background'] = wp.customize.Control.extend({
+
+ ready: function() {
+
+ var control = this,
+ value = control.getValue(),
+ picker = control.container.find( '.kirki-color-control' );
+
+ // Color.
+ picker.wpColorPicker({
+ change: function() {
+ setTimeout( function() {
+ value['background-color'] = picker.val();
+ control.saveValue( value );
+ }, 100 );
+ }
+ });
+
+ // Background-Repeat.
+ control.container.on( 'change', '.background-repeat select', function() {
+ value['background-repeat'] = jQuery( this ).val();
+ control.saveValue( value );
+ });
+
+ // Background-Size.
+ control.container.on( 'change click', '.background-size input', function() {
+ value['background-size'] = jQuery( this ).val();
+ control.saveValue( value );
+ });
+
+ // Background-Position.
+ control.container.on( 'change', '.background-position select', function() {
+ value['background-position'] = jQuery( this ).val();
+ control.saveValue( value );
+ });
+
+ // Background-Attachment.
+ control.container.on( 'change click', '.background-attachment input', function() {
+ value['background-attachment'] = jQuery( this ).val();
+ control.saveValue( value );
+ });
+
+ // Background-Image.
+ jQuery( '.background-image-upload-button' ).click( function( e ) {
+ var image = wp.media({ multiple: false }).open().on( 'select', function( e ) {
+
+ // This will return the selected image from the Media Uploader, the result is an object.
+ var uploadedImage = image.state().get( 'selection' ).first(),
+ previewImage = uploadedImage.toJSON().sizes.full.url,
+ imageUrl,
+ imageID,
+ imageWidth,
+ imageHeight,
+ preview,
+ removeButton;
+
+ if ( 'undefined' !== typeof uploadedImage.toJSON().sizes.medium ) {
+ previewImage = uploadedImage.toJSON().sizes.medium.url;
+ } else if ( 'undefined' !== typeof uploadedImage.toJSON().sizes.thumbnail ) {
+ previewImage = uploadedImage.toJSON().sizes.thumbnail.url;
+ }
+
+ imageUrl = uploadedImage.toJSON().sizes.full.url;
+ imageID = uploadedImage.toJSON().id;
+ imageWidth = uploadedImage.toJSON().width;
+ imageHeight = uploadedImage.toJSON().height;
+
+ value['background-image'] = imageUrl;
+ control.saveValue( value );
+ preview = control.container.find( '.placeholder, .thumbnail' );
+ removeButton = control.container.find( '.background-image-upload-remove-button' );
+
+ if ( preview.length ) {
+ preview.removeClass().addClass( 'thumbnail thumbnail-image' ).html( '' );
+ }
+ if ( removeButton.length ) {
+ removeButton.show();
+ }
+ });
+
+ e.preventDefault();
+ });
+
+ jQuery( '.background-image-upload-remove-button' ).click( function( e ) {
+
+ var preview,
+ removeButton;
+
+ e.preventDefault();
+
+ value['background-image'] = '';
+ control.saveValue( value );
+
+ preview = control.container.find( '.placeholder, .thumbnail' );
+ removeButton = control.container.find( '.background-image-upload-remove-button' );
+
+ if ( preview.length ) {
+ preview.removeClass().addClass( 'placeholder' ).html( 'No file selected' );
+ }
+ if ( removeButton.length ) {
+ removeButton.hide();
+ }
+ });
+ },
+
+ /**
+ * Gets the value.
+ */
+ getValue: function() {
+
+ var control = this,
+ value = {};
+
+ // Make sure everything we're going to need exists.
+ _.each( control.params['default'], function( defaultParamValue, param ) {
+ if ( false !== defaultParamValue ) {
+ value[ param ] = defaultParamValue;
+ if ( 'undefined' !== typeof control.setting._value[ param ] ) {
+ value[ param ] = control.setting._value[ param ];
+ }
+ }
+ });
+ _.each( control.setting._value, function( subValue, param ) {
+ if ( undefined === value[ param ] || 'undefined' === typeof value[ param ] ) {
+ value[ param ] = subValue;
+ }
+ });
+ return value;
+ },
+
+ /**
+ * Saves the value.
+ */
+ saveValue: function( value ) {
+
+ 'use strict';
+
+ var control = this,
+ newValue = {};
+
+ _.each( value, function( newSubValue, i ) {
+ newValue[ i ] = newSubValue;
+ });
+
+ control.setting.set( newValue );
+ }
+
+});
diff --git a/controls/background/background.scss b/controls/background/background.scss
new file mode 100644
index 000000000..a71a8d9b2
--- /dev/null
+++ b/controls/background/background.scss
@@ -0,0 +1,40 @@
+.customize-control-kirki-background {
+ .background-attachment,
+ .background-color,
+ .background-position,
+ .background-repeat,
+ .background-size {
+ h4 {
+ margin-bottom: 5px;
+ }
+ }
+
+ .background-attachment,
+ .background-size {
+ .buttonset {
+ display: flex;
+ flex-wrap: wrap;
+
+ .switch-label {
+ background: rgba(0,0,0,.05);
+ border: 1px solid rgba(0,0,0,.1);
+ color: #555;
+ padding: 0.5em 1em;
+ margin: 0;
+ text-align: center;
+ flex-grow: 1;
+
+ &:last-child {}
+ }
+
+ .switch-input {
+ &:checked {
+ + .switch-label {
+ background-color: #3498DB;
+ color: #fff;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/controls/background/class-kirki-control-background.php b/controls/background/class-kirki-control-background.php
new file mode 100644
index 000000000..b1ddbf77f
--- /dev/null
+++ b/controls/background/class-kirki-control-background.php
@@ -0,0 +1,271 @@
+json['default'] = $this->setting->default;
+ if ( isset( $this->default ) ) {
+ $this->json['default'] = $this->default;
+ }
+ $this->json['output'] = $this->output;
+ $this->json['value'] = $this->value();
+ $this->json['choices'] = $this->choices;
+ $this->json['link'] = $this->get_link();
+ $this->json['id'] = $this->id;
+
+ if ( 'user_meta' === $this->option_type ) {
+ $this->json['value'] = get_user_meta( get_current_user_id(), $this->id, true );
+ }
+
+ $this->json['inputAttrs'] = '';
+ foreach ( $this->input_attrs as $attr => $value ) {
+ $this->json['inputAttrs'] .= $attr . '="' . esc_attr( $value ) . '" ';
+ }
+ $config_id = 'global';
+ $this->json['l10n'] = $this->l10n( $config_id );
+ }
+
+ /**
+ * An Underscore (JS) template for this control's content (but not its container).
+ *
+ * Class variables for this control class are available in the `data` JS object;
+ * export custom variables by overriding {@see WP_Customize_Control::to_json()}.
+ *
+ * @see WP_Customize_Control::print_template()
+ *
+ * @access protected
+ */
+ protected function content_template() {
+ ?>
+
+
+
+
+
+
{{ data.l10n['background-color'] }}
+
+
+
+
+
+
{{ data.l10n['background-image'] }}
+
+
+
+
+
+
{{ data.l10n['background-repeat'] }}
+ <#
+ var repeats = [
+ 'no-repeat',
+ 'repeat-all',
+ 'repeat-x',
+ 'repeat-y'
+ ];
+ #>
+
+
+
+
+
+
{{ data.l10n['background-position'] }}
+ <#
+ var positions = [
+ 'left top',
+ 'left center',
+ 'left bottom',
+ 'right top',
+ 'right center',
+ 'right bottom',
+ 'center top',
+ 'center center',
+ 'center bottom'
+ ];
+ #>
+
+
+
+
+
+
{{ data.l10n['background-size'] }}
+ <#
+ var sizes = [
+ 'cover',
+ 'contain',
+ 'auto'
+ ];
+ #>
+
+ <# _.each( sizes, function( size ) { #>
+ checked="checked" <# } #>>
+
+
+ <# }); #>
+
+
+
+
+
+
{{ data.l10n['background-attachment'] }}
+ <#
+ var attachments = [
+ 'scroll',
+ 'fixed',
+ 'local'
+ ];
+ #>
+
+ <# _.each( attachments, function( attachment ) { #>
+ checked="checked" <# } #>>
+
+
+ <# }); #>
+
+
+ esc_attr__( 'Background Color', 'kirki' ),
+ 'background-image' => esc_attr__( 'Background Image', 'kirki' ),
+ 'background-repeat' => esc_attr__( 'Background Repeat', 'kirki' ),
+ 'background-attachment' => esc_attr__( 'Background Attachment', 'kirki' ),
+ 'background-position' => esc_attr__( 'Background Position', 'kirki' ),
+ 'background-size' => esc_attr__( 'Background Size', 'kirki' ),
+
+ 'no-repeat' => esc_attr__( 'No Repeat', 'kirki' ),
+ 'repeat-all' => esc_attr__( 'Repeat All', 'kirki' ),
+ 'repeat-x' => esc_attr__( 'Repeat Horizontally', 'kirki' ),
+ 'repeat-y' => esc_attr__( 'Repeat Vertically', 'kirki' ),
+
+ 'cover' => esc_attr__( 'Cover', 'kirki' ),
+ 'contain' => esc_attr__( 'Contain', 'kirki' ),
+ 'auto' => esc_attr__( 'Auto', 'kirki' ),
+ 'inherit' => esc_attr__( 'Inherit', 'kirki' ),
+
+ 'fixed' => esc_attr__( 'Fixed', 'kirki' ),
+ 'scroll' => esc_attr__( 'Scroll', 'kirki' ),
+ 'local' => esc_attr__( 'Local', 'kirki' ),
+
+ 'left top' => esc_attr__( 'Left Top', 'kirki' ),
+ 'left center' => esc_attr__( 'Left Center', 'kirki' ),
+ 'left bottom' => esc_attr__( 'Left Bottom', 'kirki' ),
+ 'right top' => esc_attr__( 'Right Top', 'kirki' ),
+ 'right center' => esc_attr__( 'Right Center', 'kirki' ),
+ 'right bottom' => esc_attr__( 'Right Bottom', 'kirki' ),
+ 'center top' => esc_attr__( 'Center Top', 'kirki' ),
+ 'center center' => esc_attr__( 'Center Center', 'kirki' ),
+ 'center bottom' => esc_attr__( 'Center Bottom', 'kirki' ),
+
+ 'no-file-selected' => esc_attr__( 'No File Selected', 'kirki' ),
+ 'remove' => esc_attr__( 'Remove', 'kirki' ),
+ 'select-file' => esc_attr__( 'Select File', 'kirki' ),
+ );
+ return apply_filters( 'kirki/' . $config_id . '/l10n', $translation_strings );
+ }
+}
diff --git a/controls/background/wp-color-picker-alpha.js b/controls/background/wp-color-picker-alpha.js
new file mode 100644
index 000000000..ad9a8c90c
--- /dev/null
+++ b/controls/background/wp-color-picker-alpha.js
@@ -0,0 +1,395 @@
+/**
+ * wp-color-picker-alpha
+ *
+ * Overwrite Automattic Iris for enabled Alpha Channel in wpColorPicker
+ * Only run in input and is defined data alpha in true
+ *
+ * Version: 1.2
+ * https://github.com/23r9i0/wp-color-picker-alpha
+ * Copyright (c) 2016 Sergio P.A. (23r9i0).
+ * Licensed under the GPLv2 license.
+ */
+( function( $ ) {
+
+ // Variable for some backgrounds
+ var image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAAHnlligAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHJJREFUeNpi+P///4EDBxiAGMgCCCAGFB5AADGCRBgYDh48CCRZIJS9vT2QBAggFBkmBiSAogxFBiCAoHogAKIKAlBUYTELAiAmEtABEECk20G6BOmuIl0CIMBQ/IEMkO0myiSSraaaBhZcbkUOs0HuBwDplz5uFJ3Z4gAAAABJRU5ErkJggg==';
+
+ // HTML stuff for wpColorPicker copy of the original color-picker.js
+ var _before = '
',
+ _after = '
',
+ _wrap = '
',
+ _button = '
';
+
+ /**
+ * Overwrite Color
+ * for enable support rbga
+ */
+ Color.fn.toString = function() {
+
+ var hex,
+ i;
+
+ if ( this._alpha < 1 ) {
+ return this.toCSS( 'rgba', this._alpha ).replace( /\s+/g, '' );
+ }
+
+ hex = parseInt( this._color, 10 ).toString( 16 );
+
+ if ( this.error ) {
+ return '';
+ }
+
+ if ( hex.length < 6 ) {
+ for ( i = 6 - hex.length - 1; i >= 0; i-- ) {
+ hex = '0' + hex;
+ }
+ }
+
+ return '#' + hex;
+ };
+
+ /**
+ * Overwrite wpColorPicker
+ */
+ jQuery.widget( 'wp.wpColorPicker', $.wp.wpColorPicker, {
+ _create: function() {
+
+ var self,
+ el;
+
+ // Bail early for unsupported Iris.
+ if ( ! $.support.iris ) {
+ return;
+ }
+
+ self = this;
+ el = self.element;
+
+ $.extend( self.options, el.data() );
+
+ // Keep close bound so it can be attached to a body listener.
+ self.close = $.proxy( self.close, self );
+
+ self.initialValue = el.val();
+
+ // Set up HTML structure, hide things
+ el.addClass( 'wp-color-picker' ).hide().wrap( _wrap );
+ self.wrap = el.parent();
+ self.toggler = jQuery( _before ).insertBefore( el ).css( { backgroundColor: self.initialValue } ).attr( 'title', wpColorPickerL10n.pick ).attr( 'data-current', wpColorPickerL10n.current );
+ self.pickerContainer = $( _after ).insertAfter( el );
+ self.button = $( _button );
+
+ if ( self.options.defaultColor ) {
+ self.button.addClass( 'wp-picker-default' ).val( wpColorPickerL10n.defaultString );
+ } else {
+ self.button.addClass( 'wp-picker-clear' ).val( wpColorPickerL10n.clear );
+ }
+
+ el.wrap( '
' ).after( self.button );
+
+ el.iris( {
+ target: self.pickerContainer,
+ hide: self.options.hide,
+ width: self.options.width,
+ mode: self.options.mode,
+ palettes: self.options.palettes,
+ change: function( event, ui ) {
+ if ( self.options.alpha ) {
+ self.toggler.css( { 'background-image': 'url(' + image + ')' } ).html( '
' );
+ self.toggler.find( 'span' ).css( {
+ 'width': '100%',
+ 'height': '100%',
+ 'position': 'absolute',
+ 'top': 0,
+ 'left': 0,
+ 'border-top-left-radius': '3px',
+ 'border-bottom-left-radius': '3px',
+ 'background': ui.color.toString()
+ });
+ } else {
+ self.toggler.css( { backgroundColor: ui.color.toString() } );
+ }
+
+ // Check for a custom cb
+ if ( $.isFunction( self.options.change ) ) {
+ self.options.change.call( this, event, ui );
+ }
+ }
+ } );
+
+ el.val( self.initialValue );
+ self._addListeners();
+ if ( ! self.options.hide ) {
+ self.toggler.click();
+ }
+ },
+ _addListeners: function() {
+ var self = this;
+
+ // Prevent any clicks inside this widget from leaking to the top and closing it.
+ self.wrap.on( 'click.wpcolorpicker', function( event ) {
+ event.stopPropagation();
+ });
+
+ self.toggler.click( function() {
+ if ( self.toggler.hasClass( 'wp-picker-open' ) ) {
+ self.close();
+ } else {
+ self.open();
+ }
+ });
+
+ self.element.change( function( event ) {
+ var me = $( this ),
+ val = me.val();
+
+ // Empty or Error = clear
+ if ( '' === val || self.element.hasClass( 'iris-error' ) ) {
+ if ( self.options.alpha ) {
+ self.toggler.removeAttr( 'style' );
+ self.toggler.find( 'span' ).css( 'backgroundColor', '' );
+ } else {
+ self.toggler.css( 'backgroundColor', '' );
+ }
+
+ // Fire clear callback if we have one.
+ if ( $.isFunction( self.options.clear ) ) {
+ self.options.clear.call( this, event );
+ }
+ }
+ });
+
+ // Open a keyboard-focused closed picker with space or enter.
+ self.toggler.on( 'keyup', function( event ) {
+ if ( 13 === event.keyCode || 32 === event.keyCode ) {
+ event.preventDefault();
+ self.toggler.trigger( 'click' ).next().focus();
+ }
+ });
+
+ self.button.click( function( event ) {
+ var me = $( this );
+ if ( me.hasClass( 'wp-picker-clear' ) ) {
+ self.element.val( '' );
+ if ( self.options.alpha ) {
+ self.toggler.removeAttr( 'style' );
+ self.toggler.find( 'span' ).css( 'backgroundColor', '' );
+ } else {
+ self.toggler.css( 'backgroundColor', '' );
+ }
+ if ( $.isFunction( self.options.clear ) ) {
+ self.options.clear.call( this, event );
+ }
+ } else if ( me.hasClass( 'wp-picker-default' ) ) {
+ self.element.val( self.options.defaultColor ).change();
+ }
+ });
+ }
+ });
+
+ /**
+ * Overwrite iris
+ */
+ $.widget( 'a8c.iris', $.a8c.iris, {
+ _create: function() {
+
+ var self,
+ el,
+ _html,
+ aContainer,
+ aSlider,
+ controls,
+ emptyWidth,
+ stripsMargin,
+ stripsWidth;
+
+ this._super();
+
+ // Global option for check is mode rbga is enabled
+ this.options.alpha = this.element.data( 'alpha' ) || false;
+
+ // Is not input disabled
+ if ( ! this.element.is( ':input' ) ) {
+ this.options.alpha = false;
+ }
+
+ if ( 'undefined' !== typeof this.options.alpha && this.options.alpha ) {
+ self = this;
+ el = self.element;
+ _html = '
';
+ aContainer = $( _html ).appendTo( self.picker.find( '.iris-picker-inner' ) );
+ aSlider = aContainer.find( '.iris-slider-offset-alpha' );
+ controls = {
+ aContainer: aContainer,
+ aSlider: aSlider
+ };
+
+ if ( 'undefined' !== typeof el.data( 'custom-width' ) ) {
+ self.options.customWidth = parseInt( el.data( 'custom-width' ), 10 ) || 0;
+ } else {
+ self.options.customWidth = 100;
+ }
+
+ // Set default width for input reset
+ self.options.defaultWidth = el.width();
+
+ // Update width for input
+ if ( self._color._alpha < 1 || 1 !== self._color.toString().indexOf( 'rgb' ) ) {
+ el.width( parseInt( self.options.defaultWidth + self.options.customWidth, 10 ) );
+ }
+
+ // Push new controls
+ jQuery.each( controls, function( k, v ) {
+ self.controls[k] = v;
+ });
+
+ // Change size strip and add margin for sliders.
+ self.controls.square.css( { 'margin-right': '0' } );
+ emptyWidth = ( self.picker.width() - self.controls.square.width() - 20 );
+ stripsMargin = emptyWidth / 6;
+ stripsWidth = ( emptyWidth / 2 ) - stripsMargin;
+
+ $.each( [ 'aContainer', 'strip' ], function( k, v ) {
+ self.controls[v].width( stripsWidth ).css({ 'margin-left': Math.floor( stripsMargin ) + 'px' });
+ });
+
+ // Add new slider
+ self._initControls();
+
+ // For updated widget
+ self._change();
+ }
+ },
+ _initControls: function() {
+
+ var self,
+ controls;
+
+ this._super();
+
+ if ( this.options.alpha ) {
+ self = this;
+ controls = self.controls;
+
+ controls.aSlider.slider({
+ orientation: 'vertical',
+ min: 0,
+ max: 100,
+ step: 1,
+ value: parseInt( self._color._alpha * 100, 10 ),
+ slide: function( event, ui ) {
+
+ // Update alpha value
+ self._color._alpha = parseFloat( ui.value / 100 );
+ self._change.apply( self, arguments );
+ }
+ });
+ }
+ },
+ _change: function() {
+
+ var self,
+ el,
+ controls,
+ alpha,
+ color,
+ gradient,
+ defaultWidth,
+ customWidth,
+ target,
+ style,
+ reset;
+
+ this._super();
+
+ self = this;
+ el = self.element;
+
+ if ( this.options.alpha ) {
+ controls = self.controls;
+ alpha = parseInt( self._color._alpha * 100, 10 );
+ color = self._color.toRgb();
+ gradient = [
+ 'rgb(' + color.r + ',' + color.g + ',' + color.b + ') 0%',
+ 'rgba(' + color.r + ',' + color.g + ',' + color.b + ', 0) 100%'
+ ];
+ defaultWidth = self.options.defaultWidth;
+ customWidth = self.options.customWidth;
+ target = self.picker.closest( '.wp-picker-container' ).find( '.wp-color-result' );
+
+ // Generate background slider alpha, only for CSS3 old browser fuck!! :)
+ controls.aContainer.css({ 'background': 'linear-gradient(to bottom, ' + gradient.join( ', ' ) + '), url(' + image + ')' });
+
+ if ( target.hasClass( 'wp-picker-open' ) ) {
+
+ // Update alpha value.
+ controls.aSlider.slider( 'value', alpha );
+
+ /**
+ * Disabled change opacity in default slider Saturation ( only is alpha enabled )
+ * and change input width for view all value
+ */
+ if ( self._color._alpha < 1 ) {
+ style = controls.strip.attr( 'style' ).replace( /rgba\(([0-9]+,)(\s+)?([0-9]+,)(\s+)?([0-9]+)(,(\s+)?[0-9\.]+)\)/g, 'rgb($1$3$5)' );
+
+ controls.strip.attr( 'style', style );
+
+ el.width( parseInt( defaultWidth + customWidth, 10 ) );
+ } else {
+ el.width( defaultWidth );
+ }
+ }
+ }
+
+ reset = el.data( 'reset-alpha' ) || false;
+ if ( reset ) {
+ self.picker.find( '.iris-palette-container' ).on( 'click.palette', '.iris-palette', function() {
+ self._color._alpha = 1;
+ self.active = 'external';
+ self._change();
+ });
+ }
+ },
+ _addInputListeners: function( input ) {
+ var self = this,
+ debounceTimeout = 100,
+ callback = function( event ) {
+ var color = new Color( input.val() ),
+ val = input.val();
+
+ input.removeClass( 'iris-error' );
+
+ // We gave a bad color.
+ if ( color.error ) {
+
+ // Don't error on an empty input.
+ if ( '' !== val ) {
+ input.addClass( 'iris-error' );
+ }
+ } else {
+ if ( color.toString() !== self._color.toString() ) {
+
+ // Let's not do this on keyup for hex shortcodes.
+ if ( ! ( 'keyup' === event.type && val.match( /^[0-9a-fA-F]{3}$/ ) ) ) {
+ self._setOption( 'color', color.toString() );
+ }
+ }
+ }
+ };
+
+ input.on( 'change', callback ).on( 'keyup', self._debounce( callback, debounceTimeout ) );
+
+ // If we initialized hidden, show on first focus. The rest is up to you.
+ if ( self.options.hide ) {
+ input.one( 'focus', function() {
+ self.show();
+ });
+ }
+ }
+ } );
+}( jQuery ) );
+
+// Auto Call plugin is class is color-picker
+jQuery( document ).ready( function( $ ) {
+ $( '.color-picker' ).wpColorPicker();
+} );
diff --git a/core/class-kirki-control.php b/core/class-kirki-control.php
index 820f601bd..b6a1837b8 100644
--- a/core/class-kirki-control.php
+++ b/core/class-kirki-control.php
@@ -105,6 +105,7 @@ final private function set_control_types() {
self::$control_types = apply_filters( 'kirki/control_types', array(
'checkbox' => 'WP_Customize_Control',
+ 'kirki-background' => 'Kirki_Control_Background',
'kirki-code' => 'Kirki_Control_Code',
'kirki-color' => 'Kirki_Control_Color',
'kirki-color-palette' => 'Kirki_Control_Color_Palette',
diff --git a/core/class-kirki-explode-background-field.php b/core/class-kirki-explode-background-field.php
deleted file mode 100644
index a0a3ae341..000000000
--- a/core/class-kirki-explode-background-field.php
+++ /dev/null
@@ -1,239 +0,0 @@
- $value ) {
-
- // No need to process the opacity, it is factored in the color control.
- if ( 'opacity' === $key ) {
- continue;
- }
-
- $key = esc_attr( $key );
- $setting = $key;
- $tooltip = $field['tooltip'];
- $description = isset( $l10n[ 'background-' . $key ] ) ? $l10n[ 'background-' . $key ] : '';
- $output_property = 'background-' . $key;
- $label = ( 0 === $i ) ? $field['label'] : '';
- $type = 'select';
- $sanitize_callback = 'esc_attr';
-
- switch ( $key ) {
- case 'color':
- // Use 'color-alpha' instead of 'color' if default is an rgba value or if 'opacity' is set.
- $type = ( false !== strpos( $field['default']['color'], 'rgba' ) ) ? 'color-alpha' : 'color';
- $type = ( isset( $field['default']['opacity'] ) ) ? 'color-alpha' : $type;
- if ( isset( $field['default']['opacity'] ) && false === strpos( $value, 'rgb' ) ) {
- $value = Kirki_Color::get_rgba( $value, $field['default']['opacity'] );
- }
- $sanitize_callback = array( 'Kirki_Sanitize_Values', 'color' );
- break;
- case 'image':
- $type = 'image';
- $sanitize_callback = 'esc_url_raw';
- break;
- case 'attach':
- // Small hack so that background attachments properly work.
- $output_property = 'background-attachment';
- $description = $l10n['background-attachment'];
- break;
- default:
- $tooltip = '';
- break;
- }
-
- // If we're using options & option_name is set, then we need to modify the setting.
- if ( ( isset( $field['option_type'] ) && 'option' === $field['option_type'] && isset( $field['option_name'] ) ) && ! empty( $field['option_name'] ) ) {
- $property_setting = str_replace( ']', '', str_replace( $field['option_name'] . '[', '', $field['settings'] ) );
- $property_setting = esc_attr( $field['option_name'] ) . '[' . esc_attr( $property_setting ) . '_' . $setting . ']';
- } else {
- $property_setting = esc_attr( $field['settings'] ) . '_' . $setting;
- }
-
- // Build the field's output element.
- $output_element = $field['output'];
- if ( ! empty( $field['output'] ) ) {
- if ( is_array( $field['output'] ) ) {
- if ( isset( $field['output']['element'] ) ) {
- $output_element = $field['output']['element'];
- } elseif ( isset( $field['output'][0] ) && isset( $field['output'][0]['element'] ) ) {
- $output_element = $field['output'][0]['element'];
- }
- }
- }
-
- /**
- * Build the field.
- * We're merging with the original field here, so any extra properties are inherited.
- */
- $fields[ $property_setting ] = array_merge( $field, array(
- 'type' => $type,
- 'label' => $label,
- 'settings' => $property_setting,
- 'tooltip' => $tooltip,
- 'section' => $field['section'],
- 'priority' => $field['priority'],
- 'required' => $field['required'],
- 'description' => $description,
- 'default' => $value,
- 'id' => sanitize_key( str_replace( '[', '-', str_replace( ']', '', $property_setting ) ) ),
- 'choices' => isset( $choices[ $key ] ) ? $choices[ $key ] : array(),
- 'sanitize_callback' => $sanitize_callback,
- 'output' => ( ! empty( $field['output'] ) ) ? array(
- array(
- 'element' => $output_element,
- 'property' => $output_property,
- ),
- ) : array(),
- ) );
- $i++;
- } // End foreach().
-
- return $fields;
-
- }
-
- /**
- * Parse all fields and add the new background fields
- *
- * @param array $fields An array of all the generated fields.
- * @return array
- */
- public static function process_fields( $fields ) {
-
- foreach ( $fields as $field ) {
- /**
- * Make sure background fields are exploded
- */
- if ( isset( $field['type'] ) && 'background' === $field['type'] ) {
- $explode = self::explode( $field );
- $fields = array_merge( $fields, $explode );
- }
- }
-
- return $fields;
-
- }
-
-
- /**
- * The background choices.
- *
- * @param array $field The field arguments.
- * @return array
- */
- public static function background_choices( $field ) {
-
- $l10n = self::l10n( $field['kirki_config'] );
-
- return array(
- 'repeat' => array(
- 'no-repeat' => $l10n['no-repeat'],
- 'repeat' => $l10n['repeat-all'],
- 'repeat-x' => $l10n['repeat-x'],
- 'repeat-y' => $l10n['repeat-y'],
- 'inherit' => $l10n['inherit'],
- ),
- 'size' => array(
- 'inherit' => $l10n['inherit'],
- 'cover' => $l10n['cover'],
- 'contain' => $l10n['contain'],
- ),
- 'attach' => array(
- 'inherit' => $l10n['inherit'],
- 'fixed' => $l10n['fixed'],
- 'scroll' => $l10n['scroll'],
- ),
- 'position' => array(
- 'left-top' => $l10n['left-top'],
- 'left-center' => $l10n['left-center'],
- 'left-bottom' => $l10n['left-bottom'],
- 'right-top' => $l10n['right-top'],
- 'right-center' => $l10n['right-center'],
- 'right-bottom' => $l10n['right-bottom'],
- 'center-top' => $l10n['center-top'],
- 'center-center' => $l10n['center-center'],
- 'center-bottom' => $l10n['center-bottom'],
- ),
- );
- }
-
- /**
- * Returns an array of translation strings.
- *
- * @static
- * @access protected
- * @since 3.0.0
- * @param string|false $config_id The string-ID.
- * @return array
- */
- protected static function l10n( $config_id ) {
- $translation_strings = array(
- 'background-color' => esc_attr__( 'Background Color', 'kirki' ),
- 'background-image' => esc_attr__( 'Background Image', 'kirki' ),
- 'no-repeat' => esc_attr__( 'No Repeat', 'kirki' ),
- 'repeat-all' => esc_attr__( 'Repeat All', 'kirki' ),
- 'repeat-x' => esc_attr__( 'Repeat Horizontally', 'kirki' ),
- 'repeat-y' => esc_attr__( 'Repeat Vertically', 'kirki' ),
- 'inherit' => esc_attr__( 'Inherit', 'kirki' ),
- 'background-repeat' => esc_attr__( 'Background Repeat', 'kirki' ),
- 'cover' => esc_attr__( 'Cover', 'kirki' ),
- 'contain' => esc_attr__( 'Contain', 'kirki' ),
- 'background-size' => esc_attr__( 'Background Size', 'kirki' ),
- 'fixed' => esc_attr__( 'Fixed', 'kirki' ),
- 'scroll' => esc_attr__( 'Scroll', 'kirki' ),
- 'background-attachment' => esc_attr__( 'Background Attachment', 'kirki' ),
- 'left-top' => esc_attr__( 'Left Top', 'kirki' ),
- 'left-center' => esc_attr__( 'Left Center', 'kirki' ),
- 'left-bottom' => esc_attr__( 'Left Bottom', 'kirki' ),
- 'right-top' => esc_attr__( 'Right Top', 'kirki' ),
- 'right-center' => esc_attr__( 'Right Center', 'kirki' ),
- 'right-bottom' => esc_attr__( 'Right Bottom', 'kirki' ),
- 'center-top' => esc_attr__( 'Center Top', 'kirki' ),
- 'center-center' => esc_attr__( 'Center Center', 'kirki' ),
- 'center-bottom' => esc_attr__( 'Center Bottom', 'kirki' ),
- 'background-position' => esc_attr__( 'Background Position', 'kirki' ),
- 'background-opacity' => esc_attr__( 'Background Opacity', 'kirki' ),
- );
- return apply_filters( 'kirki/' . $config_id . '/l10n', $translation_strings );
- }
-}
diff --git a/core/class-kirki-field.php b/core/class-kirki-field.php
index cff5b2e54..de42dded0 100644
--- a/core/class-kirki-field.php
+++ b/core/class-kirki-field.php
@@ -414,11 +414,6 @@ protected function set_field( $whitelisted_properties = array() ) {
// Add the field to the static $fields variable properly indexed.
Kirki::$fields[ $this->settings ] = $args;
- if ( 'background' === $this->type ) {
- // Build the background fields.
- Kirki::$fields = Kirki_Explode_Background_Field::process_fields( Kirki::$fields );
- }
-
}
/**
diff --git a/core/class-kirki-init.php b/core/class-kirki-init.php
index f20195916..f38617696 100644
--- a/core/class-kirki-init.php
+++ b/core/class-kirki-init.php
@@ -89,6 +89,7 @@ public function register_control_types() {
$wp_customize->register_section_type( $section_type );
}
+ $wp_customize->register_control_type( 'Kirki_Control_Background' );
$wp_customize->register_control_type( 'Kirki_Control_Code' );
$wp_customize->register_control_type( 'Kirki_Control_Color' );
$wp_customize->register_control_type( 'Kirki_Control_Color_Palette' );