/**
* USOF Field: Color
*/
! function( $, undefined ) {
var _window = window,
_document = document;
if ( _window.$usof === undefined ) {
return;
}
$usof.field[ 'color' ] = {
init: function( options ) {
// Elements
this.$color = this.$row.find( '.usof-color' );
this.$clear = $( '.usof-color-clear', this.$color );
this.$list = $( '.usof-color-list', this.$color );
this.$preview = $( '.usof-color-preview', this.$color );
// Variables
this.withGradient = !! this.$color.is( '.with-gradient' );
this.isDynamicСolors = !! this.$color.is( '.dynamic_colors' );
// Set white text color for dark backgrounds
this._toggleInputColor( this.getColor() );
// Init colpick on focus
this.$input
.off( 'focus' )
.on( 'focus', this._events.initColpick.bind( this ) )
.on( 'input', this._events.inputValue.bind( this ) )
.on( 'change', this._events.changeValue.bind( this ) );
this.$clear
.on( 'click', this._events.inputClear.bind( this ) );
// Init of a sheet of dynamic colors on click
if ( this.isDynamicСolors ) {
this.$color
.on( 'click', '.usof-color-arrow', this._events.toggleList.bind( this ) )
.on( 'click', '.usof-color-list-item', this._events._changeColorListItem.bind( this ) );
}
// If the sheet is open and there was a click outside the sheet, then close the sheet
$( _document )
.mouseup( this._events.hideList.bind( this ) );
},
_events: {
/**
* Init colpick.
*/
initColpick: function() {
this.$input
.usof_colpick( {
input: this.$input,
value: this.getColor(),
onChange: function( colors ) {
this._invertInputColors( colors.color.first.rgba );
}.bind( this ),
} );
},
/**
* Init of a sheet of dynamic variables
* @param void
*/
toggleList: function( e ) {
if ( ! this.$color.is( '.show' ) ) {
this.initDynamicColors();
}
this.$color.toggleClass( 'show' );
},
/**
* Change color list item
*
* @private
* @event handler
*
* @param {Event} e The Event interface represents an event which takes place in the DOM.
*/
_changeColorListItem: function( e ) {
this.сhooseColorVar( $( e.currentTarget ).data('name') || '' );
},
/**
* Hides the list.
* @param {Event} e
*/
hideList: function( e ) {
if ( ! this.$color.is( '.show' ) ) {
return;
}
if ( ! this.$color.is( e.target ) && this.$color.has( e.target ).length === 0 ) {
this.$color.removeClass( 'show' );
}
},
/**
* Input value
* @return value
*/
inputValue: function() {
var value = this.getValue();
// Preloading the list of variables if the value contains brackets
if ( value.indexOf( '_' ) !== - 1 ) {
this.initDynamicColors();
}
},
/**
* Changed value.
*/
changeValue: function() {
var value = this.getValue();
// Check the value for dynamic variables
if ( value.indexOf( '_' ) !== - 1 ) {
$( '[data-name^="' + value + '"]:first', this.$list )
.trigger( 'click' );
} else {
this.setValue( value );
this.trigger( 'change', value );
}
},
/**
* Clear value.
*/
inputClear: function() {
if ( this.$color.hasClass( 'show' ) ) {
this.$color.removeClass( 'show' );
}
this.setValue( '' );
}
},
/**
* Choose a color from a list of variables.
*
* @param {string} name The color name from the list example `content_bg_alt`
* @param {boolean} quiet The quiet mode
*/
сhooseColorVar: function( name, quiet ) {
var $target = $( '[data-name="' + name + '"]:first', this.$list ),
value = $target.data( 'value' ) || '';
$( '[data-name]', this.$list ) // Reset all selected
.removeClass( 'selected' );
$target // Selected color
.addClass( 'selected' );
this.$preview // Show preview
.css( 'background', value );
this.$input // Set current value
.val( $target.data( 'name' ) || '' );
if ( ! quiet ) {
this.trigger( 'change', this.$input.val() );
}
// Set white text color for dark backgrounds
this._toggleInputColor( value );
this.$color
.removeClass( 'show' );
},
/**
* Add dynamic colors to the list
*/
initDynamicColors: function() {
if ( this.$color.is( '.list-inited' ) ) return;
var /**
* Add item to list.
*
* @param {node} $el
* @param {node} item
*/
insertItem = function( $el, item ) {
// Exclude yourself
if ( this.name === item.name ) {
return;
}
var $item = $( '
' ),
$palette = $( '
' ),
value = this.getValue();
$palette
.find( 'span' )
.css( 'background', item.value )
.attr( 'title', item.value );
$item
.addClass( 'usof-color-list-item' )
.attr( 'data-name', item.name )
.data( 'value', item.value )
.append( $palette )
.append( '' + item.title + '' );
if ( value.indexOf( '_' ) !== - 1 && item.name === value ) {
$item.addClass( 'selected' );
}
$el.append( $item );
};
// Add dynamic colors to the list
$.each( $usof.getDynamicColors() || [], function( key, item ) {
// Group options
if ( $.isArray( item ) && item.length ) {
$group = $( '> [data-group="' + key + '"]:first', this.$list );
if ( ! $group.length ) {
$group = $( '' );
this.$list.append( $group );
}
$.each( item, function( _, _item ) {
insertItem.call( this, $group, _item );
}.bind( this ) );
// Options
} else {
insertItem.call( this, this.$list, item );
}
}.bind( this ) );
this.$color
.addClass( 'list-inited' );
},
/**
* Set the value.
*
* @param {string} value
* @param {boolean} quiet
*/
setValue: function( value, quiet ) {
value = value.trim();
// Check the value for dynamic variables
if ( value.indexOf( '_' ) !== - 1 ) {
this.initDynamicColors();
this.сhooseColorVar( value, quiet );
return;
}
var r, g, b, a, hexR, hexG, hexB, gradient, rgba = {};
this.convertRgbToHex = function( color ) {
if ( m = /^([^0-9]{1,3})*(\d{1,3})[^,]*,([^0-9]{1,3})*(\d{1,3})[^,]*,([^0-9]{1,3})*(\d{1,3})[\s\S]*$/.exec( color ) ) {
rgba = {
r: m[ 2 ],
g: m[ 4 ],
b: m[ 6 ],
};
hexR = m[ 2 ] <= 255 ? ( "0" + parseInt( m[ 2 ], 10 ).toString( 16 ) ).slice( - 2 ) : 'ff';
hexG = m[ 4 ] <= 255 ? ( "0" + parseInt( m[ 4 ], 10 ).toString( 16 ) ).slice( - 2 ) : 'ff';
hexB = m[ 6 ] <= 255 ? ( "0" + parseInt( m[ 6 ], 10 ).toString( 16 ) ).slice( - 2 ) : 'ff';
color = '#' + hexR + hexG + hexB;
return color;
}
};
if ( $.usof_colpick.isGradient( value ) ) {
gradient = $.usof_colpick.gradientParser( value );
rgba = $.usof_colpick.hexToRgba( gradient.hex );
} else if ( ( m = /^[^,]*,[^,]*,[\s\S]*$/.exec( value ) ) ) {
// Catch RGB and RGBa
if ( m = /^[^,]*(,)[^,]*(,)[^,]*(,)[^.]*(\.|0)[\s\S]*$/.exec( value ) ) {
// Catch only RGBa values
if ( m[ 4 ] === '.' || m[ 4 ] == 0 ) {
if ( m = /^([^0-9]{1,3})*(\d{1,3})[^,]*,([^0-9]{1,3})*(\d{1,3})[^,]*,([^0-9]{1,3})*(\d{1,3})[^,]*,[^.]*.([^0-9]{1,2})*(\d{1,2})[\s\S]*$/.exec( value ) ) {
rgba = {
r: m[ 2 ],
g: m[ 4 ],
b: m[ 6 ],
};
r = m[ 2 ] <= 255 ? m[ 2 ] : 255;
g = m[ 4 ] <= 255 ? m[ 4 ] : 255;
b = m[ 6 ] <= 255 ? m[ 6 ] : 255;
a = m[ 8 ];
value = 'rgba(' + r + ',' + g + ',' + b + ',0.' + a + ')';
}
} else {
value = this.convertRgbToHex( value );
}
} else {
value = this.convertRgbToHex( value );
}
} else {
// Check Hex Colors
if ( m = /^\#?[\s\S]*?([a-fA-F0-9]{1,6})[\s\S]*$/.exec( value ) ) {
if ( value == 'inherit' || value == 'transparent' || $.usof_colpick.colorNameToHex( value ) ) {
value = value;
} else {
value = $.usof_colpick.normalizeHex( m[ 1 ] );
rgba = $.usof_colpick.hexToRgba( value );
}
}
}
if ( value == '' ) {
this.$preview.removeAttr( 'style' );
this.$input.removeClass( 'with_alpha' );
} else {
if ( value == 'inherit' || value == 'transparent' ) {
this.$input.removeClass( 'white' );
this.$preview.css( 'background', value );
} else if ( gradient ) {
if ( this.withGradient ) {
this.$preview.css( 'background', gradient.gradient );
this.$input.val( gradient.gradient );
} else {
// Don't allow to use gradient colors
value = gradient.hex;
this.$preview.css( 'background', value );
this.$input.val( value );
}
} else {
this.$preview.css( 'background', value );
this.$input.val( value );
}
}
if ( value == '' || value == 'inherit' || value == 'transparent' ) {
this.$input.removeClass( 'white' );
} else {
this._invertInputColors( rgba );
}
this.parentSetValue( value, quiet );
},
/**
* Get the value.
* @return string
*/
getValue: function() {
return $.trim( this.$input.val() ) || '';
},
/**
* Get color, variables will be replaced with value
* @return {string}
*/
getColor: function() {
var value = this.getValue();
if ( value.indexOf( '_' ) !== - 1 ) {
var itemValue = $( '[data-name="' + value + '"]:first', this.$list ).data( 'value' ) || '';
value = itemValue || this.$color.data( 'value' ) || value;
}
return $.trim( value );
},
/**
* Set white text color for dark backgrounds
*
* @param {string} value
*/
_toggleInputColor: function( value ) {
if ( ! value ) {
this.$input.removeClass( 'white' );
return;
}
// If the HEX value is 3-digit, then convert it to 6-digit
if ( value.slice( 0, 1 ) === '#' && value.length === 4 ) {
value = value.replace( /^#([\dA-f])([\dA-f])([\dA-f])$/, "#$1$1$2$2$3$3" )
}
if (
value !== 'inherit'
&& value !== 'transparent'
&& value.indexOf( 'linear-gradient' ) === - 1
) {
if ( $.usof_colpick.colorNameToHex( value ) ) {
this._invertInputColors( $.usof_colpick.hexToRgba( $.usof_colpick.colorNameToHex( value ) ) );
} else {
this._invertInputColors( $.usof_colpick.hexToRgba( value ) );
}
} else if ( value.indexOf( 'linear-gradient' ) !== - 1 ) {
var gradient = $.usof_colpick.gradientParser( value );
// Make sure the gradient was parsed
if ( gradient != false ) {
this._invertInputColors( $.usof_colpick.hexToRgba( gradient.hex ) );
}
}
},
_invertInputColors: function( rgba ) {
if ( ! rgba && ( typeof rgba != 'object' ) ) {
return;
}
var r = rgba.r ? rgba.r : 0,
g = rgba.g ? rgba.g : 0,
b = rgba.b ? rgba.b : 0,
a = ( rgba.a === 0 || rgba.a ) ? rgba.a : 1,
light;
// Determine lightness of color
light = r * 0.213 + g * 0.715 + b * 0.072;
// Increase lightness regarding color opacity
if ( a < 1 ) {
light = light + ( 1 - a ) * ( 1 - light / 255 ) * 235;
}
if ( light < 178 ) {
this.$input.addClass( 'white' );
} else {
this.$input.removeClass( 'white' );
}
}
};
}( jQuery );