From 48c838e1d5f52a1346c14e1a2649f1823b07ed35 Mon Sep 17 00:00:00 2001 From: jamesros Date: Thu, 7 Sep 2023 12:28:31 -0400 Subject: [PATCH] New Background Controls (#542) * add legacy switching logic * update bg control * begin working on a react version * update controls * add saved-colors * fix logic for loading legacy control * remove console.log * updated jquery & sass worker builds * Do not show saved gradients in legacy color picker * fix opacity issues when changing color palette * add tooltips and selectedComponent * fix hover childs * add notice for new bg controls * fix hoverchild * update version for RC1 * update travis.yml * add tinycolor2 to yarn.lock * update comments * update nvmrc * fix spacing in control.js * fix comments in advanced.js * cleanup background.js * add file comments * removed unused styles.css file * remove unused template files * delete yarn-error.log * fix broken icon control * update boldgrid-panel * update readme * update travis.yml * remove wordpress_test for now --- .nvmrc | 2 +- .travis.yml | 7 +- assets/js/builder/component/icon/control.js | 53 +- assets/js/builder/controls.js | 8 +- .../js/builder/controls/element/advanced.js | 44 +- .../controls/element/background-legacy.js | 1966 ++++++++++++++ .../js/builder/controls/element/background.js | 1858 ++----------- assets/js/builder/notice/bg-control/index.js | 1 + assets/js/builder/notice/bg-control/notice.js | 64 + assets/js/builder/notice/loader.js | 6 +- assets/js/builder/panel.js | 18 +- assets/scss/_variables.scss | 15 + assets/scss/builder/panel/_background.scss | 27 + assets/scss/builder/panel/_navigation.scss | 11 +- babel.config.json | 5 + .../builder/class-boldgrid-editor-builder.php | 1 + includes/class-boldgrid-editor-assets.php | 6 +- includes/class-boldgrid-editor-setup.php | 20 + .../{background.php => background-legacy.php} | 2 +- includes/template/color.php | 6 +- package.json | 13 +- post-and-page-builder.php | 2 +- readme.txt | 5 +- tools/config/webpack.dev.js | 18 +- tools/config/webpack.prod.js | 15 +- yarn.lock | 2316 +++++++++++++---- 26 files changed, 4346 insertions(+), 2143 deletions(-) create mode 100644 assets/js/builder/controls/element/background-legacy.js create mode 100644 assets/js/builder/notice/bg-control/index.js create mode 100644 assets/js/builder/notice/bg-control/notice.js rename includes/template/{background.php => background-legacy.php} (99%) diff --git a/.nvmrc b/.nvmrc index e0bcfe01..f274881e 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v14.19.3 +v16.16.0 diff --git a/.travis.yml b/.travis.yml index 08d4f524..188913f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: php -dist: trusty +dist: xenial notifications: email: on_success: never @@ -10,13 +10,12 @@ php: - 7.1 - 5.6 before_script: -- nvm install 14.19.3 -- nvm use 14.19.3 +- nvm install 16.16.0 +- nvm use 16.16.0 - npm install -g gulp-cli - composer self-update --1 - composer install - yarn install -- bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION script: - npm run build deploy: diff --git a/assets/js/builder/component/icon/control.js b/assets/js/builder/component/icon/control.js index 2e4d8fd4..41d81768 100644 --- a/assets/js/builder/component/icon/control.js +++ b/assets/js/builder/component/icon/control.js @@ -188,27 +188,56 @@ BOLDGRID.EDITOR.CONTROLS = BOLDGRID.EDITOR.CONTROLS || {}; self.openPanel(); }, + /** + * Check if the target is the child of a hover box element. + * + * @since 1.25.0 + * + * @param {JQuery} $target Target Element + * + * @returns {boolean} True if the target is a hover child. + */ + isHoverChild: function( $target ) { + var $parent = $target.parent(); + + // Check if the target is a hover element. + if ( $parent.hasClass( 'has-hover-bg' ) || $parent.hasClass( 'has-hover-color' ) || $parent.hasClass( 'has-hover-image' )) { + return true; + } + + // Check if the target is inside a column that is a hover element. + if ( 0 !== $parent.closest( 'div[class*="col"].has-hover-bg' ).length + || 0 !== $parent.closest( 'div[class*="col"].has-hover-color' ).length + || 0 !== $parent.closest( 'div[class*="col"].has-hover-image' ).length + ) { + return true; + } + + // If the target is a row, it's parent will be a container, so ensure it's grandparent is a hover element. + if ( $target.is( 'div.row' ) && ( 0 !== $parent.parents( '.has-hover-bg' ).length + || 0 !== $parent.parents( '.has-hover-color' ).length + || 0 !== $parent.parents( '.has-hover-image' ).length ) + ) { + return true; + } + + return false; + }, + /** * Open the panel, setting the content. * * @since 1.2.7 */ openPanel: function() { - var $panel = BG.Panel.$element, - $menu = BG.Controls.$menu, - $target = $menu.targetData[self.name], - $parent = $target.parent(), + var $panel = BG.Panel.$element, + $menu = BG.Controls.$menu, + $target = $menu.targetData[self.name], hoverVisibilityIndex = this.panel.customizeSupport.indexOf( 'hoverVisibility' ), - isHoverChild = false, + isHoverChild = false, $selected; - if ( $parent.hasClass( 'has-hover-bg' ) ) { - isHoverChild = true; - } else if ( 0 !== $parent.closest( 'div[class*="col"].has-hover-bg' ).length ) { - isHoverChild = true; - } else if ( $target.is( 'div.row' ) && 0 !== $parent.parents( 'has-hover-bg' ).length ) { - isHoverChild = true; - } + isHoverChild = self.isHoverChild( $target ); if ( ! isHoverChild && -1 !== hoverVisibilityIndex ) { this.panel.customizeSupport.splice( hoverVisibilityIndex, 1 ); diff --git a/assets/js/builder/controls.js b/assets/js/builder/controls.js index 9552c915..8f88f3ef 100644 --- a/assets/js/builder/controls.js +++ b/assets/js/builder/controls.js @@ -266,7 +266,13 @@ BOLDGRID.EDITOR = BOLDGRID.EDITOR || {}; // Bind each menu control. $.each( this.controls, function() { - self.setupControl( this ); + /* + * For each given control, check for a loadLegacyControl method. + * If it does exist, that method will determine whether it loads or not. + */ + if ( ! this.hasOwnProperty( 'loadLegacyControl' ) || this.loadLegacyControl() ) { + self.setupControl( this ); + } } ); // Trigger a click on the body to display global controls. diff --git a/assets/js/builder/controls/element/advanced.js b/assets/js/builder/controls/element/advanced.js index 24e51d26..d3d580fc 100644 --- a/assets/js/builder/controls/element/advanced.js +++ b/assets/js/builder/controls/element/advanced.js @@ -42,6 +42,42 @@ export class Advanced { BG.Panel.$element.attr( 'data-element-type', targetType ); } + /** + * Check if the target is the child of a hover box element. + * + * @since 1.25.0 + * + * @param {JQuery} $target Target Element + * + * @returns {boolean} True if the target is a hover child. + */ + isHoverChild( $target ) { + var $parent = $target.parent(); + + // Check if the target is a hover element. + if ( $parent.hasClass( 'has-hover-bg' ) || $parent.hasClass( 'has-hover-color' ) || $parent.hasClass( 'has-hover-image' )) { + return true; + } + + // Check if the target is inside a column that is a hover element. + if ( 0 !== $parent.closest( 'div[class*="col"].has-hover-bg' ).length + || 0 !== $parent.closest( 'div[class*="col"].has-hover-color' ).length + || 0 !== $parent.closest( 'div[class*="col"].has-hover-image' ).length + ) { + return true; + } + + // If the target is a row, it's parent will be a container, so ensure it's grandparent is a hover element. + if ( $target.is( 'div.row' ) && ( 0 !== $parent.parents( '.has-hover-bg' ).length + || 0 !== $parent.parents( '.has-hover-color' ).length + || 0 !== $parent.parents( '.has-hover-image' ).length ) + ) { + return true; + } + + return false; + } + /** * Open the palette customization panel. * @@ -63,13 +99,7 @@ export class Advanced { $parent = $target.parents( '.boldgrid-section' ); } - if ( $parent.hasClass( 'has-hover-bg' ) ) { - isHoverChild = true; - } else if ( 0 !== $parent.closest( 'div[class*="col"].has-hover-bg' ).length ) { - isHoverChild = true; - } else if ( $target.is( 'div.row' ) && 0 !== $parent.parents( 'has-hover-bg' ).length ) { - isHoverChild = true; - } + isHoverChild = this.isHoverChild( $target ); hoverVisibilityIndex = this.panel.customizeSupport.indexOf( 'hoverVisibility' ); diff --git a/assets/js/builder/controls/element/background-legacy.js b/assets/js/builder/controls/element/background-legacy.js new file mode 100644 index 00000000..e6d25188 --- /dev/null +++ b/assets/js/builder/controls/element/background-legacy.js @@ -0,0 +1,1966 @@ +/** + * File: assets/js/builder/controls/element/background-legacy.js + * + * Legacy Background Control + * + * This file was moved from assets/js/builder/controls/element/background.js + * + * This file is used for legacy or non-crio themes that are not + * supported by the new background control. + * + * @since 1.25.0 + */ +window.BOLDGRID = window.BOLDGRID || {}; +BOLDGRID.EDITOR = BOLDGRID.EDITOR || {}; +BOLDGRID.EDITOR.CONTROLS = BOLDGRID.EDITOR.CONTROLS || {}; + +// Import Semver. +import { lt as semverLt } from 'semver'; + +( function( $ ) { + 'use strict'; + + var self, + BG = BOLDGRID.EDITOR; + + BOLDGRID.EDITOR.CONTROLS.Background = { + /** + * Name. + * + * @since 1.25.0 + * @type {string} + */ + name: 'background', + + /** + * Tooltip. + * + * @since 1.25.0 + * @type {string} + */ + tooltip: 'Background', + + /** + * uploadFrame. + * + * @since 1.25.0 + * @type {wp.media.view.MediaFrame | null } + */ + uploadFrame: null, + + + /** + * Priority. + * + * @since 1.25.0 + * @type {number} + */ + priority: 10, + + /** + * Currently controlled element. + * + * @since 1.25.0 + * @type {$} Jquery Element. + */ + $target: null, + + /** + * Tracking of clicked elements. + * + * @since 1.25.0 + * @type {Object>} + */ + layerEvent: { latestTime: 0, targets: [] }, + + /** + * Element Type. + * + * @since 1.25.0 + * @type {string} + */ + elementType: '', + + /** + * Is Hover Image + * + * @since 1.25.0 + * @type {boolean} + */ + isHoverImage: false, + + /** + * Icon Classes + * + * @since 1.25.0 + * @type {string} + */ + iconClasses: 'genericon genericon-picture', + + /** + * Selectors. + * + * @since 1.25.0 + * @type {Array} + */ + selectors: [ '.boldgrid-section', '.row', '[class*="col-md-"]', '.bg-box' ], + + /** + * Available Effects. + * + * @since 1.25.0 + * @type {Array} + */ + availableEffects: [ 'background-parallax', 'background-fixed' ], + + /** + * Available Hover Effects. + * + * @since 1.25.0 + * @type {Array} + */ + availableHoverEffects: [ 'background-hover-fixed' ], + + /** + * Menu Dropdown Config. + * + * @since 1.25.0 + * @type {Object>>} + */ + menuDropDown: { + title: 'Background', + options: [ + { + name: 'Section', + class: 'action section-background' + }, + { + name: 'Row', + class: 'action row-background' + }, + { + name: 'Column', + class: 'action column-background' + }, + { + name: 'Column Shape', + class: 'action column-shape-background' + } + ] + }, + + /** + * Panel Confg. + * + * @since 1.25.0 + * + * @type {Object, sizeOffset: number>} + */ + panel: { + title: 'Background', + height: '625px', + width: '450px', + scrollTarget: '.presets', + customizeSupport: [ + 'margin', + 'padding', + 'border', + 'width', + 'box-shadow', + 'animation', + 'border-radius', + 'blockAlignment', + 'device-visibility', + 'customClasses' + ], + sizeOffset: -230 + }, + + /** + * Control Init + * + * @since 1.25.0 + */ + init: function() { + if ( this.loadLegacyControl() ) { + BOLDGRID.EDITOR.Controls.registerControl( this ); + } + }, + + /** + * Load Legacy Control + * + * This determines whether or not to load this control based on + * a set of conditions. This is run in legacy controls, and in new + * controls that have a legacy version. + * + * @since 1.25.0 + * + * @return {boolean} Whether or not to load this control. + */ + loadLegacyControl() { + var maxCrioVersion = '2.20.0', // Crio 2.20.0 is the first version to support the new BG control. + isCrio = BoldgridEditor.is_crio; + + // The new BG control doesn't work with non-crio themes, so load this instead. + if ( ! isCrio ) { + return true; + } + + // Load legacy controls if we're using a Crio theme that is less than the max version. + if ( semverLt( BoldgridEditor.theme_version, maxCrioVersion ) ) { + return true; + } + + return false; + }, + + /** + * Setup Hover Boxes. + * + * @since 1.17.0 + */ + _setupHoverBoxes() { + var css = '', + $head = $( tinyMCE.activeEditor.iframeElement ) + .contents() + .find( 'head' ), + $body = $( tinyMCE.activeEditor.iframeElement ) + .contents() + .find( 'body' ), + $hoverBoxes = $body.find( '.has-hover-bg' ); + + $hoverBoxes.each( ( index, hoverBox ) => { + var $hoverBox = $( hoverBox ), + hoverBoxClass = $hoverBox.attr( 'data-hover-bg-class' ), + hoverBgUrl = $hoverBox.attr( 'data-hover-image-url' ), + hoverOverlay = $hoverBox.attr( 'data-hover-bg-overlaycolor' ), + hoverBgSize = $hoverBox.attr( 'data-hover-bg-size' ), + hoverBgSize = hoverBgSize ? hoverBgSize : 'cover', + hoverBgPos = $hoverBox.attr( 'data-hover-bg-position' ), + hoverBgPos = hoverBgPos ? hoverBgPos : '50', + hoverBgColor = $hoverBox.attr( 'data-hover-bg-color' ); + + if ( 'cover' === hoverBgSize ) { + hoverBgSize = + 'background-size: cover !important; background-repeat: "unset !important";'; + } else { + hoverBgSize = + 'background-size: auto auto !important; background-repeat: repeat !important;'; + } + + if ( hoverOverlay && hoverBgUrl ) { + css = `.${hoverBoxClass}:hover {`; + css += `background-image: linear-gradient(to left, ${hoverOverlay}, ${ + hoverOverlay + } ), url('${hoverBgUrl}') !important; }`; + $head.append( `` ); + + css = `.${hoverBoxClass}:hover { background-position: 50% ${hoverBgPos}% !important; }`; + $head.append( `` ); + + css = `.${hoverBoxClass}:hover { ${hoverBgSize} }`; + $head.append( `` ); + } else if ( hoverBgUrl ) { + css = `.${hoverBoxClass}:hover {`; + css += `background-image: url('${hoverBgUrl}') !important; }`; + $head.append( `` ); + + css = `.${hoverBoxClass}:hover { background-position: 50% ${hoverBgPos}% !important; }`; + $head.append( `` ); + + css = `.${hoverBoxClass}:hover { ${hoverBgSize} }`; + $head.append( `` ); + } + + if ( hoverBgColor && hoverBgUrl ) { + css = `.${hoverBoxClass}:hover { background-color: ${hoverBgColor} !important; }`; + $head.append( `` ); + } else if ( hoverBgColor && ! hoverBgUrl ) { + css = `.${hoverBoxClass}:hover { background-color: ${hoverBgColor} !important; }`; + $head.append( `` ); + + css = `.${hoverBoxClass}:hover {background-image: unset !important; }`; + $head.append( `` ); + } + + css = '@media screen and (max-width: 991px) {'; + if ( hoverBoxClass && hoverBgUrl && hoverOverlay ) { + let hoverCss = self.getOverlayImage( hoverOverlay ) + ', url("' + hoverBgUrl + '")'; + css += `.${hoverBoxClass}.hover-mobile-bg {background-image: ${hoverCss} !important; }`; + css += `.${hoverBoxClass}.hover-mobile-bg:hover {background-image: ${ + hoverCss + } !important; }`; + } else if ( hoverBoxClass && ! hoverBgUrl && hoverBgColor ) { + css += `.${hoverBoxClass}.hover-mobile-bg { + background-color: ${hoverBgColor} !important; + background-image: none !important; + }`; + } else { + css += `.${hoverBoxClass}.hover-mobile-bg { background-image: url('${ + hoverBgUrl + }') !important; } }`; + } + $head.append( `` ); + } ); + }, + + /** + * Get the current target. + * + * @since 1.8.0 + * @return {jQuery} Element. + */ + getTarget: function() { + return self.$target; + }, + + /** + * When the user clicks on a menu item, update the available options. + * + * @since 1.8.0 + */ + onMenuClick: function() { + self.updateMenuOptions(); + }, + + /** + * Update the avilable options in the background drop down. + * + * @since 1.8.0 + */ + updateMenuOptions: function() { + let availableOptions = []; + + for ( let target of self.layerEvent.targets ) { + availableOptions.push( self.checkElementType( $( target ) ) ); + } + + self.$menuItem.attr( 'data-available-options', availableOptions.join( ',' ) ); + }, + + /** + * When a menu item is reopened because a user clicked on another similar element + * Update the available options. + * + * @since 1.8.0 + */ + _setupMenuReactivate: function() { + self.$menuItem.on( 'reactivate', self.updateMenuOptions ); + }, + + /** + * When the user clicks Add Image open the media library. + * + * @since 1.2.7 + * + * @param {boolean} isHoverImage Whether or not this is a hover image. + */ + _setupAddImage: function( isHoverImage = false ) { + var addMediaClass = isHoverImage ? '.add-hover-image-controls' : '.add-image-controls'; + BG.Panel.$element.on( 'click', '.background-design ' + addMediaClass, function() { + self.isHoverImage = $( this ).hasClass( 'add-hover-image-controls' ); + + // If the media frame already exists, reopen it. + if ( self.uploadFrame ) { + self.uploadFrame.open(); + return; + } + + // Create a new media frame. + self.uploadFrame = wp.media( { + title: 'Select Background Image', + library: { type: 'image' }, + button: { + text: 'Use this media' + }, + + // Set to true to allow multiple files to be selected. + multiple: false + } ); + + // When an image is selected in the media frame. + self.uploadFrame.on( 'select', function() { + + // Get media attachment details from the frame state. + var attachment = self.uploadFrame + .state() + .get( 'selection' ) + .first() + .toJSON(); + + var hoverImage = self.isHoverImage ? true : false; + + // Set As current selection and apply to background. + self.setImageBackground( attachment.url, hoverImage ); + if ( hoverImage ) { + self.setImageSelection( 'hover-image', attachment.url, hoverImage ); + } else { + self.setImageSelection( 'image', attachment.url, hoverImage ); + } + } ); + + // Finally, open the modal on click. + self.uploadFrame.open(); + } ); + }, + + /** + * Open the editor panel for a given selector and store element as target. + * + * @since 1.8.0 + * + * @param {string} selector Selector. + */ + open( selector ) { + for ( let target of self.layerEvent.targets ) { + let $target = $( target ); + if ( $target.is( selector ) ) { + self.openPanel( $target ); + } + } + }, + + /** + * When the user clicks on an element within the mce editor record the element clicked. + * + * @since 1.8.0 + * + * @param {MouseEvent} event DOM Event + */ + elementClick( event ) { + if ( self.layerEvent.latestTime !== event.timeStamp ) { + self.layerEvent.latestTime = event.timeStamp; + self.layerEvent.targets = []; + } + + self.layerEvent.targets.push( event.currentTarget ); + }, + + /** + * Bind each of the sub menu items. + * + * @since 1.8.0 + */ + _setupMenuClick() { + BG.Menu.$element + .find( '.bg-editor-menu-dropdown' ) + .on( 'click', '.action.column-background', () => self.open( '[class*="col-md"]' ) ) + .on( 'click', '.action.column-shape-background', () => self.open( '.bg-box' ) ) + .on( 'click', '.action.row-background', () => self.open( '.row' ) ) + .on( 'click', '.action.section-background', () => self.open( '.boldgrid-section' ) ); + }, + + /** + * Setup Init. + * + * @since 1.2.7 + */ + setup: function() { + self.$menuItem = BG.Menu.$element.find( '[data-action="menu-background"]' ); + + self._setupHoverBoxes(); + self._setupMenuReactivate(); + self._setupMenuClick(); + self._setupBackgroundClick(); + self._setupFilterClick(); + self._setupCustomizeLeave(); + self._setupBackgroundSize(); + self._setupBackgroundColor(); + self._setupGradientColor(); + self._setupOverlayColor(); + self._setupOverlayReset(); + self._setupScrollEffects(); + self._setupGradientDirection(); + self._setupCustomization(); + self._setupAddImage(); + self._setupHoverImage(); + self._setupMobileVisibility(); + }, + + /** + * Setup Hover Image. + * + * @since 1.17.0 + */ + _setupHoverImage: function() { + self._setupAddImage( true ); + }, + + /** + * Adds hover styles to header. + * + * @since 1.17.0 + * + * @param {string} styleId Style ID. + * @param {string} css Css to add + */ + _addHeadingStyle: function( styleId, css ) { + var $target = self.getTarget(), + $body = $target.parents( 'body' ), + $head = $body.parent().find( 'head' ); + + if ( $head.find( '#' + styleId ).length ) { + $head.find( '#' + styleId ).remove(); + } + + $head.append( '' ); + }, + + /** + * Adds Hover Effects + * + * @since 1.17.0 + */ + _addHoverEffects: function() { + var $target = self.getTarget(), + $body = $target.parents( 'body' ), + $hoverBgs = $body.find( '.has-hover-bg' ), + css = ''; + + $hoverBgs.each( function() { + var hoverBgClassName = $( this ).attr( 'data-hover-bg-class' ), + hoverBgUrl = $( this ).attr( 'data-hover-image-url' ), + hoverOverlay = $( this ).attr( 'data-hover-bg-overlaycolor' ), + hoverBgColor = $( this ).attr( 'data-hover-bg-color' ); + + if ( hoverBgClassName && hoverBgUrl && hoverOverlay ) { + let hoverCss = self.getOverlayImage( hoverOverlay ) + ', url("' + hoverBgUrl + '")'; + css = `.${hoverBgClassName}:hover {background-image: ${hoverCss} !important; }`; + self._addHeadingStyle( hoverBgClassName + '-image', css ); + } else { + css = `.${hoverBgClassName}:hover {background-image: url('${hoverBgUrl}') !important; }`; + self._addHeadingStyle( hoverBgClassName + '-image', css ); + } + + css = `.${ + hoverBgClassName + }:hover {background-size: cover !important; background-position: 50%, 50% !important;}`; + self._addHeadingStyle( hoverBgClassName + '-bg-size', css ); + + css = '@media screen and (max-width: 991px) {'; + if ( hoverBgClassName && hoverBgUrl && hoverOverlay ) { + let hoverCss = self.getOverlayImage( hoverOverlay ) + ', url("' + hoverBgUrl + '")'; + css += `.${hoverBgClassName}.hover-mobile-bg {background-image: ${ + hoverCss + } !important; }`; + css += `.${hoverBgClassName}.hover-mobile-bg:hover {background-image: ${ + hoverCss + } !important; }`; + } else if ( hoverBgClassName && ! hoverBgUrl && hoverBgColor ) { + css += `.${hoverBgClassName}.hover-mobile-bg { + background-color: ${hoverBgColor} !important; + background-image: none !important; + }`; + } else { + css += `.${hoverBgClassName}.hover-mobile-bg { background-image: url('${ + hoverBgUrl + }') !important; } }`; + } + self._addHeadingStyle( hoverBgClassName + '-mobile-image', css ); + } ); + }, + + /** + * Bind Event: Change background section color. + * + * @since 1.2.7 + */ + _setupBackgroundColor: function() { + var panel = BG.Panel; + + panel.$element.on( + 'change', + '.background-design [name="section-background-color"]', + function() { + var $this = $( this ), + $target = self.getTarget(), + value = $this.val(), + type = $this.attr( 'data-type' ), + $currentSelection = BG.Panel.$element.find( '.current-selection' ), + selectionType = $currentSelection.attr( 'data-type' ), + classFromColor = self.classFromColor( value ), + alphaFromColor = self.alphaFromColor( value ); + + self.removeColorClasses( $target ); + BG.Controls.addStyle( $target, 'background-color', '' ); + + // If currently selected is a gradient. + if ( 'pattern' !== selectionType ) { + BG.Controls.addStyle( $target, 'background-image', '' ); + $target.removeAttr( 'data-bg-color-1' ); + $target.removeAttr( 'data-bg-color-2' ); + $target.removeAttr( 'data-bg-direction' ); + } + if ( 'pattern' !== selectionType ) { + BG.Panel.$element.find( '.presets .selected' ).removeClass( 'selected' ); + } + + if ( 'class' === type ) { + $target + .addClass( 'bg-background-color' ) + .addClass( BG.CONTROLS.Color.getColorClass( 'background-color', value ) ) + .addClass( BG.CONTROLS.Color.getColorClass( 'text-contrast', value ) ); + } else if ( classFromColor ) { + $target + .addClass( 'bg-background-color' ) + .addClass( BG.CONTROLS.Color.getColorClass( 'background-color', classFromColor ) ) + .addClass( BG.CONTROLS.Color.getColorClass( 'text-contrast', classFromColor ) ) + .attr( 'data-alpha', alphaFromColor ); + + self.paletteAddAlpha( + $target, + value, + BG.CONTROLS.Color.getColorClass( 'background-color', classFromColor ) + ); + } else { + BG.Controls.addStyle( $target, 'background-color', value ); + } + self.setImageSelection( selectionType, $target.css( 'background' ) ); + BOLDGRID.EDITOR.CONTROLS.SectionDividers.detectFillColors(); + } + ); + + panel.$element.on( + 'change', + '.background-design [name="section-hover-background-color"]', + function() { + var $this = $( this ), + $target = self.getTarget(), + value = $this.val(), + type = $this.attr( 'data-type' ), + hoverClass = $target.attr( 'data-hover-bg-class' ), + isGridBlock = $target.hasClass( 'dynamic-gridblock' ), + isCrio = BoldgridEditor.is_crio, + css = ''; + + if ( ! $target.hasClass( 'has-hover-bg' ) ) { + $target.addClass( 'has-hover-bg' ); + } + + if ( ! hoverClass ) { + hoverClass = 'hover-bg-' + Math.floor( Math.random() * 999 + 1 ).toString(); + $target.attr( 'data-hover-bg-class', hoverClass ); + $target.addClass( hoverClass ); + } + + if ( '' === value ) { + $target.attr( 'data-hover-bg-color', 'unset' ); + css = `.${hoverClass}:hover {background-color: ${$target.attr( + 'data-hover-bg-color' + )} !important;}`; + self._addHeadingStyle( hoverClass + '-bg-color', css ); + $target + .parents( 'html' ) + .find( 'head' ) + .find( hoverClass + '-bg-color' ) + .remove(); + + if ( ! $target.attr( 'data-hover-image-url' ) ) { + $target.removeAttr( 'data-hover-bg-class' ); + $target.removeClass( 'has-hover-bg' ); + $target.removeClass( hoverClass ); + self.setImageSelection( 'hover-color' ); + return; + } else { + self.setImageSelection( 'hover-image' ); + return; + } + } + + if ( 'class' === type && ( isGridBlock || ! isCrio ) ) { + value = 'neutral' === value ? value : parseInt( value ) - 1; + let color = + 'neutral' === value ? + BoldgridEditor.colors.neutral : + BoldgridEditor.colors.defaults[value]; + $target.attr( 'data-hover-bg-color', color ); + } else if ( 'class' === type ) { + $target.attr( 'data-hover-bg-color', 'var(--color-' + value + ')' ); + } else { + $target.attr( 'data-hover-bg-color', value ); + } + + css = `.${hoverClass}:hover {background-color: ${$target.attr( + 'data-hover-bg-color' + )} !important;}`; + self._addHeadingStyle( hoverClass + '-bg-color', css ); + + if ( ! $target.attr( 'data-hover-image-url' ) ) { + css = `.${hoverClass}:hover {background-image: none !important;}`; + self._addHeadingStyle( hoverClass + '-image', css ); + } + + self.setImageSelection( 'hover-color' ); + } + ); + }, + + /** + * Add alpha component to background color palettes + * + * @param {jQuery Object} $target The target jQuery object + * @param {string} value Background color value + * @param {string} bgColorClass Background Color class + */ + paletteAddAlpha( $target, value, bgColorClass ) { + var uuid = 'bg-alpha-' + Math.floor( Math.random() * 999 + 1 ).toString(), + $head = $( tinyMCE.activeEditor.iframeElement ) + .contents() + .find( 'head' ), + css; + + if ( $target.attr( 'data-bg-uuid' ) ) { + uuid = $target.attr( 'data-bg-uuid' ); + } else { + $target.attr( 'data-bg-uuid', uuid ); + $target.addClass( uuid ); + } + + $head.find( '#' + uuid + '-inline-style' ).remove(); + + css = `.${bgColorClass}.${uuid} {background-color: ${value} !important;}`; + + $head.append( '' ); + }, + + /** + * Obtains the alpha ( opacity ) value of an RGBA string. + * + * @since 1.25.0 + * + * @param {string} color RGBA Color String. + * + * @returns {string} Alpha value of a color + */ + alphaFromColor: function( color ) { + var alpha = 1; + + if ( color.includes( 'rgba' ) ) { + alpha = color.replace( /rgba\(\d{1,3}\,\d{1,3}\,\d{1,3}\,(.*\))/, '$1' ); + alpha = alpha.replace( ')', '' ); + } + + return alpha; + }, + + /** + * Determine the color class, if any, that matches an RGB(A) String. + * + * @since 1.25.0 + * + * @param {string} color RGB(A) color string + * + * @returns {string} The color class associated with this color string. + */ + classFromColor: function( color ) { + var colors = BoldgridEditor.colors.defaults, + neutralColor = BoldgridEditor.colors.neutral, + colorClass = false; + + if ( color.includes( 'rgba' ) ) { + color = color.replace( /(rgba\(\d{1,3}\,\d{1,3}\,\d{1,3})(.*\))/, '$1)' ); + color = color.replace( 'rgba', 'rgb' ); + } else if ( ! color.includes( 'rgb' ) ) { + return colorClass; + } + + color = color.replace( /\s/g, '' ); + + for ( let key in colors ) { + if ( colors[key].replace( /\s/g, '' ) === color ) { + colorClass = parseInt( key ) + 1; + break; + } + } + + if ( color === neutralColor ) { + colorClass = 'neutral'; + } + + return colorClass; + }, + + /** + * Add color palette for overlays to the target. + * + * @since 1.25.0 + * + * @param {object} $target jQuery object of the target element. + * @param {string} value The value of the color. + * @param {string} bgColorClass The color class string. + */ + paletteAddOverlayAlpha( $target, value, bgColorClass ) { + var image = $target.attr( 'data-image-url' ), + color = value; + + BG.Controls.addStyle( + $target, + 'background-image', + self.getOverlayImage( color ) + ', url("' + image + '")' + ); + }, + + /** + * Bind Event: Set the default color for overlay. + * + * @since 1.2.7 + */ + _setupOverlayReset: function() { + var panel = BG.Panel; + + panel.$element.on( 'click', '.background-design .overlay-color .default-color', function( e ) { + var $this = $( this ), + $target = self.getTarget(); + + e.preventDefault(); + + $this + .closest( '.color-controls' ) + .find( 'label' ) + .css( 'background-color', 'rgba(255,255,255,.5)' ); + + $target.removeAttr( 'data-bg-overlaycolor' ); + $target.removeAttr( 'data-bg-overlaycolor-alpha' ); + $target.removeAttr( 'data-bg-overlaycolor-class' ); + + self.updateBackgroundImage(); + } ); + }, + + /** + * Bind Event: Change overlay color. + * + * @since 1.2.7 + */ + _setupOverlayColor: function() { + var panel = BG.Panel; + + panel.$element.on( 'change', '.background-design [name="overlay-color"]', function() { + var $this = $( this ), + type = $this.attr( 'data-type' ), + value = $this.val(), + $target = self.getTarget(), + classFromColor = self.classFromColor( value ), + alphaFromColor = self.alphaFromColor( value ); + + if ( 'class' === type ) { + value = BoldgridEditor.colors.defaults[value - 1]; + $target.attr( 'data-bg-overlaycolor', value ); + } else if ( classFromColor ) { + $target.attr( 'data-bg-overlaycolor', value ), + $target.attr( 'data-bg-overlaycolor-alpha', alphaFromColor ); + $target.attr( 'data-bg-overlaycolor-class', classFromColor ); + self.paletteAddOverlayAlpha( + $target, + value, + BG.CONTROLS.Color.getColorClass( 'background-color', classFromColor ) + ); + } else { + $target.attr( 'data-bg-overlaycolor', value ); + } + + self.updateBackgroundImage(); + } ); + + panel.$element.on( 'change', '.background-design [name="hover-overlay-color"]', function() { + var $this = $( this ), + type = $this.attr( 'data-type' ), + value = $this.val(), + $target = self.getTarget(); + + if ( 'class' === type ) { + value = 'var(--color-' + value + ')'; + } + + $target.attr( 'data-hover-bg-overlaycolor', value ); + + self.updateBackgroundImage(); + } ); + }, + + /** + * Update background image on page. + * + * @since 1.2.7 + */ + updateBackgroundImage: function() { + var $target = self.getTarget(), + overlay = $target.attr( 'data-bg-overlaycolor' ), + image = $target.attr( 'data-image-url' ); + + if ( overlay && image ) { + BG.Controls.addStyle( + $target, + 'background-image', + self.getOverlayImage( overlay ) + ', url("' + image + '")' + ); + } else if ( image ) { + BG.Controls.addStyle( $target, 'background-image', 'url("' + image + '")' ); + } + + self._addHoverEffects(); + }, + + /** + * Create gradient overlay string. + * + * @since 1.2.7 + * + * @param {string} color. + * + * @return {string} color. + */ + getOverlayImage: function( color ) { + return 'linear-gradient(to left, ' + color + ', ' + color + ')'; + }, + + /** + * Bind Event: Changing Gradient Color. + * + * @since 1.2.7 + */ + _setupGradientColor: function() { + var panel = BG.Panel; + + panel.$element.on( 'change', '.background-design [name^="gradient-color"]', function() { + var $this = $( this ), + $target = self.getTarget(), + value = $this.val(), + name = $this.attr( 'name' ), + type = $this.attr( 'data-type' ); + + if ( BoldgridEditor.is_crio ) { + if ( 'class' === type && 'neutral' !== value ) { + value = 'var( --color-' + value + ' )'; + } else if ( 'class' === type && 'neutral' === value ) { + value = 'var( --color-neutral )'; + } + } else if ( 'class' === type ) { + value = BoldgridEditor.colors.defaults[value - 1]; + } + + if ( 'gradient-color-1' === name ) { + $target.attr( 'data-bg-color-1', value ); + } else { + $target.attr( 'data-bg-color-2', value ); + } + + BG.Controls.addStyle( $target, 'background-image', self.createGradientCss( $target ) ); + } ); + }, + + /** + * Bind Event: Clicking Settings. + * + * @since 1.2.7 + */ + _setupCustomization: function() { + var panel = BG.Panel; + + panel.$element.on( 'click', '.current-selection .settings .panel-button.customizer', function( + e + ) { + e.preventDefault(); + self.openCustomization(); + } ); + + panel.$element.on( + 'click', + '.current-selection:not( [data-type=hover-image] ) .settings .panel-button.remove-background', + function( e ) { + e.preventDefault(); + self._removeImage(); + } + ); + panel.$element.on( + 'click', + '.current-selection[data-type=hover-image] .settings .panel-button.remove-background', + function( e ) { + e.preventDefault(); + self._removeImage( e, 'hover-image' ); + } + ); + }, + + /** + * Button to remove an image. + * + * @since 1.12.0 + * + * @param {MouseEvent} e DOM Event + * @param {string} type Type of image to remove. + */ + _removeImage( e, type ) { + var $target = self.getTarget(), + bgHoverClass = $target.attr( 'data-hover-bg-class' ), + styleIdSuffixes = [ 'image', 'bg-size', 'mobile-image', 'position', 'bg-color' ]; + + if ( 'hover-image' === type ) { + + // Remove Hover Styles from head. + styleIdSuffixes.forEach( function( styleIdSuffix ) { + $target + .parents( 'html' ) + .find( 'head' ) + .find( `#${bgHoverClass}-${styleIdSuffix}` ) + .remove(); + } ); + + // Remove Image and Overlay attributes. + $target.removeAttr( 'data-hover-image-url' ); + $target.removeAttr( 'data-hover-bg-overlaycolor' ); + $target.removeAttr( 'data-hover-bg-position' ); + $target.removeAttr( 'data-hover-bg-size' ); + + // Remove Hover Color Attributes. + $target.removeAttr( 'data-hover-bg-color' ); + + // Remove hover class and atribute. + $target.removeAttr( 'data-hover-bg-class' ); + $target.removeClass( 'has-hover-bg' ); + $target.removeClass( bgHoverClass ); + + BG.Panel.$element.find( '.add-hover-image-controls' ).removeAttr( 'style' ); + + self.setImageSelection( 'hover-color' ); + } else { + self.removeColorClasses( $target ); + BG.Controls.addStyle( $target, 'background', '' ); + $target.removeAttr( 'data-image-url' ); + + BG.Panel.$element.find( '.presets .selected' ).removeClass( 'selected' ); + + // Reset Gradient attributes. + $target + .removeAttr( 'data-bg-color-1' ) + .removeAttr( 'data-image-url' ) + .removeAttr( 'data-bg-color-2' ) + .removeAttr( 'data-bg-overlaycolor' ) + .removeAttr( 'data-bg-direction' ); + self.setImageSelection( 'color' ); + } + }, + + /** + * Setup mobile visibility controls + * + * @since 1.17.0 + */ + _setupMobileVisibility: function() { + var panel = BG.Panel; + panel.$element.on( + 'change', + '.background-design input[name="mobile-only-visibility"]', + function() { + var $this = $( this ), + $target = self.getTarget(), + classes = [ 'hover-mobile-bg' ]; + + switch ( $this.val() ) { + case 'hover': + $target.removeClass( classes ); + $target.addClass( 'hover-mobile-bg' ); + break; + default: + $target.removeClass( classes ); + break; + } + } + ); + }, + + /** + * Bind Event: Input scroll effect changing. + * + * @since 1.2.7 + */ + _setupScrollEffects: function() { + var panel = BG.Panel; + + panel.$element.on( 'change', '.background-design input[name="scroll-effects"]', function() { + var $this = $( this ), + $target = self.getTarget(); + + if ( 'none' === $this.val() ) { + $target.removeClass( self.availableEffects.join( ' ' ) ); + } else { + $target.removeClass( self.availableEffects.join( ' ' ) ); + $target.addClass( $this.val() ); + } + } ); + + panel.$element.on( + 'change', + '.background-design input[name="hover-scroll-effects"]', + function() { + var $this = $( this ), + $target = self.getTarget(); + + if ( 'none' === $this.val() ) { + $target.removeClass( self.availableHoverEffects.join( ' ' ) ); + } else { + $target.removeClass( self.availableHoverEffects.join( ' ' ) ); + $target.addClass( $this.val() ); + } + } + ); + }, + + /** + * Bind Event: Input gradient direction changing. + * + * @since 1.2.7 + */ + _setupGradientDirection: function() { + var panel = BG.Panel; + + panel.$element.on( 'change', '.background-design input[name="bg-direction"]', function() { + var $this = $( this ), + $target = self.getTarget(); + + $target.attr( 'data-bg-direction', $this.val() ); + BG.Controls.addStyle( $target, 'background-image', self.createGradientCss( $target ) ); + } ); + }, + + /** + * Create the css needed for a linear gradient. + * + * @since 1.2.7 + * @param {jQuery} $element Selected element. + */ + createGradientCss: function( $element ) { + return ( + 'linear-gradient(' + + $element.attr( 'data-bg-direction' ) + + ',' + + $element.attr( 'data-bg-color-1' ) + + ',' + + $element.attr( 'data-bg-color-2' ) + + ')' + ); + }, + + /** + * Setup background size control. + * + * @since 1.2.7 + */ + _setupBackgroundSize: function( isHoverImage ) { + var panel = BG.Panel; + + panel.$element.on( + 'change', + '.background-design input[name="hover-background-size"]', + function() { + var $this = $( this ), + $target = self.getTarget(), + hoverBgId = $target.attr( 'data-hover-bg-class' ), + css = ''; + + if ( 'tiled' === $this.val() ) { + css = + '.' + + hoverBgId + + ':hover { background-size: auto auto !important; background-repeat: repeat !important; }'; + self._addHeadingStyle( hoverBgId + '-bg-size', css ); + $target.attr( 'data-hover-bg-size', 'tiled' ); + } else if ( 'cover' == $this.val() ) { + css = + '.' + + hoverBgId + + ':hover { background-size: cover !important; background-repeat: "unset !important"; }'; + self._addHeadingStyle( hoverBgId + '-bg-size', css ); + $target.attr( 'data-hover-bg-size', 'cover' ); + } + } + ); + + panel.$element.on( 'change', '.background-design input[name="background-size"]', function() { + var $this = $( this ), + $target = self.getTarget(); + + if ( 'tiled' === $this.val() ) { + BG.Controls.addStyle( $target, 'background-size', 'auto auto' ); + BG.Controls.addStyle( $target, 'background-repeat', 'repeat' ); + } else if ( 'cover' === $this.val() ) { + BG.Controls.addStyle( $target, 'background-size', 'cover' ); + BG.Controls.addStyle( $target, 'background-repeat', 'unset' ); + } + } ); + }, + + /** + * Bind Event: When the user leaves customization. + * + * @since 1.2.7 + */ + _setupCustomizeLeave: function() { + var panel = BG.Panel; + + panel.$element.on( 'click', '.background-design .back .panel-button', function( e ) { + e.preventDefault(); + + panel.$element.find( '.preset-wrapper' ).show(); + panel.$element.find( '.background-design .customize' ).hide(); + panel.initScroll(); + self.preselectBackground(); + panel.scrollToSelected(); + BG.Service.customize.navigation.disable(); + } ); + }, + + /** + * Bind Event: When the user clicks on a filter. + * + * @since 1.2.7 + */ + _setupFilterClick: function() { + var panel = BG.Panel; + + panel.$element.on( 'click', '.background-design .filter', function( e ) { + e.preventDefault(); + + let $this = $( this ), + type = $this.data( 'type' ), + label = $this.data( 'label' ), + $currentSelection = panel.$element.find( '.current-selection' ), + $presetsBackgroundColor = panel.$element.find( '.presets .background-color.section' ), + $target = self.getTarget(), + bgColor = $target.css( 'background-color' ); + + panel.$element.find( '.filter' ).removeClass( 'selected' ); + $this.addClass( 'selected' ); + + panel.$element.find( '.presets .selection' ).hide(); + $.each( type, function() { + panel.$element.find( '.presets .selection[data-type="' + this + '"]' ).show(); + } ); + + panel.$element.find( '.presets .title > *' ).text( label ); + panel.$element.find( '.presets' ).attr( 'data-filter', type ); + $currentSelection.attr( 'data-filter', type ); + + if ( type.length && type.includes( 'hover' ) ) { + let selectionType = $target.attr( 'data-hover-image-url' ) ? 'hover-image' : 'hover-color'; + $currentSelection.attr( 'data-type', selectionType ); + self.setImageSelection( selectionType, bgColor ); + } + + if ( + type.length && + ! type.includes( 'gradients' ) && + ( type.includes( 'image' ) || type.includes( 'color' ) || type.includes( 'pattern' ) ) + ) { + let selectionType = $target.attr( 'data-image-url' ) ? 'image' : 'color'; + $currentSelection.attr( 'data-type', selectionType ); + self.setImageSelection( selectionType, bgColor ); + } + + if ( type.length && type.includes( 'gradients' ) ) { + let selectionType = 'gradients'; + $currentSelection.attr( 'data-type', selectionType ); + self.setImageSelection( selectionType, $target.css( 'background-image' ) ); + } + + if ( + ( type.length && -1 !== type.indexOf( 'image' ) ) || + ( type.length && -1 !== type.indexOf( 'hover' ) ) + ) { + $presetsBackgroundColor.hide(); + } else { + $presetsBackgroundColor.show(); + } + + panel.scrollToSelected(); + } ); + }, + + /** + * Remove all color classes. + * + * @since 1.2.7 + * @param {jQuery} $target Currently selected target. + */ + removeColorClasses: function( $target ) { + $target.removeClass( 'bg-background-color' ); + $target.removeClass( BG.CONTROLS.Color.backgroundColorClasses.join( ' ' ) ); + $target.removeClass( BG.CONTROLS.Color.textContrastClasses.join( ' ' ) ); + }, + + /** + * Bind Event: When the user clicks on a design. + * + * @since 1.2.7 + */ + _setupBackgroundClick: function() { + var panel = BG.Panel; + + panel.$element.on( 'click', '.background-design .presets .selection', function() { + var $this = $( this ), + $target = self.getTarget(), + imageUrl = $this.attr( 'data-image-url' ), + imageSrc = $this.css( 'background-image' ), + background = $this.css( 'background' ), + bgUuid = $target.attr( 'data-bg-uuid' ), + value; + + if ( $this.hasClass( 'selected' ) ) { + self.removeColorClasses( $target ); + BG.Controls.addStyle( $target, 'background', '' ); + $target.removeAttr( 'data-image-url' ); + $this.removeClass( 'selected' ); + self.preselectBackground( true ); + + return; + } + + panel.$element.find( '.presets .selected' ).removeClass( 'selected' ); + $this.addClass( 'selected' ); + + // Reset Gradient attributes. + $target + .removeAttr( 'data-bg-color-1' ) + .removeAttr( 'data-image-url' ) + .removeAttr( 'data-bg-color-2' ) + .removeAttr( 'data-bg-direction' ); + + // Reset Alpha attributes. + $target + .removeAttr( 'data-bg-alpha' ) + .removeAttr( 'data-bg-uuid' ) + .removeClass( bgUuid ); + + if ( 'pattern' !== $this.data( 'type' ) ) { + self.removeColorClasses( $target ); + } + + if ( 'image' === $this.data( 'type' ) ) { + self.setImageBackground( imageUrl ); + } else if ( 'color' === $this.data( 'type' ) ) { + $target.addClass( $this.data( 'class' ) ); + value = $this.data( 'class' ); + value = value.includes( 'neutral' ) ? 'neutral' : value.replace( /\D/g, '' ); + $target.addClass( BG.CONTROLS.Color.getColorClass( 'text-contrast', value ) ); + $target.addClass( 'bg-background-color' ); + BG.Controls.addStyle( $target, 'background-image', '' ); + self.setDefaultBackgroundColors(); + } else if ( 'pattern' === $this.data( 'type' ) ) { + BG.Controls.addStyle( $target, 'background-size', 'auto auto' ); + BG.Controls.addStyle( $target, 'background-repeat', 'repeat' ); + BG.Controls.addStyle( $target, 'background-image', imageSrc ); + } else if ( 'gradients' === $this.data( 'type' ) ) { + $target + .attr( 'data-bg-color-1', $this.data( 'color1' ) ) + .attr( 'data-bg-color-2', $this.data( 'color2' ) ) + .attr( 'data-bg-direction', $this.data( 'direction' ) ); + BG.Controls.addStyle( $target, 'background-image', self.createGradientCss( $target ) ); + } else { + BG.Controls.addStyle( $target, 'background-image', imageSrc ); + } + + self.setImageSelection( $this.data( 'type' ), background ); + } ); + }, + + /** + * Activate a filter. + * + * @since 1.2.7 + * + * @param {string} type The selected filter type. + */ + activateFilter: function( type ) { + var backgroundImageProp, + filterFound = false, + $target = self.getTarget(); + + BG.Panel.$element.find( '.current-selection .filter' ).each( function() { + var $this = $( this ), + filterTypes = $this.data( 'type' ); + + if ( type && -1 !== filterTypes.indexOf( type ) ) { + $this.trigger( 'click' ); + filterFound = true; + return false; + } + } ); + + if ( ! filterFound && ! type ) { + backgroundImageProp = $target.css( 'background-image' ); + if ( backgroundImageProp && 'none' !== backgroundImageProp ) { + + // Image filter selection hack, trouble selecting array data type. + BG.Panel.$element.find( '.filter[data-type]:first-of-type' ).trigger( 'click' ); + filterFound = true; + } + } + + if ( false === filterFound ) { + BG.Panel.$element.find( '.filter[data-default="1"]' ).trigger( 'click' ); + } + }, + + /** + * Set Image selection. + * + * @since 1.2.7 + * + * @param {string} type Type of image. + * @param {string} prop Image property. + * @param {boolean} isHoverImage Is Hover Image. + */ + setImageSelection: function( type, prop, isHoverImage ) { + var $currentSelection = BG.Panel.$element.find( '.current-selection' ), + $target = self.getTarget(), + bgImageUrl = $target.attr( 'data-image-url' ), + bgColor = $target.css( 'background-color' ), + overlayColor = $target.attr( 'data-bg-overlaycolor' ), + hoverOverlayColor = $target.attr( 'data-hover-bg-overlaycolor' ), + hoverBgImageUrl = $target.attr( 'data-hover-image-url' ), + hoverColor = $target.attr( 'data-hover-bg-color' ); + + $currentSelection.css( 'background', '' ); + + if ( 'color' === type ) { + $currentSelection.css( 'background-color', prop ); + } else if ( 'hover-image' === type ) { + $currentSelection.css( 'background-color', prop ); + if ( hoverBgImageUrl && hoverOverlayColor ) { + $currentSelection.css( + 'background-image', + `${self.getOverlayImage( hoverOverlayColor )}, url('${hoverBgImageUrl}')` + ); + } else if ( hoverBgImageUrl ) { + $currentSelection.css( 'background-image', `url('${hoverBgImageUrl}')` ); + } else if ( bgImageUrl ) { + $currentSelection.css( 'background-image', `url('${bgImageUrl}')` ); + } + self._setupHoverBoxes(); + } else if ( 'hover-color' === type ) { + if ( hoverColor && ! hoverBgImageUrl ) { + $currentSelection.css( 'background-color', hoverColor ); + } else if ( ! hoverColor && ! hoverBgImageUrl ) { + $currentSelection.css( 'background-color', 'rgba(0,0,0,0)' ); + } + self._setupHoverBoxes(); + } else if ( 'gradients' === type ) { + $currentSelection.css( 'background-image', $target.css( 'background-image' ) ); + } else { + $currentSelection.css( 'background-color', bgColor ); + if ( bgImageUrl && overlayColor ) { + $currentSelection.css( + 'background-image', + `${self.getOverlayImage( overlayColor )}, url('${bgImageUrl}')` + ); + } else if ( bgImageUrl ) { + $currentSelection.css( 'background-image', `url('${bgImageUrl}')` ); + } + } + + $currentSelection.attr( 'data-type', type ); + }, + + /** + * Set Image background. + * + * @since 1.2.7 + * + * @param {string} url URL of the image. + * @param {boolean} isHoverImage Is Hover Image. + */ + setImageBackground: function( url, isHoverImage = false ) { + var $target = self.getTarget(), + hvrBgClass = $target.attr( 'data-hover-bg-class' ); + + if ( isHoverImage && ! hvrBgClass ) { + hvrBgClass = 'hover-bg-' + Math.floor( Math.random() * 999 + 1 ).toString(); + $target.addClass( hvrBgClass ); + $target.attr( 'data-hover-bg-class', hvrBgClass ); + } + if ( isHoverImage ) { + $target.attr( 'data-hover-image-url', url ); + $target.addClass( 'has-hover-bg' ); + self._addHoverEffects(); + } else { + $target.attr( 'data-image-url', url ); + BG.Controls.addStyle( $target, 'background', '' ); + self.updateBackgroundImage(); + BG.Controls.addStyle( $target, 'background-size', 'cover' ); + BG.Controls.addStyle( $target, 'background-position', '50% 50%' ); + } + }, + + /** + * Init all sliders. + * + * @since 1.2.7 + */ + _initSliders: function() { + self._initVerticleSlider(); + }, + + /** + * Init Vertical position slider. + * + * @since 1.2.7 + */ + _initVerticleSlider: function() { + var $target = self.getTarget(), + defaultPosY = $target.css( 'background-position-y' ), + defaultPosX = $target.css( 'background-position-x' ); + + defaultPosY = defaultPosY ? parseInt( defaultPosY ) : 50; + defaultPosX = defaultPosX ? parseInt( defaultPosX ) : 50; + + BG.Panel.$element + .find( '.background-design .vertical-position .slider' ) + .slider( { + min: 0, + max: 100, + value: defaultPosY, + range: 'max', + slide: function( event, ui ) { + if ( $target.css( 'background-image' ) ) { + BG.Controls.addStyle( + $target, + 'background-position', + defaultPosX + '%' + ' ' + ui.value + '%' + ); + } + } + } ) + .siblings( '.value' ) + .html( defaultPosY ); + + BG.Panel.$element + .find( '.background-design .hover-vertical-position .slider' ) + .slider( { + min: 0, + max: 100, + value: $target.attr( 'data-hover-bg-position' ) ? + $target.attr( 'data-hover-bg-position' ) : + defaultPosY, + range: 'max', + slide: function( event, ui ) { + if ( $target.attr( 'data-hover-bg-class' ) ) { + self._addHeadingStyle( + $target.attr( 'data-hover-bg-class' ) + '-position', + `.${$target.attr( 'data-hover-bg-class' )}:hover { + background-position: ${defaultPosX + '%'} ${ui.value}% !important; + }` + ); + $target.attr( 'data-hover-bg-position', ui.value ); + } + } + } ) + .siblings( '.value' ) + .html( defaultPosY ); + }, + + /** + * Open the customization view. + * + * @since 1.2.7 + */ + openCustomization: function() { + var dataType = BG.Panel.$element.find( '.current-selection' ).attr( 'data-type' ); + + BG.Panel.$element.find( '.preset-wrapper' ).hide(); + BG.Panel.$element.find( '.background-design .customize' ).show(); + BG.Panel.$element.find( '.preset-wrapper' ).attr( 'data-type', dataType ); + self._initSliders(); + self.selectDefaults(); + BG.Panel.enterCustomization(); + BG.Panel.customizeOpenEvent(); + + BG.Panel.createScrollbar( '.customize', { + height: self.panel.height + } ); + }, + + /** + * Set all defaults. + * + * @since 1.2.7 + */ + selectDefaults: function() { + self.setScrollEffect(); + self.setSize(); + self.setDefaultDirection(); + self.setDefaultBackgroundColors(); + self.setDefaultOverlayColor(); + }, + + /** + * Set default overlay color. + * + * @since 1.2.7 + */ + setDefaultOverlayColor: function() { + var $target = self.getTarget(), + $overlayColorSection = BG.Panel.$element.find( '.overlay-color' ), + $hoverOverlayColorSeciont = BG.Panel.$element.find( '.hover-overlay-color' ), + hoverOverlayColor = $target.attr( 'data-hover-bg-overlaycolor' ), + overlayColor = $target.attr( 'data-bg-overlaycolor' ); + + if ( overlayColor ) { + $overlayColorSection + .find( 'input' ) + .val( overlayColor ) + .attr( 'value', overlayColor ); + } + if ( hoverOverlayColor ) { + $hoverOverlayColorSeciont + .find( 'input' ) + .val( hoverOverlayColor ) + .attr( 'value', hoverOverlayColor ); + } + }, + + /** + * Set default background size. + * + * @since 1.2.7 + */ + setSize: function() { + var $input = BG.Panel.$element.find( 'input[name="background-size"]' ), + $target = self.getTarget(); + + if ( -1 === $target.css( 'background-size' ).indexOf( 'cover' ) ) { + $input.filter( '[value="tiled"]' ).prop( 'checked', true ); + } + }, + + /** + * Set default scroll direction. + * + * @since 1.2.7 + */ + setScrollEffect: function() { + var $target = self.getTarget(); + + $.each( self.availableEffects, function() { + if ( $target.hasClass( this ) ) { + BG.Panel.$element + .find( 'input[name="scroll-effects"][value="' + this + '"]' ) + .prop( 'checked', true ); + return false; + } + } ); + }, + + /** + * Set graadient direction. + * + * @since 1.2.7 + */ + setDefaultDirection: function() { + var $target = self.getTarget(), + direction = $target.attr( 'data-bg-direction' ); + + if ( self.backgroundIsGradient( $target.css( 'background-image' ) ) && direction ) { + BG.Panel.$element + .find( 'input[name="bg-direction"][value="' + direction + '"]' ) + .prop( 'checked', true ); + } + }, + + /** + * Set default background colors. + * + * @since 1.2.7 + */ + setDefaultBackgroundColors: function() { + var bgColor, + hoverColor, + $bgControlColor, + $hoverColorControl, + $target = self.getTarget(); + + if ( self.backgroundIsGradient( $target.css( 'background-image' ) ) ) { + BG.Panel.$element + .find( 'input[name="gradient-color-1"]' ) + .val( $target.attr( 'data-bg-color-1' ) ) + .attr( 'value', $target.attr( 'data-bg-color-1' ) ); + BG.Panel.$element + .find( 'input[name="gradient-color-2"]' ) + .val( $target.attr( 'data-bg-color-2' ) ) + .attr( 'value', $target.attr( 'data-bg-color-2' ) ); + } else { + bgColor = BG.CONTROLS.Color.findAncestorColor( $target, 'background-color' ); + $bgControlColor = BG.Panel.$element.find( 'input[name="section-background-color"]' ); + $bgControlColor.prev( 'label' ).css( 'background-color', bgColor ); + $bgControlColor.val( bgColor ).attr( 'value', bgColor ); + } + + if ( $target.attr( 'data-hover-bg-color' ) ) { + hoverColor = $target.attr( 'data-hover-bg-color' ); + $hoverColorControl = BG.Panel.$element.find( 'input[name="section-hover-background-color"]' ); + $hoverColorControl.prev( 'label' ).css( 'background-color', hoverColor ); + $hoverColorControl.val( hoverColor ).attr( 'value', hoverColor ); + self._setupHoverBoxes(); + } + }, + + /** + * Get a random gradient direction. + * + * @since 1.2.7 + * @return string. + */ + randomGradientDirection: function() { + var directions = [ 'to left', 'to bottom' ]; + + return directions[Math.floor( Math.random() * directions.length )]; + }, + + /** + * Create JSON of gradients. Not used at runtime. + * + * @since 1.2.7 + */ + _createGradients: function() { + var gradientData = []; + + $.each( BoldgridEditor.sample_backgrounds.default_gradients, function() { + var color1 = this.colors[0], + color2 = this.colors[1], + direction = self.randomGradientDirection(); + + gradientData.push( { + color1: color1, + color2: color2, + direction: direction, + css: 'linear-gradient(' + direction + ',' + color1 + ',' + color2 + ')' + } ); + } ); + }, + + /** + * Create gradients based on the users palettes. + * + * @since 1.2.7 + */ + setPaletteGradients: function() { + var combos = []; + if ( BoldgridEditor.colors.defaults && BoldgridEditor.colors.defaults.length ) { + $.each( [ 0, 1 ], function() { + var color1, color2, pos1, pos2, direction; + pos1 = Math.floor( Math.random() * BoldgridEditor.colors.defaults.length ) + 1; + pos2 = Math.floor( Math.random() * BoldgridEditor.colors.defaults.length ) + 1; + color1 = 'var( --color-' + pos1 + ' )'; + color2 = 'var( --color-' + pos2 + ' )'; + if ( ! BoldgridEditor.is_crio ) { + color1 = BoldgridEditor.colors.defaults[pos1 - 1]; + color2 = BoldgridEditor.colors.defaults[pos2 - 1]; + } + if ( color1 !== color2 ) { + direction = self.randomGradientDirection(); + combos.push( { + color1: color1, + color2: color2, + direction: direction, + css: 'linear-gradient(' + direction + ',' + color1 + ',' + color2 + ')' + } ); + } + } ); + } + + $.each( combos, function() { + BoldgridEditor.sample_backgrounds.gradients.unshift( this ); + } ); + }, + + /** + * Is the given background a gradient. + * + * @since 1.2.7 + * + * @param {string} backgroundUrl Background Image style string. + * + * @return {boolean} True if gradient. + */ + backgroundIsGradient: function( backgroundUrl ) { + return -1 !== backgroundUrl.indexOf( 'linear-gradient' ) && -1 === backgroundUrl.indexOf( 'url' ); + }, + + /** + * Preselect the background being used when opening the panel. + * + * @since 1.2.7 + */ + preselectBackground: function( keepFilter ) { + var type = 'color', + $target = self.getTarget(), + backgroundColor = $target.css( 'background-color' ), + backgroundUrl = $target.css( 'background-image' ), + $currentSelection = BG.Panel.$element.find( '.current-selection' ), + hasGradient = self.backgroundIsGradient( backgroundUrl ), + matchFound = false; + + //@TODO: update the preview screen when pressing back from the customize section. + + // Set the background color, and background image of the current section to the preview. + self.setImageSelection( 'image' ); + $currentSelection.css( 'background-color', backgroundColor ); + + BG.Panel.$element.find( '.selection' ).each( function() { + var $this = $( this ), + selectionType = $this.data( 'type' ), + dataClass = $this.data( 'class' ); + + switch ( selectionType ) { + case 'color': + if ( + dataClass && + $target.hasClass( dataClass ) && + 'none' === $target.css( 'background-image' ) + ) { + $this.addClass( 'selected' ); + type = selectionType; + matchFound = true; + self.activateFilter( type ); + return false; + } + break; + case 'image': + if ( $this.attr( 'data-image-url' ) === $target.attr( 'data-image-url' ) ) { + + //Found a match. + $this.addClass( 'selected' ); + type = selectionType; + matchFound = true; + self.activateFilter( type ); + return false; + } + break; + case 'gradients': + case 'pattern': + if ( $this.css( 'background-image' ) === backgroundUrl ) { + + //Found a match. + $this.addClass( 'selected' ); + type = selectionType; + matchFound = true; + self.activateFilter( type ); + return false; + } + break; + } + } ); + + if ( ! matchFound ) { + if ( hasGradient ) { + type = 'gradients'; + } else if ( 'none' !== backgroundUrl ) { + type = 'image'; + } + + if ( ! keepFilter ) { + self.activateFilter( type ); + } + } + + $currentSelection.attr( 'data-type', type ); + }, + + /** + * Find out what type of element we're controlling the background of. + * + * @since 1.8.0 + */ + setElementType: function() { + self.elementType = this.checkElementType( self.$target ); + BG.Panel.$element.find( '.customize-navigation' ).attr( 'data-element-type', self.elementType ); + self.panel.targetType = self.elementType; + }, + + /** + * Set element visibility. + * + * @since 1.17.0 + */ + setElementVisibility() { + var $target = self.getTarget(), + visibility = $target.hasClass( 'hover-mobile-bg' ) ? 'hover' : 'default', + $radios = BG.Panel.$element.find( '.mobile-only-visibility input' ); + + $radios.each( function() { + if ( $( this ).val() === visibility ) { + $( this ).attr( 'checked', true ); + } else { + $( this ).attr( 'checked', false ); + } + } ); + }, + + /** + * Determine the element type supported by this control. + * + * @since 1.8.0 + * + * @param {jQuery} $element Jquery Element. + * + * @return {string} Element Type. + */ + checkElementType: function( $element ) { + let type = ''; + if ( $element.hasClass( 'boldgrid-section' ) ) { + type = 'section'; + } else if ( $element.hasClass( 'row' ) ) { + type = 'row'; + } else if ( $element.hasClass( 'bg-box' ) ) { + type = 'bg-box'; + } else { + type = 'column'; + } + + return type; + }, + + /** + * Open Panel. + * + * @since 1.2.7 + * + * @param {JQuery Object} $target Current Target. + */ + openPanel: function( $target ) { + var panel = BG.Panel, + template = wp.template( 'boldgrid-editor-background-legacy' ); + + self.$target = $target; + + BoldgridEditor.sample_backgrounds.color = BG.CONTROLS.Color.getPaletteBackgroundColors(); + + // Remove all content from the panel. + panel.clear(); + + self.setPaletteGradients(); + panel.$element.find( '.panel-body' ).html( + template( { + images: BoldgridEditor.sample_backgrounds, + imageData: BoldgridEditor.builder_config.background_images + } ) + ); + + self.preselectBackground(); + self.setDefaultBackgroundColors(); + self.setElementType(); + self.setElementVisibility(); + + // Open Panel. + panel.open( self ); + } + }; + + BOLDGRID.EDITOR.CONTROLS.Background.init(); + self = BOLDGRID.EDITOR.CONTROLS.Background; + + // Prevent two controls from being loaded with the same name. + if ( ! self.loadLegacyControl() ) { + delete BOLDGRID.EDITOR.CONTROLS.Background; + } +} )( jQuery ); diff --git a/assets/js/builder/controls/element/background.js b/assets/js/builder/controls/element/background.js index b7ade576..f70f03c5 100644 --- a/assets/js/builder/controls/element/background.js +++ b/assets/js/builder/controls/element/background.js @@ -1,7 +1,22 @@ +/** + * File: assets/js/builder/controls/element/background.js + * + * Background Control + * + * This is the new version of the background control panel + * which uses react to generate the controls. + * + * @since 1.25.0 + */ window.BOLDGRID = window.BOLDGRID || {}; BOLDGRID.EDITOR = BOLDGRID.EDITOR || {}; BOLDGRID.EDITOR.CONTROLS = BOLDGRID.EDITOR.CONTROLS || {}; +// Import Semver. +import { gte as semverGte } from 'semver'; +import { createRoot } from '@wordpress/element'; +import { BoldgridPanel } from 'boldgrid-panel'; + ( function( $ ) { 'use strict'; @@ -9,12 +24,28 @@ BOLDGRID.EDITOR.CONTROLS = BOLDGRID.EDITOR.CONTROLS || {}; BG = BOLDGRID.EDITOR; BOLDGRID.EDITOR.CONTROLS.Background = { + /** + * Name. + * + * @since 1.25.0 + * @type {string} + */ name: 'background', + /** + * Tooltip. + * + * @since 1.25.0 + * @type {string} + */ tooltip: 'Background', - uploadFrame: null, - + /** + * Priority. + * + * @since 1.25.0 + * @type {number} + */ priority: 10, /** @@ -30,18 +61,36 @@ BOLDGRID.EDITOR.CONTROLS = BOLDGRID.EDITOR.CONTROLS || {}; */ layerEvent: { latestTime: 0, targets: [] }, + /** + * Element Type. + * + * @since 1.25.0 + * @type {string} + */ elementType: '', - isHoverImage: false, - + /** + * Icon Classes + * + * @since 1.25.0 + * @type {string} + */ iconClasses: 'genericon genericon-picture', + /** + * Selectors. + * + * @since 1.25.0 + * @type {Array} + */ selectors: [ '.boldgrid-section', '.row', '[class*="col-md-"]', '.bg-box' ], - availableEffects: [ 'background-parallax', 'background-fixed' ], - - availableHoverEffects: [ 'background-hover-fixed' ], - + /** + * Menu Dropdown Config. + * + * @since 1.25.0 + * @type {Object>>} + */ menuDropDown: { title: 'Background', options: [ @@ -64,124 +113,66 @@ BOLDGRID.EDITOR.CONTROLS = BOLDGRID.EDITOR.CONTROLS || {}; ] }, - init: function() { - BOLDGRID.EDITOR.Controls.registerControl( this ); - }, - + /** + * Panel Config. + * + * @since 1.25.0 + * + * @type {Object} + */ panel: { title: 'Background', height: '625px', width: '450px', - scrollTarget: '.presets', - customizeSupport: [ - 'margin', - 'padding', - 'border', - 'width', - 'box-shadow', - 'animation', - 'border-radius', - 'blockAlignment', - 'device-visibility', - 'customClasses' - ], - sizeOffset: -230 + noSlimScroll: true, + scrollTarget: '.panel-body', + sizeOffset: 0 }, /** - * Setup Hover Boxes. - * - * @since 1.17.0 + * Control Init + * + * @since 1.25.0 */ - _setupHoverBoxes() { - var css = '', - $head = $( tinyMCE.activeEditor.iframeElement ) - .contents() - .find( 'head' ), - $body = $( tinyMCE.activeEditor.iframeElement ) - .contents() - .find( 'body' ), - $hoverBoxes = $body.find( '.has-hover-bg' ); - - $hoverBoxes.each( ( index, hoverBox ) => { - var $hoverBox = $( hoverBox ), - hoverBoxClass = $hoverBox.attr( 'data-hover-bg-class' ), - hoverBgUrl = $hoverBox.attr( 'data-hover-image-url' ), - hoverOverlay = $hoverBox.attr( 'data-hover-bg-overlaycolor' ), - hoverBgSize = $hoverBox.attr( 'data-hover-bg-size' ), - hoverBgSize = hoverBgSize ? hoverBgSize : 'cover', - hoverBgPos = $hoverBox.attr( 'data-hover-bg-position' ), - hoverBgPos = hoverBgPos ? hoverBgPos : '50', - hoverBgColor = $hoverBox.attr( 'data-hover-bg-color' ); - - if ( 'cover' === hoverBgSize ) { - hoverBgSize = - 'background-size: cover !important; background-repeat: "no-repeat !important";'; - } else { - hoverBgSize = - 'background-size: auto auto !important; background-repeat: repeat !important;'; - } - - if ( hoverOverlay && hoverBgUrl ) { - css = `.${hoverBoxClass}:hover {`; - css += `background-image: linear-gradient(to left, ${hoverOverlay}, ${ - hoverOverlay - } ), url('${hoverBgUrl}') !important; }`; - $head.append( `` ); - - css = `.${hoverBoxClass}:hover { background-position: 50% ${hoverBgPos}% !important; }`; - $head.append( `` ); - - css = `.${hoverBoxClass}:hover { ${hoverBgSize} }`; - $head.append( `` ); - } else if ( hoverBgUrl ) { - css = `.${hoverBoxClass}:hover {`; - css += `background-image: url('${hoverBgUrl}') !important; }`; - $head.append( `` ); - - css = `.${hoverBoxClass}:hover { background-position: 50% ${hoverBgPos}% !important; }`; - $head.append( `` ); + init: function() { + if ( this.loadLegacyControl() ) { + BOLDGRID.EDITOR.Controls.registerControl( this ); + } + }, - css = `.${hoverBoxClass}:hover { ${hoverBgSize} }`; - $head.append( `` ); - } + /** + * Load Legacy Control + * + * This determines whether or not to load this control based on + * a set of conditions. This is run in legacy controls, and in new + * controls that have a legacy version. + * + * @since 1.25.0 + * + * @return {boolean} Whether or not to load this control. + */ + loadLegacyControl() { + var minCrioVersion = '2.20.0', // Crio 2.20.0 is the first version to support the new BG control. + isCrio = BoldgridEditor.is_crio; - if ( hoverBgColor && hoverBgUrl ) { - css = `.${hoverBoxClass}:hover { background-color: ${hoverBgColor} !important; }`; - $head.append( `` ); - } else if ( hoverBgColor && ! hoverBgUrl ) { - css = `.${hoverBoxClass}:hover { background-color: ${hoverBgColor} !important; }`; - $head.append( `` ); + // If the theme is not Crio, don't load this control. + if ( ! isCrio ) { + return false; + } - css = `.${hoverBoxClass}:hover {background-image: unset !important; }`; - $head.append( `` ); - } + // If the theme is Crio, and the version is greater than or equal to the minimum version, load this control. + if ( semverGte( BoldgridEditor.theme_version, minCrioVersion ) ) { + return true; + } - css = '@media screen and (max-width: 991px) {'; - if ( hoverBoxClass && hoverBgUrl && hoverOverlay ) { - let hoverCss = self.getOverlayImage( hoverOverlay ) + ', url("' + hoverBgUrl + '")'; - css += `.${hoverBoxClass}.hover-mobile-bg {background-image: ${hoverCss} !important; }`; - css += `.${hoverBoxClass}.hover-mobile-bg:hover {background-image: ${ - hoverCss - } !important; }`; - } else if ( hoverBoxClass && ! hoverBgUrl && hoverBgColor ) { - css += `.${hoverBoxClass}.hover-mobile-bg { - background-color: ${hoverBgColor} !important; - background-image: none !important; - }`; - } else { - css += `.${hoverBoxClass}.hover-mobile-bg { background-image: url('${ - hoverBgUrl - }') !important; } }`; - } - $head.append( `` ); - } ); + return false; }, /** * Get the current target. * - * @since 1.8.0 + * @since 1.25.0 + * * @return {jQuery} Element. */ getTarget: function() { @@ -191,7 +182,7 @@ BOLDGRID.EDITOR.CONTROLS = BOLDGRID.EDITOR.CONTROLS || {}; /** * When the user clicks on a menu item, update the available options. * - * @since 1.8.0 + * @since 1.25.0 */ onMenuClick: function() { self.updateMenuOptions(); @@ -200,7 +191,7 @@ BOLDGRID.EDITOR.CONTROLS = BOLDGRID.EDITOR.CONTROLS || {}; /** * Update the avilable options in the background drop down. * - * @since 1.8.0 + * @since 1.25.0 */ updateMenuOptions: function() { let availableOptions = []; @@ -216,70 +207,16 @@ BOLDGRID.EDITOR.CONTROLS = BOLDGRID.EDITOR.CONTROLS || {}; * When a menu item is reopened because a user clicked on another similar element * Update the available options. * - * @since 1.8.0 + * @since 1.25.0 */ _setupMenuReactivate: function() { self.$menuItem.on( 'reactivate', self.updateMenuOptions ); }, /** - * When the user clicks Add Image open the media library. - * - * @since 1.2.7 - */ - _setupAddImage: function( isHoverImage = false ) { - var addMediaClass = isHoverImage ? '.add-hover-image-controls' : '.add-image-controls'; - BG.Panel.$element.on( 'click', '.background-design ' + addMediaClass, function() { - self.isHoverImage = $( this ).hasClass( 'add-hover-image-controls' ); - - // If the media frame already exists, reopen it. - if ( self.uploadFrame ) { - self.uploadFrame.open(); - return; - } - - // Create a new media frame. - self.uploadFrame = wp.media( { - title: 'Select Background Image', - library: { type: 'image' }, - button: { - text: 'Use this media' - }, - - // Set to true to allow multiple files to be selected. - multiple: false - } ); - - // When an image is selected in the media frame. - self.uploadFrame.on( 'select', function() { - - // Get media attachment details from the frame state. - var attachment = self.uploadFrame - .state() - .get( 'selection' ) - .first() - .toJSON(); - - var hoverImage = self.isHoverImage ? true : false; - - // Set As current selection and apply to background. - self.setImageBackground( attachment.url, hoverImage ); - if ( hoverImage ) { - self.setImageSelection( 'hover-image', attachment.url, hoverImage ); - } else { - self.setImageSelection( 'image', attachment.url, hoverImage ); - } - } ); - - // Finally, open the modal on click. - self.uploadFrame.open(); - } ); - }, - - /** - * Open the editor panel for a given selector and stor element as target. + * Open the editor panel for a given selector and store element as target. * - * @since 1.8.0 + * @since 1.25.0 * * @param {string} selector Selector. */ @@ -295,9 +232,9 @@ BOLDGRID.EDITOR.CONTROLS = BOLDGRID.EDITOR.CONTROLS || {}; /** * When the user clicks on an element within the mce editor record the element clicked. * - * @since 1.8.0 + * @since 1.25.0 * - * @param {object} event DOM Event + * @param {MouseEvent} event DOM Event */ elementClick( event ) { if ( self.layerEvent.latestTime !== event.timeStamp ) { @@ -311,7 +248,7 @@ BOLDGRID.EDITOR.CONTROLS = BOLDGRID.EDITOR.CONTROLS || {}; /** * Bind each of the sub menu items. * - * @since 1.8.0 + * @since 1.25.0 */ _setupMenuClick() { BG.Menu.$element @@ -323,1493 +260,230 @@ BOLDGRID.EDITOR.CONTROLS = BOLDGRID.EDITOR.CONTROLS || {}; }, /** - * Setup Init. + * Setup Legacy Hover Boxes. + * + * In order for hover boxes created in the old + * method to be shown in the editor, we still + * have to set them up here. * - * @since 1.2.7 + * @since 1.25.0 */ - setup: function() { - self.$menuItem = BG.Menu.$element.find( '[data-action="menu-background"]' ); - - self._setupHoverBoxes(); - self._setupMenuReactivate(); - self._setupMenuClick(); - self._setupBackgroundClick(); - self._setupFilterClick(); - self._setupCustomizeLeave(); - self._setupBackgroundSize(); - self._setupBackgroundColor(); - self._setupGradientColor(); - self._setupOverlayColor(); - self._setupOverlayReset(); - self._setupScrollEffects(); - self._setupGradientDirection(); - self._setupCustomization(); - self._setupAddImage(); - self._setupHoverImage(); - self._setupMobileVisibility(); - }, + _setupLegacyHoverBoxes() { + var css = '', + $head = $( tinyMCE.activeEditor.iframeElement ) + .contents() + .find( 'head' ), + $body = $( tinyMCE.activeEditor.iframeElement ) + .contents() + .find( 'body' ), + $hoverBoxes = $body.find( '.has-hover-bg' ); - /** - * Setup Hover Image. - * - * @since 1.17.0 - */ - _setupHoverImage: function() { - self._setupAddImage( true ); - }, + $hoverBoxes.each( ( index, hoverBox ) => { + var $hoverBox = $( hoverBox ), + hoverBoxClass = $hoverBox.attr( 'data-hover-bg-class' ), + hoverBgUrl = $hoverBox.attr( 'data-hover-image-url' ), + hoverOverlay = $hoverBox.attr( 'data-hover-bg-overlaycolor' ), + hoverBgSize = $hoverBox.attr( 'data-hover-bg-size' ), + hoverBgSize = hoverBgSize ? hoverBgSize : 'cover', + hoverBgPos = $hoverBox.attr( 'data-hover-bg-position' ), + hoverBgPos = hoverBgPos ? hoverBgPos : '50', + hoverBgColor = $hoverBox.attr( 'data-hover-bg-color' ); - /** - * Adds hover styles to header. - * - * @since 1.17.0 - * - * @param {string} styleId Style ID. - * @param {string} css Css to add - */ - _addHeadingStyle: function( styleId, css ) { - var $target = self.getTarget(), - $body = $target.parents( 'body' ), - $head = $body.parent().find( 'head' ); + if ( 'cover' === hoverBgSize ) { + hoverBgSize = + 'background-size: cover !important; background-repeat: "unset !important";'; + } else { + hoverBgSize = + 'background-size: auto auto !important; background-repeat: repeat !important;'; + } - if ( $head.find( '#' + styleId ).length ) { - $head.find( '#' + styleId ).remove(); - } + if ( hoverOverlay && hoverBgUrl ) { + css = `.${hoverBoxClass}:hover {`; + css += `background-image: linear-gradient(to left, ${hoverOverlay}, ${ + hoverOverlay + } ), url('${hoverBgUrl}') !important; }`; + $head.append( `` ); - $head.append( '' ); - }, + css = `.${hoverBoxClass}:hover { background-position: 50% ${hoverBgPos}% !important; }`; + $head.append( `` ); - /** - * Adds Hover Effects - * - * @since 1.17.0 - */ - _addHoverEffects: function() { - var $target = self.getTarget(), - $body = $target.parents( 'body' ), - $hoverBgs = $body.find( '.has-hover-bg' ), - css = ''; + css = `.${hoverBoxClass}:hover { ${hoverBgSize} }`; + $head.append( `` ); + } else if ( hoverBgUrl ) { + css = `.${hoverBoxClass}:hover {`; + css += `background-image: url('${hoverBgUrl}') !important; }`; + $head.append( `` ); - $hoverBgs.each( function() { - var hoverBgClassName = $( this ).attr( 'data-hover-bg-class' ), - hoverBgUrl = $( this ).attr( 'data-hover-image-url' ), - hoverOverlay = $( this ).attr( 'data-hover-bg-overlaycolor' ), - hoverBgColor = $( this ).attr( 'data-hover-bg-color' ); + css = `.${hoverBoxClass}:hover { background-position: 50% ${hoverBgPos}% !important; }`; + $head.append( `` ); - if ( hoverBgClassName && hoverBgUrl && hoverOverlay ) { - let hoverCss = self.getOverlayImage( hoverOverlay ) + ', url("' + hoverBgUrl + '")'; - css = `.${hoverBgClassName}:hover {background-image: ${hoverCss} !important; }`; - self._addHeadingStyle( hoverBgClassName + '-image', css ); - } else { - css = `.${hoverBgClassName}:hover {background-image: url('${hoverBgUrl}') !important; }`; - self._addHeadingStyle( hoverBgClassName + '-image', css ); + css = `.${hoverBoxClass}:hover { ${hoverBgSize} }`; + $head.append( `` ); } - css = `.${ - hoverBgClassName - }:hover {background-size: cover !important; background-repeat: no-repeat !important; background-position: 50%, 50% !important;}`; - self._addHeadingStyle( hoverBgClassName + '-bg-size', css ); + if ( hoverBgColor && hoverBgUrl ) { + css = `.${hoverBoxClass}:hover { background-color: ${hoverBgColor} !important; }`; + $head.append( `` ); + } else if ( hoverBgColor && ! hoverBgUrl ) { + css = `.${hoverBoxClass}:hover { background-color: ${hoverBgColor} !important; }`; + $head.append( `` ); + + css = `.${hoverBoxClass}:hover {background-image: unset !important; }`; + $head.append( `` ); + } css = '@media screen and (max-width: 991px) {'; - if ( hoverBgClassName && hoverBgUrl && hoverOverlay ) { - let hoverCss = self.getOverlayImage( hoverOverlay ) + ', url("' + hoverBgUrl + '")'; - css += `.${hoverBgClassName}.hover-mobile-bg {background-image: ${ - hoverCss - } !important; }`; - css += `.${hoverBgClassName}.hover-mobile-bg:hover {background-image: ${ + if ( hoverBoxClass && hoverBgUrl && hoverOverlay ) { + let overlayImage = 'linear-gradient(to left, ' + hoverOverlay + ', ' + hoverOverlay + ')'; + let hoverCss = overlayImage + ', url("' + hoverBgUrl + '")'; + css += `.${hoverBoxClass}.hover-mobile-bg {background-image: ${hoverCss} !important; }`; + css += `.${hoverBoxClass}.hover-mobile-bg:hover {background-image: ${ hoverCss } !important; }`; - } else if ( hoverBgClassName && ! hoverBgUrl && hoverBgColor ) { - css += `.${hoverBgClassName}.hover-mobile-bg { + } else if ( hoverBoxClass && ! hoverBgUrl && hoverBgColor ) { + css += `.${hoverBoxClass}.hover-mobile-bg { background-color: ${hoverBgColor} !important; background-image: none !important; }`; } else { - css += `.${hoverBgClassName}.hover-mobile-bg { background-image: url('${ + css += `.${hoverBoxClass}.hover-mobile-bg { background-image: url('${ hoverBgUrl }') !important; } }`; } - self._addHeadingStyle( hoverBgClassName + '-mobile-image', css ); + $head.append( `` ); } ); }, /** - * Bind Event: Change background section color. + * Setup Init. * - * @since 1.2.7 + * @since 1.25.0 */ - _setupBackgroundColor: function() { - var panel = BG.Panel; - - panel.$element.on( - 'change', - '.background-design [name="section-background-color"]', - function() { - var $this = $( this ), - $target = self.getTarget(), - value = $this.val(), - type = $this.attr( 'data-type' ), - $currentSelection = BG.Panel.$element.find( '.current-selection' ), - selectionType = $currentSelection.attr( 'data-type' ), - classFromColor = self.classFromColor( value ), - alphaFromColor = self.alphaFromColor( value ); - - self.removeColorClasses( $target ); - BG.Controls.addStyle( $target, 'background-color', '' ); - - // If currently selected is a gradient. - if ( 'pattern' !== selectionType ) { - BG.Controls.addStyle( $target, 'background-image', '' ); - $target.removeAttr( 'data-bg-color-1' ); - $target.removeAttr( 'data-bg-color-2' ); - $target.removeAttr( 'data-bg-direction' ); - } - if ( 'pattern' !== selectionType ) { - BG.Panel.$element.find( '.presets .selected' ).removeClass( 'selected' ); - } - - if ( 'class' === type ) { - $target - .addClass( 'bg-background-color' ) - .addClass( BG.CONTROLS.Color.getColorClass( 'background-color', value ) ) - .addClass( BG.CONTROLS.Color.getColorClass( 'text-contrast', value ) ); - } else if ( classFromColor ) { - $target - .addClass( 'bg-background-color' ) - .addClass( BG.CONTROLS.Color.getColorClass( 'background-color', classFromColor ) ) - .addClass( BG.CONTROLS.Color.getColorClass( 'text-contrast', classFromColor ) ) - .attr( 'data-alpha', alphaFromColor ); - - self.paletteAddAlpha( - $target, - value, - BG.CONTROLS.Color.getColorClass( 'background-color', classFromColor ) - ); - } else { - BG.Controls.addStyle( $target, 'background-color', value ); - } - self.setImageSelection( selectionType, $target.css( 'background' ) ); - BOLDGRID.EDITOR.CONTROLS.SectionDividers.detectFillColors(); - } - ); - - panel.$element.on( - 'change', - '.background-design [name="section-hover-background-color"]', - function() { - var $this = $( this ), - $target = self.getTarget(), - value = $this.val(), - type = $this.attr( 'data-type' ), - hoverClass = $target.attr( 'data-hover-bg-class' ), - isGridBlock = $target.hasClass( 'dynamic-gridblock' ), - isCrio = BoldgridEditor.is_crio, - css = ''; - - if ( ! $target.hasClass( 'has-hover-bg' ) ) { - $target.addClass( 'has-hover-bg' ); - } - - if ( ! hoverClass ) { - hoverClass = 'hover-bg-' + Math.floor( Math.random() * 999 + 1 ).toString(); - $target.attr( 'data-hover-bg-class', hoverClass ); - $target.addClass( hoverClass ); - } - - if ( '' === value ) { - $target.attr( 'data-hover-bg-color', 'unset' ); - css = `.${hoverClass}:hover {background-color: ${$target.attr( - 'data-hover-bg-color' - )} !important;}`; - self._addHeadingStyle( hoverClass + '-bg-color', css ); - $target - .parents( 'html' ) - .find( 'head' ) - .find( hoverClass + '-bg-color' ) - .remove(); - - if ( ! $target.attr( 'data-hover-image-url' ) ) { - $target.removeAttr( 'data-hover-bg-class' ); - $target.removeClass( 'has-hover-bg' ); - $target.removeClass( hoverClass ); - self.setImageSelection( 'hover-color' ); - return; - } else { - self.setImageSelection( 'hover-image' ); - return; - } - } - - if ( 'class' === type && ( isGridBlock || ! isCrio ) ) { - value = 'neutral' === value ? value : parseInt( value ) - 1; - let color = - 'neutral' === value ? - BoldgridEditor.colors.neutral : - BoldgridEditor.colors.defaults[value]; - $target.attr( 'data-hover-bg-color', color ); - } else if ( 'class' === type ) { - $target.attr( 'data-hover-bg-color', 'var(--color-' + value + ')' ); - } else { - $target.attr( 'data-hover-bg-color', value ); - } - - css = `.${hoverClass}:hover {background-color: ${$target.attr( - 'data-hover-bg-color' - )} !important;}`; - self._addHeadingStyle( hoverClass + '-bg-color', css ); - - if ( ! $target.attr( 'data-hover-image-url' ) ) { - css = `.${hoverClass}:hover {background-image: none !important;}`; - self._addHeadingStyle( hoverClass + '-image', css ); - } + setup: function() { + self.$menuItem = BG.Menu.$element.find( '[data-action="menu-background"]' ); - self.setImageSelection( 'hover-color' ); - } - ); + self._setupLegacyHoverBoxes(); + self._setupMenuReactivate(); + self._setupMenuClick(); }, /** - * Add alpha component to background color palettes + * Find out what type of element we're controlling the background of. * - * @param {jQuery Object} $target The target jQuery object - * @param {string} value Background color value - * @param {string} bgColorClass Background Color class + * @since 1.25.0 */ - paletteAddAlpha( $target, value, bgColorClass ) { - var uuid = 'bg-alpha-' + Math.floor( Math.random() * 999 + 1 ).toString(), - $head = $( tinyMCE.activeEditor.iframeElement ) - .contents() - .find( 'head' ), - css; - - if ( $target.attr( 'data-bg-uuid' ) ) { - uuid = $target.attr( 'data-bg-uuid' ); - } else { - $target.attr( 'data-bg-uuid', uuid ); - $target.addClass( uuid ); - } - - $head.find( '#' + uuid + '-inline-style' ).remove(); - - css = `.${bgColorClass}.${uuid} {background-color: ${value} !important;}`; - - $head.append( '' ); + setElementType: function() { + self.elementType = this.checkElementType( self.$target ); + BG.Panel.$element.find( '.customize-navigation' ).attr( 'data-element-type', self.elementType ); + self.panel.targetType = self.elementType; }, /** - * Obtains the alpha ( opacity ) value of an RGBA string. + * Determine the element type supported by this control. + * + * @since 1.8.0 * - * @param {string} color RGBA Color String. - * @returns {string} Alpha value of a color + * @param {jQuery} $element Jquery Element. + * @return {string} Element. */ - alphaFromColor: function( color ) { - var alpha = 1; - - if ( color.includes( 'rgba' ) ) { - alpha = color.replace( /rgba\(\d{1,3}\,\d{1,3}\,\d{1,3}\,(.*\))/, '$1' ); - alpha = alpha.replace( ')', '' ); + checkElementType: function( $element ) { + let type = ''; + if ( $element.hasClass( 'boldgrid-section' ) ) { + type = 'section'; + } else if ( $element.hasClass( 'row' ) ) { + type = 'row'; + } else if ( $element.hasClass( 'bg-box' ) ) { + type = 'bg-box'; + } else { + type = 'column'; } - return alpha; + return type; }, /** - * Determine the color class, if any, that matches an RGB(A) String. + * Open Panel. * - * @param {string} color RGB(A) color string - * @returns {string} The color class associated with this color string. + * @since 1.2.7 + * + * @param $target Current Target. */ - classFromColor: function( color ) { - var colors = BoldgridEditor.colors.defaults, - neutralColor = BoldgridEditor.colors.neutral, - colorClass = false; + openPanel: function( $target ) { + var panel = BG.Panel, + selectedComponent = 'BoldgridBackgroundColor'; - if ( color.includes( 'rgba' ) ) { - color = color.replace( /(rgba\(\d{1,3}\,\d{1,3}\,\d{1,3})(.*\))/, '$1)' ); - color = color.replace( 'rgba', 'rgb' ); - } else if ( ! color.includes( 'rgb' ) ) { - return colorClass; - } + self.$target = $target; - color = color.replace( /\s/g, '' ); + // Remove all content from the panel. + panel.clear(); - for ( let key in colors ) { - if ( colors[key].replace( /\s/g, '' ) === color ) { - colorClass = parseInt( key ) + 1; - break; - } - } + panel.$element.find( '.panel-body' ).html(); - if ( color === neutralColor ) { - colorClass = 'neutral'; - } + self.setElementType(); - return colorClass; - }, - - /** - * Add color palette for overlays to the target. - * - * @param {object} $target jQuery object of the target element. - * @param {string} value The value of the color. - * @param {string} bgColorClass The color class string. - */ - paletteAddOverlayAlpha( $target, value, bgColorClass ) { - var image = $target.attr( 'data-image-url' ), - color = value; - - BG.Controls.addStyle( - $target, - 'background-image', - self.getOverlayImage( color ) + ', url("' + image + '")' - ); - }, - - /** - * Bind Event: Set the default color for overlay. - * - * @since 1.2.7 - */ - _setupOverlayReset: function() { - var panel = BG.Panel; - - panel.$element.on( 'click', '.background-design .overlay-color .default-color', function( e ) { - var $this = $( this ), - $target = self.getTarget(); - - e.preventDefault(); - - $this - .closest( '.color-controls' ) - .find( 'label' ) - .css( 'background-color', 'rgba(255,255,255,.5)' ); - - $target.removeAttr( 'data-bg-overlaycolor' ); - $target.removeAttr( 'data-bg-overlaycolor-alpha' ); - $target.removeAttr( 'data-bg-overlaycolor-class' ); - - self.updateBackgroundImage(); - } ); - }, - - /** - * Bind Event: Change overlay color. - * - * @since 1.2.7 - */ - _setupOverlayColor: function() { - var panel = BG.Panel; - - panel.$element.on( 'change', '.background-design [name="overlay-color"]', function() { - var $this = $( this ), - type = $this.attr( 'data-type' ), - value = $this.val(), - $target = self.getTarget(), - classFromColor = self.classFromColor( value ), - alphaFromColor = self.alphaFromColor( value ); - - if ( 'class' === type ) { - value = BoldgridEditor.colors.defaults[value - 1]; - $target.attr( 'data-bg-overlaycolor', value ); - } else if ( classFromColor ) { - $target.attr( 'data-bg-overlaycolor', value ), - $target.attr( 'data-bg-overlaycolor-alpha', alphaFromColor ); - $target.attr( 'data-bg-overlaycolor-class', classFromColor ); - self.paletteAddOverlayAlpha( - $target, - value, - BG.CONTROLS.Color.getColorClass( 'background-color', classFromColor ) - ); - } else { - $target.attr( 'data-bg-overlaycolor', value ); - } - - self.updateBackgroundImage(); - } ); - - panel.$element.on( 'change', '.background-design [name="hover-overlay-color"]', function() { - var $this = $( this ), - type = $this.attr( 'data-type' ), - value = $this.val(), - $target = self.getTarget(); - - if ( 'class' === type ) { - value = 'var(--color-' + value + ')'; - } - - $target.attr( 'data-hover-bg-overlaycolor', value ); - - self.updateBackgroundImage(); - } ); - }, - - /** - * Update background image on page. - * - * @since 1.2.7 - */ - updateBackgroundImage: function() { - var $target = self.getTarget(), - overlay = $target.attr( 'data-bg-overlaycolor' ), - hoverOverlay = $target.attr( 'data-hover-bg-overlaycolor' ), - image = $target.attr( 'data-image-url' ); - - if ( overlay && image ) { - BG.Controls.addStyle( - $target, - 'background-image', - self.getOverlayImage( overlay ) + ', url("' + image + '")' - ); - } else if ( image ) { - BG.Controls.addStyle( $target, 'background-image', 'url("' + image + '")' ); - } - - self._addHoverEffects(); - }, - - /** - * Create gradient overlay string. - * - * @since 1.2.7 - * @param string color. - * @return string color. - */ - getOverlayImage: function( color ) { - return 'linear-gradient(to left, ' + color + ', ' + color + ')'; - }, - - /** - * Bind Event: Changing Gradient Color. - * - * @since 1.2.7 - */ - _setupGradientColor: function() { - var panel = BG.Panel; - - panel.$element.on( 'change', '.background-design [name^="gradient-color"]', function() { - var $this = $( this ), - $target = self.getTarget(), - value = $this.val(), - name = $this.attr( 'name' ), - type = $this.attr( 'data-type' ); - - if ( BoldgridEditor.is_crio ) { - if ( 'class' === type && 'neutral' !== value ) { - value = 'var( --color-' + value + ' )'; - } else if ( 'class' === type && 'neutral' === value ) { - value = 'var( --color-neutral )'; - } - } else if ( 'class' === type ) { - value = BoldgridEditor.colors.defaults[value - 1]; - } - - if ( 'gradient-color-1' === name ) { - $target.attr( 'data-bg-color-1', value ); - } else { - $target.attr( 'data-bg-color-2', value ); - } - - BG.Controls.addStyle( $target, 'background-image', self.createGradientCss( $target ) ); + panel.$element.find( '.ui-sortable' ).sortable( { + handle: '.dashicons-move' } ); - }, - - /** - * Bind Event: Clicking Settings. - * - * @since 1.2.7 - */ - _setupCustomization: function() { - var panel = BG.Panel; - - panel.$element.on( 'click', '.current-selection .settings .panel-button.customizer', function( - e - ) { - e.preventDefault(); - self.openCustomization(); - } ); - - panel.$element.on( - 'click', - '.current-selection:not( [data-type=hover-image] ) .settings .panel-button.remove-background', - function( e ) { - e.preventDefault(); - self._removeImage(); - } - ); - panel.$element.on( - 'click', - '.current-selection[data-type=hover-image] .settings .panel-button.remove-background', - function( e ) { - e.preventDefault(); - self._removeImage( e, 'hover-image' ); - } - ); - }, - - /** - * Button to remove an image. - * - * @since 1.12.0 - */ - _removeImage( e, type ) { - var $target = self.getTarget(), - bgHoverClass = $target.attr( 'data-hover-bg-class' ), - styleIdSuffixes = [ 'image', 'bg-size', 'mobile-image', 'position', 'bg-color' ]; - - if ( 'hover-image' === type ) { - - // Remove Hover Styles from head. - styleIdSuffixes.forEach( function( styleIdSuffix ) { - $target - .parents( 'html' ) - .find( 'head' ) - .find( `#${bgHoverClass}-${styleIdSuffix}` ) - .remove(); - } ); - // Remove Image and Overlay attributes. - $target.removeAttr( 'data-hover-image-url' ); - $target.removeAttr( 'data-hover-bg-overlaycolor' ); - $target.removeAttr( 'data-hover-bg-position' ); - $target.removeAttr( 'data-hover-bg-size' ); - - // Remove Hover Color Attributes. - $target.removeAttr( 'data-hover-bg-color' ); + // Open Panel. + panel.open( self ); - // Remove hover class and atribute. - $target.removeAttr( 'data-hover-bg-class' ); - $target.removeClass( 'has-hover-bg' ); - $target.removeClass( bgHoverClass ); + panel.$element.find( '.panel-body' ).append( '
' ); - BG.Panel.$element.find( '.add-hover-image-controls' ).removeAttr( 'style' ); + // This will be the element that the React App attaches to. + const bgRoot = createRoot( panel.$element.find( '.bg-background-react-container' ).get( 0 ) ); - self.setImageSelection( 'hover-color' ); - } else { - self.removeColorClasses( $target ); - BG.Controls.addStyle( $target, 'background', '' ); - $target.removeAttr( 'data-image-url' ); + // TODO: Create a dynamic way of setting this to support other themes. + const colorVariables = { + 'color-1': 'var(--color-1)', + 'color-2': 'var(--color-2)', + 'color-3': 'var(--color-3)', + 'color-4': 'var(--color-4)', + 'color-5': 'var(--color-5)', + 'color-neutral': 'var(--color-neutral )', + }; - BG.Panel.$element.find( '.presets .selected' ).removeClass( 'selected' ); + const savedColors = BoldgridEditor.saved_colors; - // Reset Gradient attributes. - $target - .removeAttr( 'data-bg-color-1' ) - .removeAttr( 'data-image-url' ) - .removeAttr( 'data-bg-color-2' ) - .removeAttr( 'data-bg-overlaycolor' ) - .removeAttr( 'data-bg-direction' ); - self.setImageSelection( 'color' ); + // This ensures that the background image panel shows if there is a background image set. + if ( self.$target.css( 'background-image' ).includes( 'url' ) ) { + selectedComponent = 'BoldgridBackgroundImage'; } - }, - - /** - * Setup mobile visibility controls - * - * @since 1.17.0 - */ - _setupMobileVisibility: function() { - var panel = BG.Panel; - panel.$element.on( - 'change', - '.background-design input[name="mobile-only-visibility"]', - function() { - var $this = $( this ), - $target = self.getTarget(), - classes = [ 'hover-mobile-bg' ]; - - switch ( $this.val() ) { - case 'hover': - $target.removeClass( classes ); - $target.addClass( 'hover-mobile-bg' ); - break; - default: - $target.removeClass( classes ); - break; - } - } - ); - }, - - /** - * Bind Event: Input scroll effect changing. - * - * @since 1.2.7 - */ - _setupScrollEffects: function() { - var panel = BG.Panel; - - panel.$element.on( 'change', '.background-design input[name="scroll-effects"]', function() { - var $this = $( this ), - $target = self.getTarget(); - - if ( 'none' === $this.val() ) { - $target.removeClass( self.availableEffects.join( ' ' ) ); - } else { - $target.removeClass( self.availableEffects.join( ' ' ) ); - $target.addClass( $this.val() ); - } - } ); - panel.$element.on( - 'change', - '.background-design input[name="hover-scroll-effects"]', - function() { - var $this = $( this ), - $target = self.getTarget(); - - if ( 'none' === $this.val() ) { - $target.removeClass( self.availableHoverEffects.join( ' ' ) ); - } else { - $target.removeClass( self.availableHoverEffects.join( ' ' ) ); - $target.addClass( $this.val() ); - } + const usedComponents = [ + { + name: 'BoldgridBackgroundColor', + props: { colorVariables, savedColors, target: self.$target }, + navClass: 'dashicons dashicons-art', + title: 'Background Color', + Component: null + }, + { + name: 'BoldgridBackgroundImage', + props: { colorVariables, savedColors, target: self.$target }, + navClass: 'dashicons dashicons-format-image', + title: 'Background Image', + Component: null + }, + { + name: 'BoldgridHoverEffects', + props: { colorVariables, savedColors, target: self.$target }, + navClass: 'fa fa-hand-pointer-o', + title: 'Hover Effects', + Component: null } - ); - }, - - /** - * Bind Event: Input gradient direction changing. - * - * @since 1.2.7 - */ - _setupGradientDirection: function() { - var panel = BG.Panel; - - panel.$element.on( 'change', '.background-design input[name="bg-direction"]', function() { - var $this = $( this ), - $target = self.getTarget(); - - $target.attr( 'data-bg-direction', $this.val() ); - BG.Controls.addStyle( $target, 'background-image', self.createGradientCss( $target ) ); - } ); - }, - - /** - * Create the css needed for a linear gradient. - * - * @since 1.2.7 - * @param jQuery $element. - */ - createGradientCss: function( $element ) { - return ( - 'linear-gradient(' + - $element.attr( 'data-bg-direction' ) + - ',' + - $element.attr( 'data-bg-color-1' ) + - ',' + - $element.attr( 'data-bg-color-2' ) + - ')' - ); - }, - - /** - * Setup background size control. - * - * @since 1.2.7 - */ - _setupBackgroundSize: function( isHoverImage ) { - var panel = BG.Panel; + ]; - panel.$element.on( - 'change', - '.background-design input[name="hover-background-size"]', - function() { - var $this = $( this ), - $target = self.getTarget(), - hoverBgId = $target.attr( 'data-hover-bg-class' ), - css = ''; - - if ( 'tiled' === $this.val() ) { - css = - '.' + - hoverBgId + - ':hover { background-size: auto auto !important; background-repeat: repeat !important; }'; - self._addHeadingStyle( hoverBgId + '-bg-size', css ); - $target.attr( 'data-hover-bg-size', 'tiled' ); - } else { - css = - '.' + - hoverBgId + - ':hover { background-size: cover !important; background-repeat: "no-repeat !important"; }'; - self._addHeadingStyle( hoverBgId + '-bg-size', css ); - $target.attr( 'data-hover-bg-size', 'cover' ); - } - } + return bgRoot.render( + ); - - panel.$element.on( 'change', '.background-design input[name="background-size"]', function() { - var $this = $( this ), - $target = self.getTarget(); - - if ( 'tiled' === $this.val() ) { - BG.Controls.addStyle( $target, 'background-size', 'auto auto' ); - BG.Controls.addStyle( $target, 'background-repeat', 'repeat' ); - } else if ( 'cover' === $this.val() ) { - BG.Controls.addStyle( $target, 'background-size', 'cover' ); - BG.Controls.addStyle( $target, 'background-repeat', 'no-repeat' ); - } - } ); - }, - - /** - * Bind Event: When the user leaves customization. - * - * @since 1.2.7 - */ - _setupCustomizeLeave: function() { - var panel = BG.Panel; - - panel.$element.on( 'click', '.background-design .back .panel-button', function( e ) { - e.preventDefault(); - - panel.$element.find( '.preset-wrapper' ).show(); - panel.$element.find( '.background-design .customize' ).hide(); - panel.initScroll(); - self.preselectBackground(); - panel.scrollToSelected(); - BG.Service.customize.navigation.disable(); - } ); - }, - - /** - * Bind Event: When the user clicks on a filter. - * - * @since 1.2.7 - */ - _setupFilterClick: function() { - var panel = BG.Panel; - - panel.$element.on( 'click', '.background-design .filter', function( e ) { - e.preventDefault(); - - let $this = $( this ), - type = $this.data( 'type' ), - label = $this.data( 'label' ), - $currentSelection = panel.$element.find( '.current-selection' ), - $presetsBackgroundColor = panel.$element.find( '.presets .background-color.section' ), - $target = self.getTarget(), - bgColor = $target.css( 'background-color' ); - - panel.$element.find( '.filter' ).removeClass( 'selected' ); - $this.addClass( 'selected' ); - - panel.$element.find( '.presets .selection' ).hide(); - $.each( type, function() { - panel.$element.find( '.presets .selection[data-type="' + this + '"]' ).show(); - } ); - - panel.$element.find( '.presets .title > *' ).text( label ); - panel.$element.find( '.presets' ).attr( 'data-filter', type ); - $currentSelection.attr( 'data-filter', type ); - - if ( type.length && type.includes( 'hover' ) ) { - let selectionType = $target.attr( 'data-hover-image-url' ) ? 'hover-image' : 'hover-color'; - $currentSelection.attr( 'data-type', selectionType ); - self.setImageSelection( selectionType, bgColor ); - } - - if ( - type.length && - ! type.includes( 'gradients' ) && - ( type.includes( 'image' ) || type.includes( 'color' ) || type.includes( 'pattern' ) ) - ) { - let selectionType = $target.attr( 'data-image-url' ) ? 'image' : 'color'; - $currentSelection.attr( 'data-type', selectionType ); - self.setImageSelection( selectionType, bgColor ); - } - - if ( type.length && type.includes( 'gradients' ) ) { - let selectionType = 'gradients'; - $currentSelection.attr( 'data-type', selectionType ); - self.setImageSelection( selectionType, $target.css( 'background-image' ) ); - } - - if ( - ( type.length && -1 !== type.indexOf( 'image' ) ) || - ( type.length && -1 !== type.indexOf( 'hover' ) ) - ) { - $presetsBackgroundColor.hide(); - } else { - $presetsBackgroundColor.show(); - } - - panel.scrollToSelected(); - } ); - }, - - /** - * Remove all color classes. - * - * @since 1.2.7 - * @param jQuery $target. - */ - removeColorClasses: function( $target ) { - $target.removeClass( 'bg-background-color' ); - $target.removeClass( BG.CONTROLS.Color.backgroundColorClasses.join( ' ' ) ); - $target.removeClass( BG.CONTROLS.Color.textContrastClasses.join( ' ' ) ); - }, - - /** - * Bind Event: When the user clicks on a design. - * - * @since 1.2.7 - */ - _setupBackgroundClick: function() { - var panel = BG.Panel; - - panel.$element.on( 'click', '.background-design .presets .selection', function() { - var $this = $( this ), - $target = self.getTarget(), - imageUrl = $this.attr( 'data-image-url' ), - imageSrc = $this.css( 'background-image' ), - background = $this.css( 'background' ), - bgUuid = $target.attr( 'data-bg-uuid' ), - value; - - if ( $this.hasClass( 'selected' ) ) { - self.removeColorClasses( $target ); - BG.Controls.addStyle( $target, 'background', '' ); - $target.removeAttr( 'data-image-url' ); - $this.removeClass( 'selected' ); - self.preselectBackground( true ); - - return; - } - - panel.$element.find( '.presets .selected' ).removeClass( 'selected' ); - $this.addClass( 'selected' ); - - // Reset Gradient attributes. - $target - .removeAttr( 'data-bg-color-1' ) - .removeAttr( 'data-image-url' ) - .removeAttr( 'data-bg-color-2' ) - .removeAttr( 'data-bg-direction' ); - - // Reset Alpha attributes. - $target - .removeAttr( 'data-bg-alpha' ) - .removeAttr( 'data-bg-uuid' ) - .removeClass( bgUuid ); - - if ( 'pattern' !== $this.data( 'type' ) ) { - self.removeColorClasses( $target ); - } - - if ( 'image' === $this.data( 'type' ) ) { - self.setImageBackground( imageUrl ); - } else if ( 'color' === $this.data( 'type' ) ) { - $target.addClass( $this.data( 'class' ) ); - value = $this.data( 'class' ); - value = value.includes( 'neutral' ) ? 'neutral' : value.replace( /\D/g, '' ); - $target.addClass( BG.CONTROLS.Color.getColorClass( 'text-contrast', value ) ); - $target.addClass( 'bg-background-color' ); - BG.Controls.addStyle( $target, 'background-image', '' ); - self.setDefaultBackgroundColors(); - } else if ( 'pattern' === $this.data( 'type' ) ) { - BG.Controls.addStyle( $target, 'background-size', 'auto auto' ); - BG.Controls.addStyle( $target, 'background-repeat', 'repeat' ); - BG.Controls.addStyle( $target, 'background-image', imageSrc ); - } else if ( 'gradients' === $this.data( 'type' ) ) { - $target - .attr( 'data-bg-color-1', $this.data( 'color1' ) ) - .attr( 'data-bg-color-2', $this.data( 'color2' ) ) - .attr( 'data-bg-direction', $this.data( 'direction' ) ); - BG.Controls.addStyle( $target, 'background-image', self.createGradientCss( $target ) ); - } else { - BG.Controls.addStyle( $target, 'background-image', imageSrc ); - } - - self.setImageSelection( $this.data( 'type' ), background ); - } ); - }, - - /** - * Activate a filter. - * - * @since 1.2.7 - * @param string type. - */ - activateFilter: function( type ) { - var backgroundImageProp, - filterFound = false, - $target = self.getTarget(); - - BG.Panel.$element.find( '.current-selection .filter' ).each( function() { - var $this = $( this ), - filterTypes = $this.data( 'type' ); - - if ( type && -1 !== filterTypes.indexOf( type ) ) { - $this.click(); - filterFound = true; - return false; - } - } ); - - if ( ! filterFound && ! type ) { - backgroundImageProp = $target.css( 'background-image' ); - if ( backgroundImageProp && 'none' !== backgroundImageProp ) { - - // Image filter selection hack, trouble selecting array data type. - BG.Panel.$element.find( '.filter[data-type]:first-of-type' ).click(); - filterFound = true; - } - } - - if ( false === filterFound ) { - BG.Panel.$element.find( '.filter[data-default="1"]' ).click(); - } }, - - /** - * Set Image selection. - * - * @since 1.2.7 - * @param string type. - * @param string prop. - */ - setImageSelection: function( type, prop, isHoverImage ) { - var $currentSelection = BG.Panel.$element.find( '.current-selection' ), - $target = self.getTarget(), - bgImageUrl = $target.attr( 'data-image-url' ), - bgColor = $target.css( 'background-color' ), - overlayColor = $target.attr( 'data-bg-overlaycolor' ), - hoverOverlayColor = $target.attr( 'data-hover-bg-overlaycolor' ), - hoverBgImageUrl = $target.attr( 'data-hover-image-url' ), - hoverColor = $target.attr( 'data-hover-bg-color' ); - - $currentSelection.css( 'background', '' ); - - if ( 'color' === type ) { - $currentSelection.css( 'background-color', prop ); - } else if ( 'hover-image' === type ) { - $currentSelection.css( 'background-color', prop ); - if ( hoverBgImageUrl && hoverOverlayColor ) { - $currentSelection.css( - 'background-image', - `${self.getOverlayImage( hoverOverlayColor )}, url('${hoverBgImageUrl}')` - ); - } else if ( hoverBgImageUrl ) { - $currentSelection.css( 'background-image', `url('${hoverBgImageUrl}')` ); - } else if ( bgImageUrl ) { - $currentSelection.css( 'background-image', `url('${bgImageUrl}')` ); - } - self._setupHoverBoxes(); - } else if ( 'hover-color' === type ) { - if ( hoverColor && ! hoverBgImageUrl ) { - $currentSelection.css( 'background-color', hoverColor ); - } else if ( ! hoverColor && ! hoverBgImageUrl ) { - $currentSelection.css( 'background-color', 'rgba(0,0,0,0)' ); - } - self._setupHoverBoxes(); - } else if ( 'gradients' === type ) { - $currentSelection.css( 'background-image', $target.css( 'background-image' ) ); - } else { - $currentSelection.css( 'background-color', bgColor ); - if ( bgImageUrl && overlayColor ) { - $currentSelection.css( - 'background-image', - `${self.getOverlayImage( overlayColor )}, url('${bgImageUrl}')` - ); - } else if ( bgImageUrl ) { - $currentSelection.css( 'background-image', `url('${bgImageUrl}')` ); - } - } - - $currentSelection.attr( 'data-type', type ); - }, - - /** - * Set Image background. - * - * @since 1.2.7 - * @param string url. - * @param isHoverImage Is Hover Image. - */ - setImageBackground: function( url, isHoverImage = false ) { - var $target = self.getTarget(), - hvrBgClass = $target.attr( 'data-hover-bg-class' ); - - if ( isHoverImage && ! hvrBgClass ) { - hvrBgClass = 'hover-bg-' + Math.floor( Math.random() * 999 + 1 ).toString(); - $target.addClass( hvrBgClass ); - $target.attr( 'data-hover-bg-class', hvrBgClass ); - } - if ( isHoverImage ) { - $target.attr( 'data-hover-image-url', url ); - $target.addClass( 'has-hover-bg' ); - self._addHoverEffects(); - } else { - $target.attr( 'data-image-url', url ); - BG.Controls.addStyle( $target, 'background', '' ); - self.updateBackgroundImage(); - BG.Controls.addStyle( $target, 'background-size', 'cover' ); - BG.Controls.addStyle( $target, 'background-repeat', 'no-repeat' ); - BG.Controls.addStyle( $target, 'background-position', '50% 50%' ); - } - }, - - /** - * Init all sliders. - * - * @since 1.2.7 - */ - _initSliders: function() { - self._initVerticleSlider(); - }, - - /** - * Init Vertical position slider. - * - * @since 1.2.7 - */ - _initVerticleSlider: function() { - var $target = self.getTarget(), - defaultPosY = $target.css( 'background-position-y' ), - defaultPosX = $target.css( 'background-position-x' ); - - defaultPosY = defaultPosY ? parseInt( defaultPosY ) : 50; - defaultPosX = defaultPosX ? parseInt( defaultPosX ) : 50; - - BG.Panel.$element - .find( '.background-design .vertical-position .slider' ) - .slider( { - min: 0, - max: 100, - value: defaultPosY, - range: 'max', - slide: function( event, ui ) { - if ( $target.css( 'background-image' ) ) { - BG.Controls.addStyle( - $target, - 'background-position', - defaultPosX + '%' + ' ' + ui.value + '%' - ); - } - } - } ) - .siblings( '.value' ) - .html( defaultPosY ); - - BG.Panel.$element - .find( '.background-design .hover-vertical-position .slider' ) - .slider( { - min: 0, - max: 100, - value: $target.attr( 'data-hover-bg-position' ) ? - $target.attr( 'data-hover-bg-position' ) : - defaultPosY, - range: 'max', - slide: function( event, ui ) { - if ( $target.attr( 'data-hover-bg-class' ) ) { - self._addHeadingStyle( - $target.attr( 'data-hover-bg-class' ) + '-position', - `.${$target.attr( 'data-hover-bg-class' )}:hover { - background-position: ${defaultPosX + '%'} ${ui.value}% !important; - }` - ); - $target.attr( 'data-hover-bg-position', ui.value ); - } - } - } ) - .siblings( '.value' ) - .html( defaultPosY ); - }, - - /** - * Open the customization view. - * - * @since 1.2.7 - */ - openCustomization: function() { - var dataType = BG.Panel.$element.find( '.current-selection' ).attr( 'data-type' ); - - BG.Panel.$element.find( '.preset-wrapper' ).hide(); - BG.Panel.$element.find( '.background-design .customize' ).show(); - BG.Panel.$element.find( '.preset-wrapper' ).attr( 'data-type', dataType ); - self._initSliders(); - self.selectDefaults(); - BG.Panel.enterCustomization(); - BG.Panel.customizeOpenEvent(); - - BG.Panel.createScrollbar( '.customize', { - height: self.panel.height - } ); - }, - - /** - * Set all defaults. - * - * @since 1.2.7 - */ - selectDefaults: function() { - self.setScrollEffect(); - self.setSize(); - self.setDefaultDirection(); - self.setDefaultBackgroundColors(); - self.setDefaultOverlayColor(); - }, - - /** - * Set default overlay color. - * - * @since 1.2.7 - */ - setDefaultOverlayColor: function() { - var $target = self.getTarget(), - $overlayColorSection = BG.Panel.$element.find( '.overlay-color' ), - $hoverOverlayColorSeciont = BG.Panel.$element.find( '.hover-overlay-color' ), - hoverOverlayColor = $target.attr( 'data-hover-bg-overlaycolor' ), - overlayColor = $target.attr( 'data-bg-overlaycolor' ); - - if ( overlayColor ) { - $overlayColorSection - .find( 'input' ) - .val( overlayColor ) - .attr( 'value', overlayColor ); - } - if ( hoverOverlayColor ) { - $hoverOverlayColorSeciont - .find( 'input' ) - .val( hoverOverlayColor ) - .attr( 'value', hoverOverlayColor ); - } - }, - - /** - * Set default background size. - * - * @since 1.2.7 - */ - setSize: function() { - var $input = BG.Panel.$element.find( 'input[name="background-size"]' ), - $target = self.getTarget(); - - if ( -1 === $target.css( 'background-size' ).indexOf( 'cover' ) ) { - $input.filter( '[value="tiled"]' ).prop( 'checked', true ); - } - }, - - /** - * Set default scroll direction. - * - * @since 1.2.7 - */ - setScrollEffect: function() { - var $target = self.getTarget(); - - $.each( self.availableEffects, function() { - if ( $target.hasClass( this ) ) { - BG.Panel.$element - .find( 'input[name="scroll-effects"][value="' + this + '"]' ) - .prop( 'checked', true ); - return false; - } - } ); - }, - - /** - * Set graadient direction. - * - * @since 1.2.7 - */ - setDefaultDirection: function() { - var $target = self.getTarget(), - direction = $target.attr( 'data-bg-direction' ); - - if ( self.backgroundIsGradient( $target.css( 'background-image' ) ) && direction ) { - BG.Panel.$element - .find( 'input[name="bg-direction"][value="' + direction + '"]' ) - .prop( 'checked', true ); - } - }, - - /** - * Set default background colors. - * - * @since 1.2.7 - */ - setDefaultBackgroundColors: function() { - var bgColor, - hoverColor, - $bgControlColor, - $hoverColorControl, - $target = self.getTarget(); - - if ( self.backgroundIsGradient( $target.css( 'background-image' ) ) ) { - BG.Panel.$element - .find( 'input[name="gradient-color-1"]' ) - .val( $target.attr( 'data-bg-color-1' ) ) - .attr( 'value', $target.attr( 'data-bg-color-1' ) ); - BG.Panel.$element - .find( 'input[name="gradient-color-2"]' ) - .val( $target.attr( 'data-bg-color-2' ) ) - .attr( 'value', $target.attr( 'data-bg-color-2' ) ); - } else { - bgColor = BG.CONTROLS.Color.findAncestorColor( $target, 'background-color' ); - $bgControlColor = BG.Panel.$element.find( 'input[name="section-background-color"]' ); - $bgControlColor.prev( 'label' ).css( 'background-color', bgColor ); - $bgControlColor.val( bgColor ).attr( 'value', bgColor ); - } - - if ( $target.attr( 'data-hover-bg-color' ) ) { - hoverColor = $target.attr( 'data-hover-bg-color' ); - $hoverColorControl = BG.Panel.$element.find( 'input[name="section-hover-background-color"]' ); - $hoverColorControl.prev( 'label' ).css( 'background-color', hoverColor ); - $hoverColorControl.val( hoverColor ).attr( 'value', hoverColor ); - self._setupHoverBoxes(); - } - }, - - /** - * Get a random gradient direction. - * - * @since 1.2.7 - * @return string. - */ - randomGradientDirection: function() { - var directions = [ 'to left', 'to bottom' ]; - - return directions[Math.floor( Math.random() * directions.length )]; - }, - - /** - * Create JSON of gradients. Not used at runtime. - * - * @since 1.2.7 - */ - _createGradients: function() { - var gradientData = []; - - $.each( BoldgridEditor.sample_backgrounds.default_gradients, function() { - var color1 = this.colors[0], - color2 = this.colors[1], - direction = self.randomGradientDirection(); - - gradientData.push( { - color1: color1, - color2: color2, - direction: direction, - css: 'linear-gradient(' + direction + ',' + color1 + ',' + color2 + ')' - } ); - } ); - }, - - /** - * Create gradients based on the users palettes. - * - * @since 1.2.7 - */ - setPaletteGradients: function() { - var combos = []; - if ( BoldgridEditor.colors.defaults && BoldgridEditor.colors.defaults.length ) { - $.each( [ 0, 1 ], function() { - var color1, color2, pos1, pos2, direction; - pos1 = Math.floor( Math.random() * BoldgridEditor.colors.defaults.length ) + 1; - pos2 = Math.floor( Math.random() * BoldgridEditor.colors.defaults.length ) + 1; - color1 = 'var( --color-' + pos1 + ' )'; - color2 = 'var( --color-' + pos2 + ' )'; - if ( ! BoldgridEditor.is_crio ) { - color1 = BoldgridEditor.colors.defaults[pos1 - 1]; - color2 = BoldgridEditor.colors.defaults[pos2 - 1]; - } - if ( color1 !== color2 ) { - direction = self.randomGradientDirection(); - combos.push( { - color1: color1, - color2: color2, - direction: direction, - css: 'linear-gradient(' + direction + ',' + color1 + ',' + color2 + ')' - } ); - } - } ); - } - - $.each( combos, function() { - BoldgridEditor.sample_backgrounds.gradients.unshift( this ); - } ); - }, - - /** - * Is the given url a gradient. - * - * @since 1.2.7 - * @param string backgroundUrl. - * @return boolean. - */ - backgroundIsGradient: function( backgroundUrl ) { - return -1 !== backgroundUrl.indexOf( 'linear-gradient' ) && -1 === backgroundUrl.indexOf( 'url' ); - }, - - /** - * Preselect the background being used when opening the panel. - * - * @since 1.2.7 - */ - preselectBackground: function( keepFilter ) { - var type = 'color', - $target = self.getTarget(), - backgroundColor = $target.css( 'background-color' ), - backgroundUrl = $target.css( 'background-image' ), - hoverBackgroundUrl = $target.attr( 'data-hover-image-url' ), - $currentSelection = BG.Panel.$element.find( '.current-selection' ), - hasGradient = self.backgroundIsGradient( backgroundUrl ), - matchFound = false; - - //@TODO: update the preview screen when pressing back from the customize section. - - // Set the background color, and background image of the current section to the preview. - self.setImageSelection( 'image' ); - $currentSelection.css( 'background-color', backgroundColor ); - - BG.Panel.$element.find( '.selection' ).each( function() { - var $this = $( this ), - selectionType = $this.data( 'type' ), - dataClass = $this.data( 'class' ); - - switch ( selectionType ) { - case 'color': - if ( - dataClass && - $target.hasClass( dataClass ) && - 'none' === $target.css( 'background-image' ) - ) { - $this.addClass( 'selected' ); - type = selectionType; - matchFound = true; - self.activateFilter( type ); - return false; - } - break; - case 'image': - if ( $this.attr( 'data-image-url' ) === $target.attr( 'data-image-url' ) ) { - - //Found a match. - $this.addClass( 'selected' ); - type = selectionType; - matchFound = true; - self.activateFilter( type ); - return false; - } - break; - case 'gradients': - case 'pattern': - if ( $this.css( 'background-image' ) === backgroundUrl ) { - - //Found a match. - $this.addClass( 'selected' ); - type = selectionType; - matchFound = true; - self.activateFilter( type ); - return false; - } - break; - } - } ); - - if ( ! matchFound ) { - if ( hasGradient ) { - type = 'gradients'; - } else if ( 'none' !== backgroundUrl ) { - type = 'image'; - } - - if ( ! keepFilter ) { - self.activateFilter( type ); - } - } - - $currentSelection.attr( 'data-type', type ); - }, - - /** - * Find out what type of element we're controlling the background of. - * - * @since 1.8.0 - */ - setElementType: function() { - self.elementType = this.checkElementType( self.$target ); - BG.Panel.$element.find( '.customize-navigation' ).attr( 'data-element-type', self.elementType ); - self.panel.targetType = self.elementType; - }, - - /** - * Set element visibility. - * - * @since 1.17.0 - */ - setElementVisibility() { - var $target = self.getTarget(), - visibility = $target.hasClass( 'hover-mobile-bg' ) ? 'hover' : 'default', - $radios = BG.Panel.$element.find( '.mobile-only-visibility input' ); - - $radios.each( function() { - if ( $( this ).val() === visibility ) { - $( this ).attr( 'checked', true ); - } else { - $( this ).attr( 'checked', false ); - } - } ); - }, - - /** - * Determine the element type supported by this control. - * - * @since 1.8.0 - * - * @param {jQuery} $element Jquery Element. - * @return {string} Element. - */ - checkElementType: function( $element ) { - let type = ''; - if ( $element.hasClass( 'boldgrid-section' ) ) { - type = 'section'; - } else if ( $element.hasClass( 'row' ) ) { - type = 'row'; - } else if ( $element.hasClass( 'bg-box' ) ) { - type = 'bg-box'; - } else { - type = 'column'; - } - - return type; - }, - - /** - * Open Panel. - * - * @since 1.2.7 - * - * @param $target Current Target. - */ - openPanel: function( $target ) { - var panel = BG.Panel, - template = wp.template( 'boldgrid-editor-background' ); - - self.$target = $target; - - BoldgridEditor.sample_backgrounds.color = BG.CONTROLS.Color.getPaletteBackgroundColors(); - - // Remove all content from the panel. - panel.clear(); - - self.setPaletteGradients(); - panel.$element.find( '.panel-body' ).html( - template( { - images: BoldgridEditor.sample_backgrounds, - imageData: BoldgridEditor.builder_config.background_images - } ) - ); - - self.preselectBackground(); - self.setDefaultBackgroundColors(); - self.setElementType(); - self.setElementVisibility(); - - // Open Panel. - panel.open( self ); - } }; BOLDGRID.EDITOR.CONTROLS.Background.init(); self = BOLDGRID.EDITOR.CONTROLS.Background; + + if ( ! self.loadLegacyControl() ) { + delete BOLDGRID.EDITOR.CONTROLS.Background; + } } )( jQuery ); diff --git a/assets/js/builder/notice/bg-control/index.js b/assets/js/builder/notice/bg-control/index.js new file mode 100644 index 00000000..59d01728 --- /dev/null +++ b/assets/js/builder/notice/bg-control/index.js @@ -0,0 +1 @@ +export { Notice as BgControl } from './notice'; diff --git a/assets/js/builder/notice/bg-control/notice.js b/assets/js/builder/notice/bg-control/notice.js new file mode 100644 index 00000000..3b13a622 --- /dev/null +++ b/assets/js/builder/notice/bg-control/notice.js @@ -0,0 +1,64 @@ +import { Base } from '../base.js'; + +export class Notice extends Base { + constructor() { + super(); + + this.name = 'bg_control'; + + this.panel = { + title: 'BoldGrid Post and Page Builder - New Feature', + height: '345px', + width: '675px', + disabledClose: true, + autoCenter: true + }; + } + + /** + * Open the panel. + * + * @since 1.9.0 + */ + init() { + BG.Panel.currentControl = this; + BG.Panel.setDimensions( this.panel.width, this.panel.height ); + BG.Panel.setTitle( this.panel.title ); + BG.Panel.setContent( this.getHTML() ); + BG.Panel.centerPanel(); + BG.Panel.$element.show(); + this.bindDismissButton(); + } + + /** + * Get HTML for the notice. + * + * @since 1.9.0 + * + * @return {string} Template markup. + */ + getHTML() { + return ` +
+
+ +
+
+

+ Feature Update: + Background Controls +

+

+ The background controls have been updated to add new features, such as better gradient controls, and + better utilization of theme color variables. Check out our support article for more information. +

+

+ Okay, Got It! +

+
+
+ `; + } +} diff --git a/assets/js/builder/notice/loader.js b/assets/js/builder/notice/loader.js index 6aca5a03..323e7674 100644 --- a/assets/js/builder/notice/loader.js +++ b/assets/js/builder/notice/loader.js @@ -1,5 +1,6 @@ import { EditorChoice } from './editor-choice'; import { Intro } from './intro'; +import { BgControl } from './bg-control'; /** * Load one time notices, on first editor load. @@ -14,7 +15,10 @@ export class Loader { intro: Intro, // eslint-disable-next-line - editor_choice: EditorChoice + editor_choice: EditorChoice, + + // eslint-disable-next-line + bg_control: BgControl }; } diff --git a/assets/js/builder/panel.js b/assets/js/builder/panel.js index f34339c5..dd2454a7 100644 --- a/assets/js/builder/panel.js +++ b/assets/js/builder/panel.js @@ -179,7 +179,8 @@ BOLDGRID.EDITOR = BOLDGRID.EDITOR || {}; var sizeOffset = -66, $target = this.$element.find( selector ); - if ( config && config.sizeOffset ) { + // If the config has a sizeOffset, use that instead. + if ( config && 'undefined' !== typeof config.sizeOffset ) { sizeOffset = config.sizeOffset; } @@ -572,6 +573,20 @@ BOLDGRID.EDITOR = BOLDGRID.EDITOR || {}; _onWheel: function( e ) { e = e || window.event; + /** + * New controls using the BoldgridPanel + * React component do not use the slimScroll module + * that legacy controls do. Therefore, we have to check for + * this. + */ + if ( + self.currentControl && + self.currentControl.panel && + true === self.currentControl.panel.noSlimScroll + ) { + return; + } + if ( e.preventDefault ) { e.preventDefault(); } @@ -658,7 +673,6 @@ BOLDGRID.EDITOR = BOLDGRID.EDITOR || {}; this.$element.show(); this.initScroll( control ); this.preselect(); - this.scrollToSelected(); this.collapseSelection(); this.showOverlay(); diff --git a/assets/scss/_variables.scss b/assets/scss/_variables.scss index 19abb412..f505abb2 100644 --- a/assets/scss/_variables.scss +++ b/assets/scss/_variables.scss @@ -10,3 +10,18 @@ $heading-text-color: #32373c; $title-border-color: rgba(218, 218, 218, 0.4); $gridblock-color: #32373c; $darkened-boldgrid-color: darken( $boldgrid-color, 10% ); + +:root { + --COLOR-1: var(--color-1); + --COLOR-1-RAW: var(--color-1-raw); + --COLOR-2: var(--color-2); + --COLOR-2-RAW: var(--color-2-raw); + --COLOR-3: var(--color-3); + --COLOR-3-RAW: var(--color-3-raw); + --COLOR-4: var(--color-4); + --COLOR-4-RAW: var(--color-4-raw); + --COLOR-5: var(--color-5); + --COLOR-5-RAW: var(--color-5-raw); + --COLOR-NEUTRAL: var(--color-neutral); + --COLOR-NEUTRAL-RAW: var(--color-neutral-raw); +} diff --git a/assets/scss/builder/panel/_background.scss b/assets/scss/builder/panel/_background.scss index 8730fe3f..fb0ab8d7 100644 --- a/assets/scss/builder/panel/_background.scss +++ b/assets/scss/builder/panel/_background.scss @@ -297,3 +297,30 @@ } } } + +.editor-panel[data-type="background"] { + .background-design.non-legacy { + margin-left: 60px; + padding: 10px; + .background-panel-section { + display: none; + &.active { + display: block; + } + } + } + .background-nav { + display: block; + .background-nav-item { + width: 60px; + span.dashicons { + color: white; + font-size:30px; + text-align: center; + width: 60px; + height: 40px; + padding-top: 10px; + } + } + } +} diff --git a/assets/scss/builder/panel/_navigation.scss b/assets/scss/builder/panel/_navigation.scss index cab196fc..e1aa1e53 100644 --- a/assets/scss/builder/panel/_navigation.scss +++ b/assets/scss/builder/panel/_navigation.scss @@ -9,7 +9,16 @@ } } -.customize-navigation { +.editor-panel .boldgrid-panel-nav__item:hover { + .boldgrid-tooltip { + display: block; + right: 40px !important; + top: 50% !important; + transform: translateY(-50%); + } +} + +.customize-navigation, .background-nav { position: absolute; bottom: 0; left: 0; diff --git a/babel.config.json b/babel.config.json index 1d8ae498..cb15c1dc 100644 --- a/babel.config.json +++ b/babel.config.json @@ -6,6 +6,11 @@ "useBuiltIns": "entry", "corejs": "3.22" } + ], + [ + "@babel/preset-react", { + "runtime": "automatic" + } ] ], "plugins": [ diff --git a/includes/builder/class-boldgrid-editor-builder.php b/includes/builder/class-boldgrid-editor-builder.php index 8ffdd1d6..c22cb5d1 100644 --- a/includes/builder/class-boldgrid-editor-builder.php +++ b/includes/builder/class-boldgrid-editor-builder.php @@ -246,6 +246,7 @@ public function print_scripts() { $paths[] = $template_path . '/gridblock.php'; $paths[] = $template_path . '/information.php'; $paths[] = $template_path . '/background.php'; + $paths[] = $template_path . '/background-legacy.php'; $paths[] = $template_path . '/box.php'; $paths[] = $template_path . '/panel.php'; $paths[] = $template_path . '/upgrade-notice.php'; diff --git a/includes/class-boldgrid-editor-assets.php b/includes/class-boldgrid-editor-assets.php index b16ae560..4dda0eed 100644 --- a/includes/class-boldgrid-editor-assets.php +++ b/includes/class-boldgrid-editor-assets.php @@ -322,9 +322,10 @@ public function get_js_vars() { $boldgrid_settings['api_key'] = $config['api_key']; $current_theme = wp_get_theme(); + $theme_version = $current_theme->get( 'Version' ); $is_crio = false; if ( $current_theme->exists() ) { - $theme_name = $current_theme->get( 'Name' ); + $theme_name = $current_theme->get( 'Name' ); if ( 'Crio' === $theme_name || 'Prime' === $theme_name ) { $is_crio = true; } @@ -360,6 +361,7 @@ public function get_js_vars() { 'is_boldgrid_theme' => $is_bg_theme, 'crio_button_classes' => apply_filters( 'bgtfw_button_classes', array() ), 'is_crio' => $is_crio, + 'theme_version' => $theme_version, 'is_add_new' => 'post-new.php' === $pagenow, 'body_class' => Boldgrid_Editor_Theme::theme_body_class(), 'post' => (array) $post, @@ -615,7 +617,7 @@ public function add_styles() { wp_register_style( 'editor-css-imhwpb', self::editor_css_url(), array(), BOLDGRID_EDITOR_VERSION ); wp_enqueue_style( 'animatecss', - plugins_url( '/assets/css/animate.min.css', $plugin_file ), array(), BOLDGRID_EDITOR_VERSION ); + plugins_url( '/assets/css/animate.min.css', $plugin_file ), array( 'wp-components' ), BOLDGRID_EDITOR_VERSION ); wp_enqueue_style( 'boldgrid-components', plugins_url( '/assets/css/components' . $suffix . '.css', $plugin_file ), array(), diff --git a/includes/class-boldgrid-editor-setup.php b/includes/class-boldgrid-editor-setup.php index c6176ff1..8755f940 100644 --- a/includes/class-boldgrid-editor-setup.php +++ b/includes/class-boldgrid-editor-setup.php @@ -40,6 +40,7 @@ public static function get_notice_status() { */ return [ [ 'name' => 'editor_choice', 'enabled' => self::has_editor_choice_notice() ], + [ 'name' => 'bg_control', 'enabled' => self::has_bg_control_notice() ], [ 'name' => 'intro', 'enabled' => ! self::is_notice_dismissed( 'editor_choice' ) && ! $setup ], ]; } @@ -55,6 +56,25 @@ public static function has_editor_choice_notice() { return Boldgrid_Editor_Version::is_activated_version_older_than( '1.9.0-rc.0' ) && ! self::check_and_dismiss( 'editor_choice' ); } + /** + * Should we display the new Background Control Notice? + * + * @since 1.25.0 + * + * @return boolean Display Notice? + */ + public static function has_bg_control_notice() { + $is_crio = false; + $current_theme = wp_get_theme(); + if ( $current_theme->exists() ) { + $theme_name = $current_theme->get( 'Name' ); + if ( 'Crio' === $theme_name || 'Prime' === $theme_name ) { + $is_crio = true; + } + } + return Boldgrid_Editor_Version::is_activated_version_older_than( '1.25.0-rc1' ) && ! self::check_and_dismiss( 'bg_control' ) && $is_crio; + } + /** * Check if a notice is dismissed. * diff --git a/includes/template/background.php b/includes/template/background-legacy.php similarity index 99% rename from includes/template/background.php rename to includes/template/background-legacy.php index 97a75552..72942280 100644 --- a/includes/template/background.php +++ b/includes/template/background-legacy.php @@ -1,4 +1,4 @@ -