/* global FusionPageBuilderApp, FusionPageBuilder, FusionPageBuilderElements */
/* eslint no-unused-vars: 0 */
( function() {
// Insert shortcode into post editor
window.fusionBuilderInsertIntoEditor = function( shortcode, editorID ) { // jshint ignore:line
var editorArea,
editor;
if ( 'tinymce' === window.SCmoduleContentEditorMode && ( '' === editorID || 'undefined' === typeof editorID ) ) {
if ( 'undefined' !== typeof window.tinyMCE ) {
// Set active editor
editor = FusionPageBuilderApp.shortcodeGeneratorActiveEditor;
editor.focus();
if ( 'excerpt' === editor.id ) {
FusionPageBuilderApp.fromExcerpt = true;
}
// Insert shortcode
window.tinyMCE.activeEditor.execCommand( 'mceInsertContent', false, shortcode );
window.tinyMCE.activeEditor.execCommand( 'mceCleanup', false );
}
} else {
if ( null === editorID || '' === editorID || 'undefined' === typeof editorID ) {
editorArea = jQuery( window.editorArea );
} else {
editorArea = jQuery( '#' + editorID );
}
if ( 'excerpt' === editorArea.attr( 'id' ) ) {
FusionPageBuilderApp.fromExcerpt = true;
}
if ( 'undefined' === typeof window.cursorPosition ) {
if ( 0 === editorArea.getCursorPosition() ) {
editorArea.val( shortcode + editorArea.val() );
} else if ( editorArea.val().length === editorArea.getCursorPosition() ) {
editorArea.val( editorArea.val() + shortcode );
} else {
editorArea.val( editorArea.val().slice( 0, editorArea.getCursorPosition() ) + shortcode + editorArea.val().slice( editorArea.getCursorPosition() ) );
}
} else {
editorArea.val( [ editorArea.val().slice( 0, window.cursorPosition ), shortcode, editorArea.val().slice( window.cursorPosition ) ].join( '' ) );
}
editorArea.trigger( 'change' );
}
if ( false === FusionPageBuilderApp.manuallyAdded ) {
FusionPageBuilderApp.shortcodeGeneratorActiveEditor = '';
}
};
}( jQuery ) );
function openShortcodeGenerator( trigger ) { // jshint ignore:line
// Get editor id from event.trigger. parent.parent
var view,
viewSettings,
editorArea,
editorCid;
if ( 'object' === typeof trigger && 'undefined' !== typeof trigger[ 0 ].$el ) {
trigger = trigger[ 0 ].$el;
}
editorArea = '#' + trigger.parent().parent().find( '.wp-editor-area' ).attr( 'id' );
editorCid = trigger.closest( '.fusion-builder-module-settings' ).attr( 'data-element-cid' );
window.cursorPosition = 0;
window.editorArea = editorArea;
// Set shortcode generator flag
FusionPageBuilderApp.shortcodeGenerator = true;
// Get active editor mode
if ( FusionPageBuilderApp.isTinyMceActive() ) {
window.SCmoduleContentEditorMode = 'tinymce';
} else {
window.SCmoduleContentEditorMode = 'html';
}
// Get current cursor position ( for html editor )
if ( 'tinymce' !== window.SCmoduleContentEditorMode ) {
window.cursorPosition = jQuery( editorArea ).getCursorPosition();
}
viewSettings = {
collection: FusionPageBuilderElements,
view: this,
targetCid: editorCid
},
view = new FusionPageBuilder.GeneratorElementsView( viewSettings );
jQuery( view.render().el ).dialog( {
title: 'Select Element',
draggable: false,
modal: true,
resizable: false,
dialogClass: 'fusion-builder-dialog fusion-builder-large-library-dialog fusion-builder-element-library-dialog',
open: function( event, ui ) { // jshint ignore: line
window.FusionApp.dialog.resizeDialog();
},
close: function( event, ui ) { // jshint ignore: line
view.removeView();
}
} );
}
// Helper function to check the cursor position of text editor content field before the shortcode generator is opened
( function() {
jQuery.fn.getCursorPosition = function() {
var el = jQuery( this ).get( 0 ),
pos = 0,
Sel,
SelLength;
if ( 'selectionStart' in el ) {
pos = el.selectionStart;
} else if ( 'selection' in document ) {
el.focus();
Sel = document.selection.createRange();
SelLength = document.selection.createRange().text.length;
Sel.moveStart( 'character', -el.value.length );
pos = Sel.text.length - SelLength;
}
return pos;
};
}( jQuery ) );
;/* global FusionPageBuilderApp, FusionApp, fusionBuilderText, FusionEvents */
var FusionPageBuilder = FusionPageBuilder || {};
( function() {
// Builder Builder History
FusionPageBuilder.BuilderHistory = window.wp.Backbone.View.extend( {
template: FusionPageBuilder.template( jQuery( '#fusion-builder-front-end-history' ).html() ),
className: 'fusion-builder-history-list submenu-trigger-target',
tagName: 'ul',
/**
* Init.
*
* @since 2.0.0
* @param {Object} data - The data.
* @return {void}
*/
initialize: function() {
var data = FusionApp.data;
this.fusionCommands = new Array( '[]' );
this.fusionCommandsStates = new Array( '[]' ); // History states
this.maxSteps = 25; // Maximum steps allowed/saved
this.currStep = 1; // Current Index of step
this.allElements = data.postDetails.post_content;
this.fusionHistoryState = '';
this.tracking = 'on';
this.trackingPaused = 'off';
this.unsavedStep = 1; // Unsaved steps.
// Set initial history step
this.fusionCommands[ this.currStep ] = { allElements: data.postDetails.post_content };
this.fusionCommandsStates[ this.currStep ] = fusionBuilderText.empty;
this.listenTo( FusionEvents, 'fusion-history-pause-tracking', this.pauseTracking );
this.listenTo( FusionEvents, 'fusion-history-resume-tracking', this.resumeTracking );
this.listenTo( FusionEvents, 'fusion-history-save-step', this.saveHistoryStep );
this.listenTo( FusionEvents, 'fusion-history-turn-on-tracking', this.turnOnTracking );
this.listenTo( FusionEvents, 'fusion-history-turn-off-tracking', this.turnOffTracking );
this.listenTo( FusionEvents, 'fusion-history-go-to-step', this.historyStep );
this.listenTo( FusionEvents, 'fusion-history-clear', this.clearEditor );
this.listenTo( FusionEvents, 'fusion-history-capture-editor', this.captureEditor );
this.listenTo( FusionEvents, 'fusion-history-undo', this.doUndo );
this.listenTo( FusionEvents, 'fusion-history-redo', this.doRedo );
this.listenTo( FusionEvents, 'fusion-builder-reset', this.resetStates );
this.listenTo( FusionEvents, 'fusion-element-removed', this.resetStates );
},
resetStates: function( cid ) {
var self = this;
if ( 'object' === typeof this.fusionCommands ) {
_.each( this.fusionCommands, function( state, index ) {
if ( 'undefined' === typeof cid || ! cid || ( 'param' === state.type && 'undefined' !== typeof state.cid && cid === state.cid ) ) {
self.fusionCommands[ index ] = { allElements: state.allElements };
}
} );
}
},
/**
* Renders the view.
*
* @since 2.0.0
* @return {Object} this
*/
render: function() {
var self = this;
this.$el.html( this.template( { steps: this.fusionCommandsStates, currentStep: this.currStep } ) );
this.$el.attr( 'aria-expanded', false );
this.$el.find( 'li' ).on( 'click', function( event ) {
if ( event ) {
event.preventDefault();
}
self.historyStep( event );
} );
this.updateUI();
return this;
},
/**
* Saves a step in the history.
*
* @since 2.0.0
* @param {string} text - The text to be displayed in the history log.
* @return {void}
*/
saveHistoryStep: function( text, state ) {
this.fusionHistoryState = text;
this.turnOnTracking();
this.captureEditor( state );
this.turnOffTracking();
},
/**
* Captures the editor (used in front-end.js)
*
* @since 2.0.0
* @return {void}
*/
captureEditor: function( state ) {
if ( 'object' !== typeof state ) {
state = {};
}
if ( 'undefined' === typeof FusionPageBuilderApp ) {
return;
}
FusionPageBuilderApp.builderToShortcodes();
if ( this.isTrackingOn() && ! this.isTrackingPaused() ) {
// If reached limit
if ( this.currStep == this.maxSteps ) {
// Remove first index
this.fusionCommands.shift();
this.fusionCommandsStates.shift();
} else {
// Else increment index
this.currStep += 1;
this.unsavedStep += 1;
}
// If we are not at the end of the states, we need to wipe those ahead.
if ( this.currStep !== this.fusionCommands.length ) {
this.fusionCommandsStates.length = this.currStep;
this.fusionCommands.length = this.currStep;
}
// Get content
this.allElements = FusionApp.data.postDetails.post_content;
// Add all elements as fallback method.
state.allElements = this.allElements;
// Add editor data to Array
this.fusionCommands[ this.currStep ] = state;
// Add history state
this.fusionCommandsStates[ this.currStep ] = this.fusionHistoryState;
FusionApp.contentChange( 'page', 'builder-content' );
// Update buttons
this.fusionHistoryState = '';
this.render();
}
},
/**
* Turn history tracking ON.
*
* @since 2.0.0
* @return {void}
*/
turnOnTracking: function() {
this.tracking = 'on';
},
/**
* Turn history tracking OFF.
*
* @since 2.0.0
* @return {void}
*/
turnOffTracking: function() {
this.tracking = 'off';
},
/**
* Turn history tracking ON.
*
* @since 2.0.0
* @return {void}
*/
pauseTracking: function() {
this.trackingPaused = 'on';
},
/**
* Turn history tracking OFF.
*
* @since 2.0.0
* @return {void}
*/
resumeTracking: function() {
this.trackingPaused = 'off';
},
canApplyStep: function( historyStep ) {
if ( 'object' !== typeof historyStep || 'undefined' === typeof historyStep.type ) {
return false;
}
if ( 'param' === historyStep.type || 'price-param' === historyStep.type || 'pricefooter-param' === historyStep.type || 'pricefeatures-param' === historyStep.type ) {
return true;
}
return false;
},
canApplySteps: function( stepIndex ) {
var self = this,
redo = stepIndex < this.currStep ? false : true,
steps = [],
canApply = true;
if ( ! redo ) {
steps = this.fusionCommands.slice( stepIndex + 1, this.currStep + 1 );
} else {
steps = this.fusionCommands.slice( this.currStep + 1, stepIndex + 1 );
}
_.each( steps, function( step ) {
if ( ! self.canApplyStep( step ) ) {
canApply = false;
}
} );
return canApply;
},
applySteps: function( stepIndex ) {
var self = this,
redo = stepIndex < this.currStep ? false : true,
steps = [];
if ( ! redo ) {
steps = this.fusionCommands.slice( stepIndex + 1, this.currStep + 1 ).reverse();
} else {
steps = this.fusionCommands.slice( this.currStep + 1, stepIndex + 1 );
}
_.each( steps, function( step ) {
self.applyStep( step, redo );
} );
},
applyStep: function( historyStep, redo ) {
var elementView,
params, // eslint-disable-line no-unused-vars
columnView;
redo = 'undefined' === typeof redo ? false : redo;
switch ( historyStep.type ) {
case 'param':
elementView = window.FusionPageBuilderViewManager.getView( historyStep.cid );
if ( elementView ) {
params = elementView.model.get( 'params' ); // eslint-disable-line no-unused-vars
// If undo, set new value to step so redo can use it.
if ( ! redo ) {
elementView.historyUpdateParam( historyStep.param, historyStep.oldValue );
FusionEvents.trigger( 'fusion-param-changed', historyStep.param, historyStep.oldValue );
FusionEvents.trigger( 'fusion-param-changed-' + historyStep.cid, historyStep.param, historyStep.oldValue );
} else {
elementView.historyUpdateParam( historyStep.param, historyStep.newValue );
FusionEvents.trigger( 'fusion-param-changed', historyStep.param, historyStep.newValue );
FusionEvents.trigger( 'fusion-param-changed-' + historyStep.cid, historyStep.param, historyStep.newValue );
}
}
break;
case 'price-param':
elementView = window.FusionPageBuilderViewManager.getView( historyStep.cid );
if ( elementView ) {
// If undo, set new value to step so redo can use it.
if ( ! redo ) {
elementView.updatePricingTablePrice( historyStep.param, historyStep.oldValue );
FusionEvents.trigger( 'fusion-param-changed', historyStep.param, historyStep.oldValue );
FusionEvents.trigger( 'fusion-param-changed-' + historyStep.cid, historyStep.param, historyStep.oldValue );
} else {
elementView.updatePricingTablePrice( historyStep.param, historyStep.newValue );
FusionEvents.trigger( 'fusion-param-changed', historyStep.param, historyStep.newValue );
FusionEvents.trigger( 'fusion-param-changed-' + historyStep.cid, historyStep.param, historyStep.newValue );
}
}
break;
case 'pricefooter-param':
elementView = window.FusionPageBuilderViewManager.getView( historyStep.cid );
if ( elementView ) {
// If undo, set new value to step so redo can use it.
if ( ! redo ) {
elementView.updatePricingTableFooter( historyStep.oldValue );
FusionEvents.trigger( 'fusion-param-changed', 'footer_content', historyStep.oldValue );
FusionEvents.trigger( 'fusion-param-changed-' + historyStep.cid, 'footer_content', historyStep.oldValue );
} else {
elementView.updatePricingTableFooter( historyStep.newValue );
FusionEvents.trigger( 'fusion-param-changed', 'footer_content', historyStep.newValue );
FusionEvents.trigger( 'fusion-param-changed-' + historyStep.cid, 'footer_content', historyStep.newValue );
}
}
break;
case 'pricefeatures-param':
elementView = window.FusionPageBuilderViewManager.getView( historyStep.cid );
if ( elementView ) {
// If undo, set new value to step so redo can use it.
if ( ! redo ) {
elementView.updatePricingTableFeatures( historyStep.oldValue );
FusionEvents.trigger( 'fusion-param-changed', 'footer_content', historyStep.oldValue );
FusionEvents.trigger( 'fusion-param-changed-' + historyStep.cid, 'feature_rows', historyStep.oldValue );
} else {
elementView.updatePricingTableFeatures( historyStep.newValue );
FusionEvents.trigger( 'fusion-param-changed', 'footer_content', historyStep.newValue );
FusionEvents.trigger( 'fusion-param-changed-' + historyStep.cid, 'feature_rows', historyStep.newValue );
}
}
break;
case 'add-element':
if ( redo ) {
FusionPageBuilderApp.collection.add( historyStep.model );
} else {
elementView = window.FusionPageBuilderViewManager.getView( historyStep.model.cid );
if ( elementView ) {
elementView.removeElement();
}
}
break;
case 'remove-element':
if ( redo ) {
elementView = window.FusionPageBuilderViewManager.getView( historyStep.model.cid );
if ( elementView ) {
elementView.removeElement();
}
} else {
FusionPageBuilderApp.collection.add( historyStep.model );
}
break;
case 'move-element':
elementView = window.FusionPageBuilderViewManager.getView( historyStep.cid );
// Need to ignore itself.
elementView.$el.addClass( 'ignore-me' );
if ( redo ) {
columnView = window.FusionPageBuilderViewManager.getView( historyStep.newParent );
if ( elementView && columnView ) {
columnView.$el.find( '.fusion-builder-column-content' ).first().find( '> span, > div' ).not( '.ignore-me' ).eq( ( historyStep.newIndex - 1 ) ).after( elementView.$el );
FusionPageBuilderApp.onDropCollectionUpdate( elementView.model, historyStep.newIndex, historyStep.newParent );
}
} else {
columnView = window.FusionPageBuilderViewManager.getView( historyStep.oldParent );
if ( elementView && columnView ) {
columnView.$el.find( '.fusion-builder-column-content' ).first().find( '> span, > div' ).not( '.ignore-me' ).eq( ( historyStep.oldIndex - 1 ) ).after( elementView.$el );
FusionPageBuilderApp.onDropCollectionUpdate( elementView.model, historyStep.oldIndex, historyStep.oldParent );
}
}
elementView.$el.removeClass( 'ignore-me' );
break;
}
},
updateActiveStyling: function() {
FusionApp.builderToolbarView.$el.find( '.fusion-builder-history-list li' ).removeClass( 'fusion-history-active-state' );
FusionApp.builderToolbarView.$el.find( '.fusion-builder-history-list' ).find( '[data-state-id="' + this.currStep + '"]' ).addClass( 'fusion-history-active-state' );
},
fullContentReplace: function( data ) {
this.resetStates();
FusionPageBuilderApp.clearBuilderLayout();
FusionPageBuilderApp.$el.find( '.fusion_builder_container' ).remove();
// Try to make the shortcode if the content does not contain them.
if ( ! FusionApp.data.is_fusion_element || 'mega_menus' === FusionApp.data.fusion_element_type ) {
data = FusionPageBuilderApp.validateContent( data );
}
// Reset models with new elements
FusionPageBuilderApp.createBuilderLayout( data );
},
/**
* Undo last step in history.
* Saves the undone step so that we may redo later if needed.
*
* @since 2.0.0
* @param {Object} event - The event.
* @return {void}
*/
doUndo: function( event ) {
var undoData,
historyStep = {};
if ( event ) {
event.preventDefault();
}
// Turn off tracking first, so these actions are not captured
if ( this.hasUndo() ) { // If no data or end of stack and nothing to undo
// Close opened nested cols to make sure UI works after history change.
this.closeNestedCols();
this.turnOffTracking();
// Data to undo
historyStep = this.fusionCommands[ this.currStep ];
if ( this.canApplyStep( historyStep ) ) {
this.applyStep( historyStep, false );
this.currStep -= 1;
} else {
this.currStep -= 1;
historyStep = this.fusionCommands[ this.currStep ];
undoData = 'object' === typeof historyStep ? historyStep.allElements : false;
if ( undoData && '[]' !== undoData ) {
this.fullContentReplace( undoData );
}
}
this.updateActiveStyling();
}
},
/**
* Redo last step.
*
* @since 2.0.0
* @param {Object} event - The event.
* @return {void}
*/
doRedo: function( event ) {
var redoData;
if ( event ) {
event.preventDefault();
}
if ( this.hasRedo() ) { // If not at end and nothing to redo
// Close opened nested cols to make sure UI works after history change.
this.closeNestedCols();
// Turn off tracking, so these actions are not tracked
this.turnOffTracking();
// Move index
this.currStep += 1;
window.historyStep = this.fusionCommands[ this.currStep ];
redoData = 'object' === typeof window.historyStep ? window.historyStep.allElements : false;
if ( this.canApplyStep( window.historyStep ) ) {
this.applyStep( window.historyStep, true );
} else if ( redoData && '[]' !== redoData ) {
this.fullContentReplace( redoData );
}
this.updateActiveStyling();
}
},
/**
* Go to a step.
*
* @since 2.0.0
* @param {string|number} step - The step.
* @param {Object} event - The event.
* @return {void}
*/
historyStep: function( event ) {
var step,
stepData;
if ( event ) {
event.preventDefault();
}
// Close opened nested cols to make sure UI works after history change.
this.closeNestedCols();
step = jQuery( event.currentTarget ).data( 'state-id' );
// Turn off tracking, so these actions are not tracked
this.turnOffTracking();
if ( this.canApplySteps( step ) ) {
this.applySteps( step );
this.currStep = step;
} else {
this.currStep = step;
stepData = 'object' === typeof this.fusionCommands[ this.currStep ] ? this.fusionCommands[ this.currStep ].allElements : false;
if ( stepData && '[]' !== stepData ) {
this.fullContentReplace( stepData );
}
}
this.updateActiveStyling();
},
/**
* Are we currently tracking history?
*
* @since 2.0.0
* @return {boolean}
*/
isTrackingOn: function() {
return 'on' === this.tracking;
},
/**
* Is tracking paused currently?
*
* @since 2.0.0
* @return {boolean}
*/
isTrackingPaused: function() {
return 'on' === this.trackingPaused;
},
/**
* Log commands in the console as JSON.
*
* @since 2.0.0
* @return {void}
*/
logStacks: function() {
console.log( JSON.parse( this.fusionCommands ) );
},
/**
* Clear the editor.
*
* @since 2.0.0
* @return {void}
*/
clearEditor: function() {
this.fusionCommands = new Array( '[]' );
this.fusionCommandsStates = new Array( '[]' );
this.currStep = 1;
this.unsavedStep = 1;
this.fusionHistoryState = '';
this.fusionCommands[ this.currStep ] = { allElements: FusionApp.data.postDetails.post_content };
this.fusionCommandsStates[ this.currStep ] = fusionBuilderText.empty;
this.render();
},
/**
* Do we have an undo? Checks if the current step is the 1st one.
*
* @since 2.0.0
* @return {boolean}
*/
hasUndo: function() {
return 1 !== this.currStep;
},
/**
* Do we have a redo? Checks if a step greater than current one exists.
*
* @since 2.0.0
* @return {boolean}
*/
hasRedo: function() {
return this.currStep < ( this.fusionCommands.length - 1 );
},
/**
* Get the array of steps/fusionCommands.
*
* @since 2.0.0
* @return {Array}
*/
getCommands: function() {
return this.fusionCommands;
},
/**
* Update the undo/redo/history buttons.
*
* @since 2.0.0
* @return {void}
*/
updateUI: function() {
if ( 1 < this.unsavedStep ) {
FusionApp.builderToolbarView.$el.find( '#fusion-builder-toolbar-history-menu' ).attr( 'data-has-unsaved', true );
} else {
FusionApp.builderToolbarView.$el.find( '#fusion-builder-toolbar-history-menu' ).attr( 'data-has-unsaved', false );
}
this.updateActiveStyling();
},
/**
* Close nested cols.
*
* @since 2.2
* @return {void}
*/
closeNestedCols: function() {
var activeNestedCols = FusionPageBuilderApp.$el.find( '.fusion-nested-columns.editing' );
if ( activeNestedCols.length ) {
activeNestedCols.find( '.fusion-builder-cancel-row' ).trigger( 'click' );
}
}
} );
}( jQuery ) );
;/* global FusionPageBuilderApp, fusionAppConfig, FusionApp, FusionEvents, fusionBuilderText */
var FusionPageBuilder = FusionPageBuilder || {};
( function() {
// Builder Toolbar
FusionPageBuilder.BuilderToolbar = window.wp.Backbone.View.extend( {
template: FusionPageBuilder.template( jQuery( '#fusion-builder-front-end-toolbar' ).html() ),
className: 'fusion-toolbar-nav fb',
tagName: 'ul',
events: {
'click .fusion-builder-clear-layout': 'clearLayout',
'click .fusion-builder-open-library': 'openLibrary',
'click .fusion-builder-save-template': 'openLibrary',
'click #fusion-builder-toolbar-new-post .add-new': 'newPost',
'click .fusion-builder-preferences': 'openPreferences',
'click #fusion-builder-toolbar-history-menu': 'preventDefault',
'click .fusion-preview-only-link': 'generatePreview'
},
initialize: function() {
this.builderHistory = new FusionPageBuilder.BuilderHistory();
this.listenTo( FusionEvents, 'fusion-post_title-changed', this.updatePreviewTitle );
},
/**
* Renders the view.
*
* @since 2.0.0
* @return {Object} this
*/
render: function() {
this.$el.html( this.template() );
this.$el.find( '.fusion-builder-history-container' ).append( this.builderHistory.render().el );
this.delegateEvents();
return this;
},
/**
* Make sure all the unsaved content is set like on frame refresh, then open page.
*
* @since 2.0.0
* @param {Object} event - The JS event.
* @return {Object} this
*/
generatePreview: function( event ) {
var $element = jQuery( event.currentTarget );
if ( 'undefined' !== typeof event ) {
event.preventDefault();
event.stopPropagation();
}
if ( $element.attr( 'data-disabled' ) ) {
return;
}
$element.attr( 'data-disabled', true );
// Avada Builder
if ( 'undefined' !== typeof FusionPageBuilderApp ) {
FusionPageBuilderApp.builderToShortcodes();
}
// Fusion Panel
if ( this.sidebarView ) {
this.setGoogleFonts();
}
FusionApp.formPost( FusionApp.getAjaxData( 'fusion_app_preview_only' ), false, '_blank' );
$element.removeAttr( 'data-disabled' );
},
/**
* Opens the library.
* Calls the LibraryView and then renders it.
*
* @since 2.0.0
* @param {Object} event - The event.
* @return {void}
*/
openLibrary: function( event ) {
var view,
libraryModel = {
target: jQuery( event.currentTarget ).data( 'target' ),
focus: jQuery( event.currentTarget ).data( 'focus' )
},
viewSettings = {
model: libraryModel
};
if ( 'undefined' !== typeof event ) {
event.preventDefault();
event.stopPropagation();
}
if ( jQuery( '.fusion-builder-dialog' ).length && jQuery( '.fusion-builder-dialog' ).is( ':visible' ) ) {
FusionApp.multipleDialogsNotice();
return;
}
view = new FusionPageBuilder.LibraryView( viewSettings );
view.render();
},
/**
* Clears the layout.
* Calls FusionPageBuilderApp.clearLayout
*
* @since 2.0.0
* @param {Object} event - The event.
* @return {void}
*/
clearLayout: function( event ) {
if ( event ) {
event.preventDefault();
}
FusionApp.confirmationPopup( {
title: fusionBuilderText.are_you_sure,
content: fusionBuilderText.are_you_sure_you_want_to_delete_this_layout,
actions: [
{
label: fusionBuilderText.cancel,
classes: 'cancel',
callback: function() {
FusionApp.confirmationPopup( {
action: 'hide'
} );
}
},
{
label: fusionBuilderText.remove,
classes: 'delete-layout',
callback: function() {
// Close dialogs.
if ( jQuery( '.ui-dialog-content' ).length ) {
jQuery( '.ui-dialog-content' ).dialog( 'close' );
}
FusionEvents.trigger( 'fusion-history-save-step', fusionBuilderText.layout_cleared );
FusionPageBuilderApp.clearLayout( event );
FusionApp.confirmationPopup( {
action: 'hide'
} );
}
}
]
} );
},
/**
* Create a new draft of specific post type.
*
* @since 2.0.0
* @param {Object} event - The event.
* @return {void}
*/
newPost: function( event ) {
var postType = jQuery( event.currentTarget ).data( 'post-type' );
if ( event ) {
event.preventDefault();
}
jQuery.ajax( {
type: 'POST',
url: fusionAppConfig.ajaxurl,
dataType: 'JSON',
data: {
action: 'fusion_create_post',
fusion_load_nonce: fusionAppConfig.fusion_load_nonce,
post_type: postType
}
} )
.done( function( response ) {
FusionApp.checkLink( event, response.permalink );
} );
},
/**
* Renders the FusionPageBuilder.PreferencesView view.
*
* @since 2.0.0
* @param {Object} event - The event.
* @return {void}
*/
openPreferences: function( event ) {
var view;
if ( 'undefined' !== typeof event ) {
event.preventDefault();
event.stopPropagation();
}
if ( jQuery( '.fusion-builder-dialog' ).length && jQuery( '.fusion-builder-dialog' ).is( ':visible' ) ) {
FusionApp.multipleDialogsNotice();
return;
}
view = new FusionPageBuilder.PreferencesView();
view.render();
},
/**
* Prevents default action.
*
* @param {Object} event - The event.
* @return {void}
*/
preventDefault: function( event ) {
event.preventDefault();
},
/**
* Updates the text for the title of the page.
*
* @return {void}
*/
updatePreviewTitle: function() {
this.$el.find( '.fusion-preview-only-link strong' ).html( FusionApp.getPost( 'post_title' ) );
}
} );
}( jQuery ) );
;var FusionPageBuilder = FusionPageBuilder || {};
( function() {
// Builder element model
FusionPageBuilder.Element = Backbone.Model.extend( {
defaults: {
type: 'element'
}
} );
}( jQuery ) );
;var FusionPageBuilder = FusionPageBuilder || {};
( function() {
FusionPageBuilder.ExtraShortcodes = Backbone.Model.extend( {
defaults: {
elementCount: 0,
shortcodes: {}
},
addData: function( content ) {
var self = this,
shortcodes = self.get( 'shortcodes' ),
elementCount = self.get( 'elementCount' );
_.each( content, function( shortcode ) {
shortcode.id = elementCount;
shortcode.matcher = self.convert( shortcode.shortcode );
shortcodes[ elementCount ] = shortcode;
elementCount++;
} );
this.set( { elementCount: elementCount } );
this.set( { shortcodes: shortcodes } );
},
addShortcode: function( shortcode, output, tag ) {
var self = this,
shortcodes = self.get( 'shortcodes' ),
elementCount = self.get( 'elementCount' ),
originalCount = self.get( 'elementCount' );
shortcodes[ elementCount ] = {
shortcode: shortcode,
output: output,
matcher: self.convert( shortcode ),
id: elementCount,
tag: tag
};
elementCount++;
this.set( { elementCount: elementCount } );
this.set( { shortcodes: shortcodes } );
return originalCount;
},
byId: function( id ) {
var shortcodes = this.get( 'shortcodes' );
return shortcodes[ id ];
},
byShortcode: function( content ) {
var shortcodes = this.get( 'shortcodes' ),
$matches = _.findWhere( shortcodes, { shortcode: content } );
if ( 'undefined' === typeof $matches ) {
content = this.convert( content );
$matches = _.findWhere( shortcodes, { matcher: content } );
}
return $matches;
},
byOutput: function( content ) {
var shortcodes = this.get( 'shortcodes' );
return _.findWhere( shortcodes, { ouput: content } );
},
getAll: function() {
return this.get( 'shortcodes' );
},
convert: function( content ) {
// Clean up any parts which can be ignored for sake of matching.
content = content.replace( / /g, '' );
content = content.replace( /\r?\n|\r/g, '' );
content = content.replace( /(
]+?>|
|<\/p>)/g, '' );
content = content.replace( /(
]+?>|
|<\/br>)/g, '' );
content = content.replace( /\[fusion_text\]\[\/fusion_text\]/g, '' );
return content.trim();
}
} );
}( jQuery ) );
;/* global FusionEvents, FusionApp, fusionBuilderText */
var FusionPageBuilder = FusionPageBuilder || {};
( function() {
FusionPageBuilder.DynamicValues = Backbone.Model.extend( {
defaults: {
values: {},
options: {},
orderedParams: false
},
getOrderedParams: function() {
var params = this.get( 'orderedParams' ),
options = this.getOptions();
if ( ! params ) {
params = {};
_.each( options, function( object, id ) {
var group,
groupText;
if ( 'object' !== typeof object ) {
return;
}
group = object.group;
groupText = group;
if ( 'string' !== typeof object.group ) {
group = 'other';
groupText = fusionBuilderText.other;
}
group = group.replace( /\s+/g, '_' ).toLowerCase();
if ( 'object' !== typeof params[ group ] ) {
params[ group ] = {
label: '',
params: {}
};
}
params[ group ].label = groupText;
params[ group ].params[ id ] = object;
} );
}
return params;
},
addData: function( data, options ) {
this.set( 'values', data );
this.set( 'options', options );
},
getOptions: function() {
var options = this.get( 'options' );
return jQuery.extend( true, {}, options );
},
getOption: function( param ) {
var options = this.getOptions();
return 'undefined' !== typeof options[ param ] ? options[ param ] : false;
},
getAll: function() {
var values = this.get( 'values' );
return jQuery.extend( true, {}, values );
},
getValue: function( args ) {
var values = this.getAll(),
id = args.data,
postId = FusionApp.getDynamicPost( 'post_id' ),
idValues = false,
match = false;
if ( 'undefined' !== typeof values[ postId ] ) {
idValues = 'object' === typeof values[ postId ][ id ] ? values[ postId ][ id ] : false;
}
// No initial match, fetch it.
if ( ! idValues ) {
return this.fetchValue( id, args );
}
// Check each value object with same ID.
match = this.findMatch( idValues, args );
// We found a matching object, then return its value.
if ( match ) {
return match.value;
}
// No match, fetch.
return this.fetchValue( id, args );
},
findMatch: function( idValues, args, idWanted ) {
var match = false;
idWanted = 'undefined' === typeof idWanted ? false : idWanted;
_.each( idValues, function( idValue, idCount ) {
var argsMatch = true;
// Already found a match, just return early.
if ( match ) {
return true;
}
// Value object has no args, then set match and return.
if ( 'undefined' === typeof idValue.args ) {
match = idWanted ? idCount : idValue;
return true;
}
// We do have args, check that each value matches.
if ( 'object' === typeof idValue.args ) {
_.each( idValue.args, function( argValue, argId ) {
if ( 'undefined' === typeof args[ argId ] || 'before' === argId || 'after' === argId || 'fallback' === argId ) {
return true;
}
if ( args[ argId ] !== argValue ) {
argsMatch = false;
}
} );
if ( argsMatch ) {
match = idWanted ? idCount : idValue;
}
}
} );
return match;
},
fetchValue: function( id, args ) {
var options = this.getOptions(),
param = 'object' === typeof options && 'object' === typeof options[ id ] ? options[ id ] : false,
callback = param && 'undefined' !== typeof param.callback ? param.callback : false,
callbackFunction = callback && 'string' === typeof callback[ 'function' ] ? callback[ 'function' ] : false,
callbackExists = callbackFunction && 'function' === typeof FusionApp.callback[ callbackFunction ] ? true : false,
callbackAjax = callbackExists && 'undefined' !== typeof callback.ajax ? callback.ajax : false,
dynamicPost,
value;
// If no callback found, use default ajax one.
if ( ! callbackExists ) {
callbackFunction = 'defaultDynamicCallback';
callbackAjax = true;
}
if ( ! param ) {
this.setValue( args, false );
return false;
}
// Return default (dummy) value if template post is set as target post.
dynamicPost = 'fusion_tb_section' === FusionApp.data.postDetails.post_type || 'post_cards' === FusionApp.data.template_category;
if ( true === FusionApp.data.is_singular && dynamicPost && -99 === FusionApp.getDynamicPost( 'post_id' ) && 'undefined' !== typeof param[ 'default' ] ) {
return param[ 'default' ];
}
// If ajax callback should be run when template is edited.
if ( true === FusionApp.data.is_singular && dynamicPost && 'undefined' !== typeof param.ajax_on_template && true === param.ajax_on_template ) {
return FusionApp.callback.defaultDynamicCallback( args );
}
if ( callbackAjax ) {
return FusionApp.callback[ callbackFunction ]( args );
}
value = FusionApp.callback[ callbackFunction ]( args );
this.setValue( args, value );
return value;
},
setValue: function( args, value ) {
var values = this.getAll(),
id = args.data,
postId = FusionApp.getDynamicPost( 'post_id' ),
existing = {},
matchId = false,
newData = {
args: jQuery.extend( true, {}, args ),
value: value
};
if ( 'object' !== typeof values[ postId ] ) {
values[ postId ] = [];
}
existing = jQuery.extend( true, {}, values[ postId ][ id ] );
if ( 'object' !== typeof values[ postId ][ id ] ) {
values[ postId ][ id ] = [];
} else if ( 'function' !== typeof values[ postId ][ id ].push ) {
values[ postId ][ id ] = [ existing[ 0 ] ];
}
matchId = this.findMatch( values[ postId ][ id ], args, true );
if ( ! matchId ) {
values[ postId ][ id ].push( newData );
} else {
values[ postId ][ id ][ matchId ] = newData;
}
this.set( 'values', values );
// ReRender the element. Perhaps via event using id.
FusionEvents.trigger( 'fusion-dynamic-data-value', id );
},
removeValue: function( id ) {
var values = this.getAll(),
postId = FusionApp.getDynamicPost( 'post_id' );
if ( 'object' === typeof values[ postId ][ id ] ) {
delete values[ postId ][ id ];
}
this.set( 'values', values );
}
} );
}( jQuery ) );
;/* global FusionEvents, FusionPageBuilderApp, fusionAllElements, fusionBuilderText */
var FusionPageBuilder = FusionPageBuilder || {};
( function() {
FusionPageBuilder.DynamicParams = Backbone.Model.extend( {
defaults: {
params: {},
elementView: false,
listeners: []
},
initialize: function() {
this._historyPush = _.debounce( _.bind( this.historyPush, this ), 300 );
},
setData: function( data ) {
if ( 'object' === typeof data ) {
this.set( 'params', data );
this.setListeners();
}
},
getAll: function() {
var params = this.get( 'params' );
return jQuery.extend( true, {}, params );
},
setListeners: function() {
var params = this.getAll(),
self = this;
_.each( params, function( param ) {
var option = FusionPageBuilderApp.dynamicValues.getOption( param.data );
if ( option && 'object' === typeof option.listeners ) {
_.each( option.listeners, function( listenerData, listenerId ) {
self.setListener( listenerId, listenerData, param );
} );
}
} );
},
setListener: function( id, data, args ) {
var location = 'undefined' !== typeof data.location ? data.location : false,
self = this,
cid = this.cid,
listeners = this.get( 'listeners' );
if ( ! location ) {
return;
}
switch ( location ) {
case 'postDetails':
FusionEvents.on( 'fusion-' + id + '-changed', function() {
FusionPageBuilderApp.dynamicValues.removeValue( args.data );
self.getValueAndUpdate( args );
}, cid );
listeners.push( 'fusion-' + id + '-changed' );
self.set( 'listeners', listeners );
break;
case 'postMeta':
FusionEvents.on( 'fusion-po-' + id + '-changed', function() {
FusionPageBuilderApp.dynamicValues.removeValue( args.data );
self.getValueAndUpdate( args );
}, cid );
listeners.push( 'fusion-po-' + id + '-changed' );
self.set( 'listeners', listeners );
break;
}
},
hasDynamicParam: function( param ) {
var params = this.getAll();
if ( 'undefined' !== typeof params[ param ] ) {
return true;
}
return false;
},
getParamValue: function( data ) {
var value = FusionPageBuilderApp.dynamicValues.getValue( data ),
beforeString = 'string' === typeof data.before ? data.before : '',
afterString = 'string' === typeof data.after ? data.after : '',
fallback = 'undefined' !== typeof data.fallback ? data.fallback : false,
hasValue = 'undefined' !== typeof value && null !== value && false !== value && '' !== value,
elementView = this.get( 'elementView' );
if ( ! hasValue && fallback ) {
return fallback;
}
if ( ! hasValue ) {
return undefined;
}
if ( 'object' === typeof value && 'function' === typeof value.then ) {
value.then( function() {
elementView.reRender();
} );
return false;
} else if ( 'string' !== typeof value ) {
return value;
}
return beforeString + value + afterString;
},
addParam: function( param, data ) {
var self = this,
params = this.getAll(),
options = FusionPageBuilderApp.dynamicValues.getOptions(),
option = false;
if ( 'object' !== typeof data ) {
data = {
data: data
};
}
// // Set default values.
_.each( options[ data.data ].fields, function( field, key ) {
if ( 'undefined' === typeof data[ key ] ) {
if ( 'undefined' !== typeof field[ 'default' ] ) {
data[ key ] = field[ 'default' ];
} else if ( 'undefined' !== typeof field.value ) {
data[ key ] = field.value;
}
}
} );
params[ param ] = data;
option = FusionPageBuilderApp.dynamicValues.getOption( data.data );
if ( option && 'object' === typeof option.listeners ) {
_.each( option.listeners, function( listenerData, listenerId ) {
self.setListener( listenerId, listenerData, param );
} );
}
this.set( 'params', params );
this.saveData();
FusionEvents.trigger( 'fusion-dynamic-data-added', param, this.cid );
this.getValueAndUpdate( params[ param ] );
},
updateParam: function( param, subParam, value ) {
var params = this.getAll();
if ( 'object' === typeof params[ param ] ) {
params[ param ][ subParam ] = value;
this.set( 'params', params );
FusionEvents.trigger( 'fusion-dynamic-data-updated', param );
this.saveData();
this.getValueAndUpdate( params[ param ] );
}
},
getValueAndUpdate: function( args ) {
var elementView = this.get( 'elementView' ),
valueReturn = FusionPageBuilderApp.dynamicValues.getValue( args, elementView );
if ( valueReturn && 'object' === typeof valueReturn && 'function' === typeof valueReturn.then ) {
elementView.addLoadingOverlay();
valueReturn.then(
function() {
elementView.reRender();
},
function() {
elementView.removeLoadingOverlay();
}
);
} else {
elementView.reRender();
}
},
updateListeners: function() {
var cid = this.cid;
_.each( this.get( 'listeners' ), function( listener ) {
FusionEvents.off( listener, null, cid );
} );
this.setListeners();
},
removeParam: function( param ) {
var params = this.getAll(),
elementView = this.get( 'elementView' );
delete params[ param ];
this.set( 'params', params );
this.updateListeners();
this.saveData();
elementView.reRender();
FusionEvents.trigger( 'fusion-dynamic-data-removed', param );
},
historyPush: function() {
var elementView = this.get( 'elementView' ),
elementMap = fusionAllElements[ elementView.model.get( 'element_type' ) ];
// TODO: refactor history.
FusionEvents.trigger( 'fusion-history-save-step', fusionBuilderText.edited + ' ' + elementMap.name + ' - ' + fusionBuilderText.dynamic_data );
},
saveData: function() {
var elementView = this.get( 'elementView' ),
elementParams = elementView.model.get( 'params' ),
originalValue = elementParams.dynamic_params;
elementParams.dynamic_params = FusionPageBuilderApp.base64Encode( JSON.stringify( this.getAll() ) );
elementView.model.set( 'params', elementParams );
// Make sure that parent is updated, usually done in base view changeParam.
if ( 'function' === typeof elementView.forceUpdateParent ) {
elementView.forceUpdateParent();
}
if ( originalValue !== elementParams.dynamic_params ) {
this._historyPush();
}
}
} );
}( jQuery ) );
;/* global FusionApp, FusionEvents */
var FusionPageBuilder = FusionPageBuilder || {};
( function() {
FusionPageBuilder.FormStyles = Backbone.Model.extend( {
initialize: function() {
this.baseSelector = '.fusion-form.fusion-form-form-wrapper';
this.dynamic_css = {};
this.formData = FusionApp.data.postMeta._fusion;
this.addStyleVariables();
this.listenTo( FusionEvents, 'fusion-form-styles', this.addStyleVariables );
this.listenTo( FusionEvents, 'fusion-builder-loaded', this.addStyleVariables );
this.listenTo( FusionEvents, 'fusion-preview-refreshed', this.updateFormData );
},
updateFormData: function() {
this.formData = FusionApp.data.postMeta._fusion;
},
isDefault: function( param, subset ) {
if ( 'string' === typeof subset ) {
return 'undefined' === typeof this.formData[ param ] || 'undefined' === typeof this.formData[ param ][ subset ] || '' === this.formData[ param ][ subset ];
}
return 'undefined' === typeof this.formData[ param ] || '' === this.formData[ param ];
},
/**
* Adds style variables.
*
* @since 3.9
* @return {String}
*/
addStyleVariables: function() {
var customVars = [],
cssVarsOptions = [],
styles;
if ( 'undefined' !== typeof this.formData.tooltip_text_color && '' !== this.formData.tooltip_text_color ) {
customVars.tooltip_text_color = this.formData.tooltip_text_color;
}
if ( 'undefined' !== typeof this.formData.tooltip_background_color && '' !== this.formData.tooltip_background_color ) {
customVars.tooltip_background_color = this.formData.tooltip_background_color;
}
if ( ! this.isDefault( 'field_margin', 'top' ) ) {
customVars.field_margin_top = _.fusionGetValueWithUnit( this.formData.field_margin.top );
}
if ( ! this.isDefault( 'field_margin', 'bottom' ) ) {
customVars.field_margin_bottom = _.fusionGetValueWithUnit( this.formData.field_margin.bottom );
}
if ( ! this.isDefault( 'form_input_height' ) ) {
customVars.form_input_height = _.fusionGetValueWithUnit( this.formData.form_input_height );
}
if ( ! this.isDefault( 'form_bg_color' ) ) {
customVars.form_bg_color = this.formData.form_bg_color;
}
if ( ! this.isDefault( 'label_font_size' ) ) {
customVars.label_font_size = _.fusionGetValueWithUnit( this.formData.label_font_size );
}
if ( ! this.isDefault( 'form_font_size' ) ) {
customVars.form_font_size = _.fusionGetValueWithUnit( this.formData.form_font_size );
}
if ( 'undefined' !== typeof this.formData.form_placeholder_color && '' !== this.formData.form_placeholder_color ) {
customVars.form_placeholder_color = this.formData.form_placeholder_color;
} else if ( ! this.isDefault( 'form_text_color' ) ) {
customVars.form_placeholder_color = jQuery.AWB_Color( this.formData.form_text_color ).alpha( 0.5 ).toRgbaString();
}
if ( ! this.isDefault( 'form_text_color' ) ) {
customVars.form_text_color = this.formData.form_text_color;
}
if ( ! this.isDefault( 'form_label_color' ) ) {
customVars.form_label_color = this.formData.form_label_color;
}
if ( ! this.isDefault( 'form_border_width', 'top' ) ) {
customVars.form_border_width_top = _.fusionGetValueWithUnit( this.formData.form_border_width.top, 'px' );
}
if ( ! this.isDefault( 'form_border_width', 'bottom' ) ) {
customVars.form_border_width_bottom = _.fusionGetValueWithUnit( this.formData.form_border_width.bottom, 'px' );
}
if ( ! this.isDefault( 'form_border_width', 'right' ) ) {
customVars.form_border_width_right = _.fusionGetValueWithUnit( this.formData.form_border_width.right, 'px' );
}
if ( ! this.isDefault( 'form_border_width', 'left' ) ) {
customVars.form_border_width_left = _.fusionGetValueWithUnit( this.formData.form_border_width.left, 'px' );
}
if ( ! this.isDefault( 'form_border_color' ) ) {
customVars.form_border_color = this.formData.form_border_color;
}
if ( ! this.isDefault( 'form_focus_border_color' ) ) {
customVars.form_focus_border_color = this.formData.form_focus_border_color;
customVars.form_focus_border_hover_color = jQuery.AWB_Color( this.formData.form_focus_border_color ).alpha( 0.5 ).toRgbaString();
}
if ( ! this.isDefault( 'form_border_radius' ) ) {
customVars.form_border_radius = _.fusionGetValueWithUnit( this.formData.form_border_radius, 'px' );
}
if ( ! this.isDefault( 'form_border_width', 'bottom' ) || !this.isDefault( 'form_border_width', 'top' ) ) {
customVars.icon_alignment_top = this.isDefault( 'form_border_width', 'top' ) ? 'var(--form_border_width-top)' : _.fusionGetValueWithUnit( this.formData.form_border_width.top, 'px' );
customVars.icon_alignment_bottom = this.isDefault( 'form_border_width', 'bottom' ) ? 'var(--form_border_width-bottom)' : _.fusionGetValueWithUnit( this.formData.form_border_width.bottom, 'px' );
customVars.icon_alignment_font_size = this.isDefault( 'form_font_size' ) ? '1em' : this.formData.form_font_size;
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).find( '.fusion-form-form-wrapper' ).addClass( 'has-icon-alignment' );
} else {
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).find( '.fusion-form-form-wrapper' ).removeClass( 'has-icon-alignment' );
}
if ( 'undefined' !== typeof this.formData.required_field_symbol_decoration && 'no' === this.formData.required_field_symbol_decoration ) {
customVars.required_field_symbol_deco = 'none';
}
cssVarsOptions.margin_top = { 'callback': _.fusionGetValueWithUnit };
cssVarsOptions.margin_right = { 'callback': _.fusionGetValueWithUnit };
cssVarsOptions.margin_bottom = { 'callback': _.fusionGetValueWithUnit };
cssVarsOptions.margin_left = { 'callback': _.fusionGetValueWithUnit };
styles = this.getCssVarsForOptions( cssVarsOptions ) + this.getCustomCssVars( customVars );
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).find( '.fusion-form-form-wrapper' ).attr( 'style', styles );
},
/**
* Get a string with each of the option as a CSS variable, if the option is not default.
*
* @since 3.9
* @param {array} options The array with the options ids.
* @return {string}
*/
getCssVarsForOptions( options ) {
var css = '',
varName,
value,
callback_args,
key;
for ( key in options ) {
if ( ! options.hasOwnProperty( key ) || 'length' === key ) {
continue; // eslint-disable-line no-continue
}
value = options[ key ];
if ( 'object' === typeof value ) { // If the value is an array, then the CSS var name is the key.
if ( ! this.isDefault( key ) ) {
varName = '--awb-' + key.replaceAll( '_', '-' );
callback_args = ( 'object' === typeof value.args ? value.args : [ this.values[ key ] ] );
css += varName + ':' + value.callback.apply( null, callback_args ) + ';';
}
} else {
if ( ! this.isDefault( value ) ) { // eslint-disable-line no-lonely-if
varName = '--awb-' + value.replaceAll( '_', '-' );
css += varName + ':' + this.values[ value ] + ';';
}
}
}
return css;
},
/**
* Get a string with custom CSS variables, created from array key => value pairs.
*
* @since 3.9
* @param {Object} $options The object with the custom css vars. The property
* represents the option name, while the value represents the custom value.
* @return {string}
*/
getCustomCssVars( options, prefix ) {
var css = '',
varName,
property;
if ( 'undefined' === typeof prefix ) {
prefix = true;
}
for ( property in options ) {
if ( ! options.hasOwnProperty( property ) ) {
continue; // eslint-disable-line no-continue
}
if ( prefix ) {
varName = '--awb-' + property.replaceAll( '_', '-' );
} else {
varName = '--' + property;
}
css += varName + ':' + options[ property ] + ';';
}
return css;
}
} );
}( jQuery ) );
;/* global FusionApp, FusionPageBuilderApp, FusionEvents */
var FusionPageBuilder = FusionPageBuilder || {};
( function() {
FusionPageBuilder.offCanvasStyles = Backbone.Model.extend( {
/**
* Off Canvas Live editor preview initialization.
*
* @since 3.6
* @return {void}
*/
initialize: function() {
const body = jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ),
ocID = body.find( '.awb-off-canvas-wrap' ).attr( 'data-id' );
// Make sure Off Canvas is 100% width in LE.
body.find( '#main' ).addClass( 'width-100' );
this.baseSelector = '.awb-off-canvas-wrap[data-id="' + ocID + '"]';
this.dynamic_css = {};
this.options = this.filterOptions();
this.buildAttr();
// Remove saved styles.
body.find( '#awb-off-canvas-style-block-' + ocID ).remove();
this.listenTo( FusionEvents, 'awb-off-canvas-styles', this.buildStyles );
this.listenTo( FusionEvents, 'awb-off-canvas-attr', this.buildAttr );
this.listenTo( FusionEvents, 'awb-off-canvas-custom-close-button', this.customCloseButton );
this.listenTo( FusionEvents, 'awb-off-canvas-enter-animation', this.enterAnimation );
this.listenTo( FusionEvents, 'awb-off-canvas-exit-animation', this.exitAnimation );
this.listenTo( FusionEvents, 'fusion-builder-loaded', this.buildStyles );
this.listenTo( FusionEvents, 'fusion-builder-loaded', this.buildAttr );
this.listenTo( FusionEvents, 'fusion-builder-loaded', this.customCloseButton );
},
/**
* Array with animations without directions.
*
* @since 3.6
* @return {void}
*/
animationsWithoutDirection: [ 'flash', 'rubberBand', 'shake', 'flipinx', 'flipiny', 'lightspeedin', 'flipOutX', 'flipOutY', 'lightSpeedOut' ],
/**
* Modify options mostly for sliding bar type.
*
* @since 3.6
* @return {Object} Modified options object.
*/
filterOptions: function() {
const options = FusionApp.data.postMeta._fusion;
const filteredOptions = Object.assign( {}, options );
if ( 'undefined' !== typeof options && 'sliding-bar' === options.type ) {
filteredOptions.type = 'sliding-bar';
filteredOptions.enter_animation = filteredOptions.sb_enter_animation;
filteredOptions.enter_animation_speed = filteredOptions.sb_enter_animation_speed;
filteredOptions.enter_animation_timing = filteredOptions.sb_enter_animation_timing;
filteredOptions.exit_animation = filteredOptions.sb_exit_animation;
filteredOptions.exit_animation_speed = filteredOptions.sb_exit_animation_speed;
filteredOptions.exit_animation_timing = filteredOptions.sb_exit_animation_timing;
if ( 'left' === filteredOptions.position || !filteredOptions.position ) {
filteredOptions.height = 'full';
filteredOptions.width = options.width || 400;
filteredOptions.enter_animation_direction = 'left';
filteredOptions.exit_animation_direction = 'left';
filteredOptions.vertical_position = 'flex-start';
if ( this.isRTL() ) {
filteredOptions.horizontal_position = 'flex-end';
} else {
filteredOptions.horizontal_position = 'flex-start';
}
}
if ( 'right' === filteredOptions.position ) {
filteredOptions.height = 'full';
filteredOptions.width = options.width || 400;
filteredOptions.enter_animation_direction = 'right';
filteredOptions.exit_animation_direction = 'right';
filteredOptions.vertical_position = 'flex-start';
if ( this.isRTL() ) {
filteredOptions.horizontal_position = 'flex-start';
} else {
filteredOptions.horizontal_position = 'flex-end';
}
}
if ( 'top' === filteredOptions.position ) {
const height = filteredOptions.sb_height || 'auto';
filteredOptions.width = '100vw';
filteredOptions.height = 'custom';
filteredOptions.custom_height = height;
filteredOptions.enter_animation_direction = 'down';
filteredOptions.exit_animation_direction = 'up';
filteredOptions.vertical_position = 'flex-start';
filteredOptions.horizontal_position = 'flex-start';
}
if ( 'bottom' === filteredOptions.position ) {
const height = filteredOptions.sb_height || 'auto';
filteredOptions.width = '100vw';
filteredOptions.height = 'custom';
filteredOptions.custom_height = height;
filteredOptions.enter_animation_direction = 'up';
filteredOptions.exit_animation_direction = 'down';
filteredOptions.vertical_position = 'flex-end';
filteredOptions.horizontal_position = 'flex-start';
}
return this.parseOptions( filteredOptions );
}
return this.parseOptions( options );
},
/**
* Merge default options with current options.
* To ensure the preview works as same as the front-end.
* @since 3.6
* @param {Object} options - The options object.
* @return {Object} New options object with default values.
*/
parseOptions( options ) {
const defaults = {
// General.
'type': 'popup',
'width': '800',
'width_medium': '',
'width_small': '',
'height': 'fit',
'custom_height': '',
'custom_height_medium': '',
'custom_height_small': '',
'horizontal_position': 'center',
'horizontal_position_medium': '',
'horizontal_position_small': '',
'vertical_position': 'center',
'vertical_position_medium': '',
'vertical_position_small': '',
'content_layout': 'column',
'align_content': 'flex-start',
'valign_content': 'flex-start',
'content_wrap': 'wrap',
'enter_animation': '',
'enter_animation_direction': 'static',
'enter_animation_speed': 0.5,
'enter_animation_timing': 'ease',
'exit_animation': '',
'exit_animation_direction': 'static',
'exit_animation_speed': 0.5,
'exit_animation_timing': 'ease',
'off_canvas_state': 'closed',
'sb_height': '',
'position': 'left',
'transition': 'overlap',
'sb_enter_animation': 'slideShort',
'sb_enter_animation_speed': 0.5,
'sb_enter_animation_timing': 'ease',
'sb_exit_animation': 'slideShort',
'sb_exit_animation_speed': 0.5,
'sb_exit_animation_timing': 'ease',
// Design.
'background_color': '#ffffff',
'background_image': '',
'background_position': 'left top',
'background_repeat': 'repeat',
'background_size': '',
'background_custom_size': '',
'background_blend_mode': 'none',
'oc_scrollbar': 'default',
'oc_scrollbar_background': '#f2f3f5',
'oc_scrollbar_handle_color': '#65bc7b',
'margin': '',
'padding': '',
'box_shadow': 'no',
'box_shadow_position': '',
'box_shadow_blur': '0',
'box_shadow_spread': '0',
'box_shadow_color': '',
'border_radius': '',
'border_width': '',
'border_color': '',
// Overlay.
'overlay': 'yes',
'overlay_z_index': '',
'overlay_close_on_click': 'yes',
'overlay_page_scrollbar': 'yes',
'overlay_background_color': 'rgba(0,0,0,0.8)',
'overlay_background_image': '',
'overlay_background_position': 'left top',
'overlay_background_repeat': 'repeat',
'overlay_background_size': '',
'overlay_background_custom_size': '',
'overlay_background_blend_mode': 'none',
// close button.
'close_button': 'yes',
'close_on_esc': 'yes',
'close_button_position': 'right',
'close_button_margin': {},
'close_button_color': '',
'close_button_color_hover': '',
'close_icon_size': '16',
'close_button_custom_icon': ''
};
return Object.assign( defaults, options );
},
/**
* Adds CSS property to object.
*
* @since 3.2
* @param {String} selectors - The CSS selectors.
* @param {String} property - The CSS property.
* @param {String} value - The CSS property value.
* @param {Bool} important - Should have important tag.
* @return {void}
*/
addCssProperty: function ( selectors, property, value, important ) {
if ( 'object' === typeof selectors ) {
selectors = Object.values( selectors );
}
if ( 'object' === typeof selectors ) {
selectors = selectors.join( ',' );
}
if ( 'object' !== typeof this.dynamic_css[ selectors ] ) {
this.dynamic_css[ selectors ] = {};
}
if ( 'undefined' !== typeof important && important ) {
value += ' !important';
}
if ( 'undefined' === typeof this.dynamic_css[ selectors ][ property ] || ( 'undefined' !== typeof important && important ) || ! this.dynamic_css[ selectors ][ property ].includes( 'important' ) ) {
this.dynamic_css[ selectors ][ property ] = value;
}
},
/**
* Parses CSS.
*
* @since 3.2
* @return {String}
*/
parseCSS: function () {
var css = '.awb-off-canvas-wrap .awb-off-canvas .fusion-fullwidth{margin-right:0;margin-left:0;}';
if ( 'object' === typeof this.dynamic_css ) {
_.each( this.dynamic_css, function ( properties, selector ) {
if ( 'object' === typeof properties ) {
css += selector + '{';
_.each( properties, function ( value, property ) {
css += property + ':' + value + ';';
} );
css += '}';
}
} );
}
return css;
},
/**
* Checks if param has got default value or not.
*
* @since 3.2
* @param {String} param - The param.
* @return {Bool}
*/
isDefault: function( param, subset ) {
if ( 'string' === typeof subset ) {
return 'undefined' === typeof this.options[ param ] || 'undefined' === typeof this.options[ param ][ subset ] || '' === this.options[ param ][ subset ];
}
return 'undefined' === typeof this.options[ param ] || '' === this.options[ param ];
},
/**
* Checks if website using RTL language.
*
* @since 3.6
* @return {Bool}
*/
isRTL: function () {
return jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).hasClass( 'rtl' );
},
/**
* Get CSS from spacing fields.
* used for margin, padding, position, etc.
* @since 3.6
* @param {Object} options - The options object.
* @param {String} key - options key.
* @param {String} prop - CSS property, if empty key will used instead.
* @return {String} CSS code.
*/
getSpacing: function( options, key ) {
if ( !options[ key ] && 'object' !== typeof options[ key ] ) {
return [];
}
const vars = [];
const keys = [ 'top', 'right', 'bottom', 'left' ];
keys.forEach( ( k ) => {
const v = options[ key ][ k ] || '';
if ( '' !== v ) {
vars[ key + '_' + k ] = _.fusionGetValueWithUnit( v );
}
} );
return vars;
},
/**
* Get CSS code for box shadow.
*
* @since 3.6
* @param {Object} options - The options object.
* @return {String} CSS code.
*/
getShadow( options ) {
if ( 'yes' !== options.box_shadow ) {
return '';
}
let h = '0',
v = '0';
const blur = options.box_shadow_blur || '0',
spread = options.box_shadow_spread || '0',
color = options.box_shadow_color || '';
if ( options.box_shadow_position && 'object' === typeof options.box_shadow_position ) {
h = options.box_shadow_position.horizontal || h;
v = options.box_shadow_position.vertical || v;
}
return `${_.fusionGetValueWithUnit( h )} ${_.fusionGetValueWithUnit( v )} ${_.fusionGetValueWithUnit( blur )} ${_.fusionGetValueWithUnit( spread )} ${color}`;
},
/**
* Get CSS code for borders including border radius.
*
* @since 3.6
* @param {Object} options - The options object.
* @return {String} CSS code.
*/
getBorder( options ) {
const vars = [];
// Border radius.
if ( options.border_radius && 'object' === typeof options.border_radius ) {
const br = options.border_radius;
// ensure preview works when delete value.
if ( !br.top_left ) {
br.top_left = '';
}
if ( !br.top_right ) {
br.top_right = '';
}
if ( !br.bottom_right ) {
br.bottom_right = '';
}
if ( !br.bottom_left ) {
br.bottom_left = '';
}
// loop through border radius.
Object.keys( br ).forEach( ( r ) => {
const v = br[ r ] || 0;
vars[ `border_${r}_radius` ] = _.fusionGetValueWithUnit( v );
} );
}
// Border width.
if ( options.border_width && 'object' === typeof options.border_width ) {
const bw = options.border_width;
// ensure preview works when delete value.
if ( !bw.top ) {
bw.top = '';
}
if ( !bw.right ) {
bw.right = '';
}
if ( !bw.bottom ) {
bw.bottom = '';
}
if ( !bw.left ) {
bw.left = '';
}
Object.keys( bw ).forEach( ( b ) => {
const v = bw[ b ] || 0;
vars[ `border_${b}_width` ] = _.fusionGetValueWithUnit( v );
} );
}
// Border color.
if ( options.border_color ) {
vars.border_color = options.border_color;
}
return vars;
},
/**
* Build CSS style block and add it to the head.
*
* @since 3.6
* @return {void} CSS code.
*/
buildStyles: function() {
var selectors,
css = '';
this.dynamic_css = {};
const options = this.filterOptions();
// Add style variables.
const body = jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' );
body.find( this.baseSelector ).attr( 'style', this.getStylesVars() );
// Fix close button z-index in LE.
selectors = [ this.baseSelector + ' .awb-off-canvas:hover .off-canvas-close' ];
this.addCssProperty( selectors, 'display', 'none' );
// Close button.
selectors = [ this.baseSelector + ' .off-canvas-close' ];
if ( 'no' === options.close_button ) {
this.addCssProperty( selectors, 'display', 'none' );
}
// Add attribute to the option.
const value = jQuery( '[data-option-id="content_layout"]' ).find( 'input#content_layout' ).val();
jQuery( '[data-option-id="content_layout"]' ).attr( 'data-direction', value );
// hidden scrollbar.
if ( 'hidden' === options.oc_scrollbar ) {
selectors = [ this.baseSelector + ' .off-canvas-content' ];
// Firefox.
this.addCssProperty( selectors, 'scrollbar-width', 'none' );
// Chrome, Safari, Edge.
this.addCssProperty( [ this.baseSelector + ' .off-canvas-content::-webkit-scrollbar' ], 'display', 'none' );
}
css = this.parseCSS();
if ( jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'head' ).find( '#awb-off-canvas-style-block' ).length ) {
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'head' ).find( '#awb-off-canvas-style-block' ).html( css );
return;
}
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'head' ).prepend( '' );
},
/**
* Build style variables.
*
* @since 3.9
* @return String CSS variables.
*/
getStylesVars: function() {
const options = this.filterOptions();
let vars = {};
if ( options.horizontal_position ) {
vars.horizontal_position = options.horizontal_position;
}
if ( options.horizontal_position_medium ) {
vars.horizontal_position_medium = options.horizontal_position_medium;
}
if ( options.horizontal_position_small ) {
vars.horizontal_position_small = options.horizontal_position_small;
}
if ( options.vertical_position ) {
vars.vertical_position = options.vertical_position;
}
if ( options.vertical_position_medium ) {
vars.vertical_position_medium = options.vertical_position_medium;
}
if ( options.vertical_position_small ) {
vars.vertical_position_small = options.vertical_position_small;
}
if ( options.overlay_z_index ) {
vars.overlay_z_index = options.overlay_z_index;
}
// Overlay Background.
if ( 'yes' === options.overlay ) {
if ( options.overlay_background_color ) {
vars.overlay_background_color = options.overlay_background_color;
}
if ( options.overlay_background_image ) {
let overlay_background_image = options.overlay_background_image;
if ( _.isObject( overlay_background_image ) ) {
overlay_background_image = overlay_background_image.url;
}
vars.overlay_background_image = `url(${overlay_background_image})`;
if ( options.overlay_background_repeat ) {
vars.overlay_background_repeat = options.overlay_background_repeat;
}
if ( options.overlay_background_position ) {
vars.overlay_background_position = options.overlay_background_position;
}
if ( options.overlay_background_blend_mode ) {
vars.overlay_background_blend_mode = options.overlay_background_blend_mode;
}
if ( '' !== options.overlay_background_size ) {
if ( 'custom' === options.overlay_background_size ) {
const width = options.overlay_background_custom_size.width ? _.fusionGetValueWithUnit( options.overlay_background_custom_size.width ) : '';
const height = options.overlay_background_custom_size.height ? _.fusionGetValueWithUnit( options.overlay_background_custom_size.height ) : '';
// eslint-disable-next-line max-depth
if ( width ) {
vars.overlay_background_size = width + ' ' + height;
}
} else {
vars.overlay_background_size = options.overlay_background_size;
}
}
}
}
if ( options.width ) {
vars.width = _.fusionGetValueWithUnit( options.width );
}
if ( options.width_medium ) {
vars.width_medium = _.fusionGetValueWithUnit( options.width_medium );
}
if ( options.width_small ) {
vars.width_small = _.fusionGetValueWithUnit( options.width_small );
}
if ( options.height ) {
if ( 'full' === options.height ) {
vars.height = '100vh';
}
if ( 'custom' === options.height ) {
if ( options.custom_height ) {
vars.height = _.fusionGetValueWithUnit( options.custom_height );
}
if ( options.custom_height_medium ) {
vars.height_medium = _.fusionGetValueWithUnit( options.custom_height_medium );
}
if ( options.custom_height_small ) {
vars.height_small = _.fusionGetValueWithUnit( options.custom_height_small );
}
}
}
// Margin.
vars = { ...vars, ...this.getSpacing( options, 'margin' ) };
// Padding.
vars = { ...vars, ...this.getSpacing( options, 'padding' ) };
vars.box_shadow = this.getShadow( options );
vars = { ...vars, ...this.getBorder( options ) };
if ( options.background_color ) {
vars.background_color = options.background_color;
}
if ( options.background_image ) {
let background_image = options.background_image;
if ( _.isObject( background_image ) ) {
background_image = background_image.url;
}
vars.background_image = `url(${background_image})`;
if ( options.background_repeat ) {
vars.background_repeat = options.background_repeat;
}
if ( options.background_position ) {
vars.background_position = options.background_position;
}
if ( options.background_blend_mode ) {
vars.background_blend_mode = options.background_blend_mode;
}
if ( '' !== options.background_size ) {
if ( 'custom' === options.background_size ) {
const width = options.background_custom_size.width ? _.fusionGetValueWithUnit( options.background_custom_size.width ) : '';
const height = options.background_custom_size.height ? _.fusionGetValueWithUnit( options.background_custom_size.height ) : '';
if ( width ) {
vars.background_size = width + ' ' + height;
}
} else {
vars.background_size = options.background_size;
}
}
}
// Custom Scrollbar.
if ( 'custom' === options.oc_scrollbar ) {
if ( options.oc_scrollbar_handle_color ) {
vars.oc_scrollbar_handle_color = options.oc_scrollbar_handle_color;
}
if ( options.oc_scrollbar_background ) {
vars.oc_scrollbar_background = options.oc_scrollbar_background;
}
}
// Alignment.
if ( options.content_layout ) {
vars.content_layout = options.content_layout;
}
if ( options.align_content ) {
vars.align_content = options.align_content;
}
if ( options.valign_content ) {
vars.valign_content = options.valign_content;
}
if ( options.content_wrap ) {
vars.content_wrap = options.content_wrap;
}
// Close button.
vars = { ...vars, ...this.getSpacing( options, 'close_button_margin' ) };
if ( options.close_button_color ) {
vars.close_button_color = options.close_button_color;
}
if ( options.close_icon_size ) {
vars.close_icon_size = _.fusionGetValueWithUnit( options.close_icon_size );
}
if ( options.close_button_color_hover ) {
vars.close_button_color_hover = options.close_button_color_hover;
}
let style = '';
Object.keys( vars ).forEach( ( v ) => {
const var_name = '--awb-' + v.replaceAll( '_', '-' );
style += var_name + ':' + vars[ v ] + ';';
} );
return style;
},
/**
* build attributes.
*
* @since 3.6
* @return {String} CSS code.
*/
buildAttr: function() {
const body = jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' );
const options = this.filterOptions();
// Wrap Classes.
let wrapClasses = 'awb-off-canvas-wrap awb-show';
if ( '' !== options.css_id ) {
body.find( this.baseSelector ).attr( 'id', options.css_id );
}
if ( '' !== options.css_class ) {
wrapClasses += ' ' + options.css_class;
}
if ( '' !== options.type ) {
wrapClasses += ' type-' + options.type;
}
if ( 'sliding-bar' === options.type ) {
if ( !options.position ) {
options.position = 'left';
}
wrapClasses += ' position-' + options.position;
}
if ( 'no' === options.overlay ) {
wrapClasses += ' overlay-disabled';
}
if ( 'custom' === options.oc_scrollbar ) {
wrapClasses += ' has-custom-scrollbar';
}
if ( 'hidden' === options.oc_scrollbar ) {
wrapClasses += ' hidden-scrollbar';
}
body.find( this.baseSelector ).removeClass().addClass( wrapClasses );
body.find( this.baseSelector ).attr( 'style', this.getStylesVars() );
// remove is empty class.
if ( 1 < FusionPageBuilderApp.collection.length ) {
body.find( this.baseSelector + ' .awb-off-canvas-inner' ).removeClass( 'is-empty' );
}
// close button attr.
const closeButton = body.find( this.baseSelector ).find( '.off-canvas-close' );
closeButton.removeClass( function ( index, className ) {
return ( className.match( /(^|\s)close-position-\S+/g ) || [] ).join( ' ' );
} );
closeButton.addClass( 'close-position-' + options.close_button_position );
},
/**
* Custom close button.
*
* @since 3.6
* @return {void}.
*/
customCloseButton: function() {
const options = this.filterOptions();
const body = jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' );
let closeButton = body.find( '.off-canvas-close' );
if ( ! closeButton.length ) {
body.find( '.awb-off-canvas' ).prepend( '' );
closeButton = body.find( '.off-canvas-close' );
}
let cls = 'off-canvas-close';
if ( options.close_button_custom_icon ) {
cls += ' ' + _.fusionFontAwesome( options.close_button_custom_icon );
} else {
cls += ' awb-icon-close';
}
cls += ' close-position-' + options.close_button_position;
closeButton.removeClass().addClass( cls );
},
/**
* Capitalize string.
*
* @since 3.6
* @return {String} The capitalized string.
*/
capitalize: function ( string ) {
return string.charAt( 0 ).toUpperCase() + string.slice( 1 );
},
/**
* Enter animation preview.
*
* @since 3.6
* @param {String} string
* @return {void}
*/
enterAnimation: function() {
const body = jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ),
offCanvas = body.find( '.awb-off-canvas' ),
options = this.filterOptions();
let animation = options.enter_animation;
const animationDirection = options.enter_animation_direction && 'static' !== options.enter_animation_direction ? this.capitalize( options.enter_animation_direction ) : '',
animationSpeed = options.enter_animation_speed || 1,
animationTiming = options.enter_animation_timing || 'ease';
if ( animation ) {
if ( ! this.animationsWithoutDirection.includes( animation ) ) {
animation = animation + 'In' + animationDirection;
}
offCanvas.addClass( 'fusion-animated ' + animation );
offCanvas.attr( 'data-animation-type', animation );
offCanvas.css( {
'visibility': 'visible',
'animation-duration': animationSpeed + 's',
'animation-timing-function': animationTiming
} );
}
offCanvas.addClass( 'fusion-animated ' + animation );
offCanvas.on( 'animationend', function() {
const el = jQuery( this );
if ( el.attr( 'data-animation-type' ) ) {
el.removeClass( 'fusion-animated' ).removeClass( el.attr( 'data-animation-type' ) ).removeAttr( 'data-animation-type' );
}
} );
},
/**
* Exit animation preview.
*
* @since 3.6
* @return {void}
*/
exitAnimation: function() {
const body = jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ),
offCanvas = body.find( '.awb-off-canvas' ),
options = this.filterOptions();
let animation = options.exit_animation;
const animationDirection = options.exit_animation_direction && 'static' !== options.exit_animation_direction ? this.capitalize( options.exit_animation_direction ) : '',
animationSpeed = options.exit_animation_speed || 1,
animationTiming = options.exit_animation_timing || 'ease';
if ( animation ) {
if ( ! this.animationsWithoutDirection.includes( animation ) ) {
animation = animation + 'Out' + animationDirection;
}
offCanvas.addClass( 'fusion-animated ' + animation );
offCanvas.attr( 'data-animation-type', animation );
offCanvas.css( {
'visibility': 'visible',
'animation-duration': animationSpeed + 's',
'animation-timing-function': animationTiming
} );
}
offCanvas.addClass( 'fusion-animated ' + animation );
offCanvas.on( 'animationend', function() {
const el = jQuery( this );
setTimeout( () => {
if ( el.attr( 'data-animation-type' ) ) {
el.removeClass( 'fusion-animated' ).removeClass( el.attr( 'data-animation-type' ) ).removeAttr( 'data-animation-type' );
}
}, 500 );
} );
}
} );
}( jQuery ) );
;var FusionPageBuilder = FusionPageBuilder || {};
( function() {
// Element collection
FusionPageBuilder.Collection = Backbone.Collection.extend( {
model: FusionPageBuilder.Element
} );
window.FusionPageBuilderElements = new FusionPageBuilder.Collection(); // jshint ignore: line
}( jQuery ) );
;/* global fusionBuilderText, fusionGlobalManager, FusionApp, FusionPageBuilderViewManager, fusionAllElements, FusionPageBuilderApp, FusionEvents, fusionAppConfig */
/* eslint no-empty-function: 0 */
/* eslint no-shadow: 0 */
var FusionPageBuilder = FusionPageBuilder || {};
( function() {
jQuery( document ).ready( function() {
// Builder Element View
FusionPageBuilder.BaseView = window.wp.Backbone.View.extend( {
modalDialogMoreView: null,
events: {
},
/**
* Init.
*
* @since 2.0.0
* @return {void}
*/
initialize: function() {
},
/**
* Before initial render.
*
* @since 2.0.0
* @return {void}
*/
beforeRender: function() {
},
/**
* Filters render markup.
*
* @since 2.0.0
* @return null
*/
filterRender: function( $markup ) {
return $markup;
},
/**
* Runs during render() call.
*
* @since 2.0.0
* @return null
*/
onRender: function() {
},
/**
* Runs during initialize() call.
*
* @since 2.0.0
* @return null
*/
onInit: function() {
},
/**
* Runs just before view is removed.
*
* @since 2.0.0
* @return null
*/
beforeRemove: function() {
},
/**
* Runs just after render on cancel.
*
* @since 2.0.0
* @return null
*/
onCancel: function() {
},
/**
* Runs just after render on cancel.
*
* @since 3.0.2
* @return null
*/
beforeGenerateShortcode: function() {
var elementType = this.model.get( 'element_type' ),
options = fusionAllElements[ elementType ].params,
values = jQuery.extend( true, {}, fusionAllElements[ elementType ].defaults, _.fusionCleanParameters( this.model.get( 'params' ) ) ),
self = this,
iconWithoutFusionPrefix;
if ( 'object' !== typeof options ) {
return;
}
// If images needs replaced lets check element to see if we have media being used to add to object.
if ( 'undefined' !== typeof FusionApp.data.replaceAssets && FusionApp.data.replaceAssets && ( 'undefined' !== typeof FusionApp.data.fusion_element_type || 'fusion_template' === FusionApp.getPost( 'post_type' ) ) ) {
this.mapStudioImages( options, values );
if ( 'undefined' !== typeof this.model.get( 'multi' ) && 'multi_element_parent' === this.model.get( 'multi' ) ) {
this.model.children.each( function( child ) {
var elementType = child.attributes.element_type,
childOptions = fusionAllElements[ elementType ].params,
childValues = jQuery.extend( true, {}, fusionAllElements[ elementType ].defaults, _.fusionCleanParameters( child.attributes.params ) );
self.mapStudioImages( childOptions, childValues );
} );
}
if ( 'fusion_form' === elementType && '' !== values.form_post_id ) {
// If its not within object already, add it.
if ( 'undefined' === typeof FusionPageBuilderApp.mediaMap.forms[ values.form_post_id ] ) {
FusionPageBuilderApp.mediaMap.forms[ values.form_post_id ] = true;
}
}
// Add custom icons that used in forms to media map.
if ( this.isString( elementType ) && elementType.startsWith( 'fusion_form_' ) && this.isString( values.input_field_icon ) && 'fusion-prefix-' === values.input_field_icon.substr( 0, 14 ) ) {
if ( 'undefined' !== typeof fusionAppConfig.customIcons ) {
iconWithoutFusionPrefix = values.input_field_icon.substr( 14 );
// TODO: try to optimize this check.
jQuery.each( fusionAppConfig.customIcons, function( iconPostName, iconSet ) {
if ( 0 === iconWithoutFusionPrefix.indexOf( iconSet.css_prefix ) ) {
FusionPageBuilderApp.mediaMap.icons[ iconSet.post_id ] = iconSet.css_prefix;
return false;
}
} );
}
}
}
},
/**
* Add studio images to media map.
* @param {Object} options
* @param {Object} values
* @returns void
*/
mapStudioImages: function( options, values ) {
if ( 'object' !== typeof options ) {
return;
}
// If images needs replaced lets check element to see if we have media being used to add to object.
_.each( options, function( option ) {
var value;
if ( 'upload' === option.type && 'undefined' !== typeof values[ option.param_name ] && '' !== values[ option.param_name ] ) {
value = values[ option.param_name ];
if ( 'undefined' === typeof value || 'undefined' === value ) {
return;
}
// If its not within object already, add it.
if ( 'undefined' === typeof FusionPageBuilderApp.mediaMap.images[ value ] ) {
FusionPageBuilderApp.mediaMap.images[ value ] = true;
}
// Check if we have an image ID for this param.
if ( 'undefined' !== typeof values[ option.param_name + '_id' ] && '' !== values[ option.param_name + '_id' ] ) {
if ( 'object' !== typeof FusionPageBuilderApp.mediaMap.images[ value ] ) {
FusionPageBuilderApp.mediaMap.images[ value ] = {};
}
FusionPageBuilderApp.mediaMap.images[ value ][ option.param_name + '_id' ] = values[ option.param_name + '_id' ];
}
} else if ( 'upload_images' === option.type && 'undefined' !== typeof values[ option.param_name ] && '' !== values[ option.param_name ] ) {
if ( 'object' !== typeof FusionPageBuilderApp.mediaMap.multiple_images ) {
FusionPageBuilderApp.mediaMap.multiple_images = {};
}
const key = option.param_name + '-' + values[ option.param_name ];
if ( 'object' !== typeof FusionPageBuilderApp.mediaMap.multiple_images[ key ] ) {
FusionPageBuilderApp.mediaMap.multiple_images[ key ] = {};
}
// Add images URLs
const images = values[ option.param_name ].split( ',' );
images.forEach( ( id ) => {
const image = wp.media.attachment( id );
if ( _.isUndefined( image.get( 'url' ) ) ) {
image.fetch().then( function() {
FusionPageBuilderApp.mediaMap.multiple_images[ key ][ id ] = image.get( 'url' );
} );
} else {
FusionPageBuilderApp.mediaMap.multiple_images[ key ][ id ] = image.get( 'url' );
}
} );
}
} );
},
/**
* Triggers a refresh.
*
* @since 2.0.0
* @return void
*/
refreshJs: function() {
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).trigger( 'fusion-element-render-' + this.model.attributes.element_type, this.model.attributes.cid );
},
/**
* Triggers responsive typography to recalculate.
*
* @since 2.0.0
* @return void
*/
updateResponsiveTypography: function() {
document.querySelector( '#fb-preview' ).contentWindow.document.body.dispatchEvent( new Event( 'fusion-force-typography-update', { 'bubbles': true, 'cancelable': true } ) );
},
/**
* Re-Renders the view.
*
* @since 2.0.0
* @param {Object} event - The event triggering the rerender.
* @return {void}
*/
reRender: function( event ) {
if ( event && 'object' === typeof event ) {
event.preventDefault();
}
this.patchView( event );
if ( this.model.get( 'inline_editor' ) && ! this.activeInlineEditing ) {
FusionPageBuilderApp.inlineEditorHelpers.liveEditorEvent( this );
this.activeInlineEditing = false;
}
},
patchView: function() {
var self = this,
$oldContent = '',
$newContent = '',
MultiGlobalArgs = {},
diff,
heightBeforePatch;
if ( 'generated_element' === this.model.get( 'type' ) || 'fusion_builder_form_step' === this.model.get( 'type' ) ) {
return;
}
heightBeforePatch = this.$el.outerHeight();
this.beforePatch();
FusionPageBuilderApp.disableDocumentWrite();
$oldContent = this.getElementContent();
$newContent = $oldContent.clone();
$newContent.html( self.getTemplate() );
// Find the difference
diff = FusionPageBuilderApp._diffdom.diff( $oldContent[ 0 ], $newContent[ 0 ] );
// Columns. Skip resizable patching.
if ( 'function' === typeof this.patcherFilter ) {
diff = this.patcherFilter( diff );
}
// Apply the difference.
FusionPageBuilderApp._diffdom.apply( $oldContent[ 0 ], diff );
if ( 'fusion_builder_column' !== this.model.get( 'element_type' ) ) {
// Handle multiple global elements.
MultiGlobalArgs = {
currentModel: this.model,
handleType: 'changeView',
difference: diff
};
fusionGlobalManager.handleMultiGlobal( MultiGlobalArgs );
}
$oldContent.removeClass( 'fusion-loader' );
FusionPageBuilderApp.enableDocumentWrite();
this.afterPatch();
// So equalHeights columns are updated.
if ( heightBeforePatch !== this.$el.outerHeight() && 'function' === typeof this._triggerColumn ) {
this._triggerColumn();
}
},
/**
* Filter out DOM before patching.
*
* @since 2.0.0
* @return {void}
*/
patcherFilter: function( diffs ) {
var filteredDiffs = [],
ignoreList = [
'aria-multiline',
'contenteditable',
'data-inline-fontsize',
'data-medium-editor-index',
'data-medium-editor-element',
'data-medium-focused',
'data-placeholder',
'medium-editor-index',
'role',
'spellcheck'
],
skipReInit = false;
if ( this.activeInlineEditing ) {
_.each( diffs, function( diff ) {
if ( 'removeAttribute' === diff.action && -1 !== jQuery.inArray( diff.name, ignoreList ) ) {
skipReInit = true;
return;
} else if ( 'modifyAttribute' === diff.action && -1 !== diff.oldValue.indexOf( 'medium-editor-element' ) && -1 === diff.oldValue.indexOf( 'medium-editor-element' ) ) {
diff.newValue = diff.newValue + ' medium-editor-element';
filteredDiffs.push( diff );
skipReInit = true;
return;
}
filteredDiffs.push( diff );
} );
diffs = filteredDiffs;
// If we are not just removing/modifying attributes then inline needs recreated.
this.activeInlineEditing = skipReInit;
this.autoSelectEditor = ! skipReInit;
}
return diffs;
},
/**
* Runs before view DOM is patched.
*
* @since 2.0.0
* @return null
*/
beforePatch: function() {
},
/**
* Runs after view DOM is patched.
*
* @since 2.0.0
* @return null
*/
afterPatch: function() {
// This will trigger a JS event on the preview frame.
this._refreshJs();
},
/**
* Runs after render to open any newly added inline element settings.
*
* @since 2.0.0
* @return null
*/
renderInlineSettings: function() {
var newlyAdded;
if ( 'undefined' === typeof FusionPageBuilderApp.inlineEditors || ! FusionPageBuilderApp.inlineEditors.shortcodeAdded ) {
return;
}
newlyAdded = this.model.inlineCollection.find( function( model ) {
return 'true' == model.get( 'params' ).open_settings; // jshint ignore: line
} );
if ( 'undefined' !== typeof newlyAdded ) {
newlyAdded.parentView = this;
newlyAdded.$target = this.$el.find( '.fusion-disable-editing[data-id="' + newlyAdded.get( 'cid' ) + '"]' );
delete newlyAdded.attributes.params.open_settings;
if ( 'undefined' !== typeof FusionApp && 'off' !== FusionApp.preferencesData.open_settings ) {
newlyAdded.set( 'added', true );
FusionPageBuilderApp.inlineEditorHelpers.getInlineElementSettings( newlyAdded );
}
}
},
/**
* Get the template.
*
* @since 2.0.0
* @return {void}
*/
getTemplate: function() {
var atts = this.getTemplateAtts();
if ( 'undefined' !== typeof this.elementTemplate ) {
return this.elementTemplate( atts );
}
},
/**
* Modify template attributes.
*
* @since 2.0.0
* @return {Object}
*/
filterTemplateAtts: function( atts ) {
return atts;
},
/**
* Get dynamic values.
*
* @since 2.0.0
* @return {Object}
*/
getDynamicAtts: function( atts ) {
var self = this;
if ( 'undefined' !== typeof this.dynamicParams && this.dynamicParams && ! _.isEmpty( this.dynamicParams.getAll() ) ) {
_.each( this.dynamicParams.getAll(), function( data, id ) {
var value = self.dynamicParams.getParamValue( data );
if ( 'undefined' !== typeof value && false !== value ) {
atts.values[ id ] = value;
}
} );
}
return atts;
},
/**
* Gets element DOM for patching.
*
* @since 2.1
* @return {Object}
*/
getValues: function() {
var elementType = this.model.get( 'element_type' ),
element = fusionAllElements[ elementType ];
return this.getDynamicAtts( jQuery.extend( true, {}, element.defaults, _.fusionCleanParameters( this.model.get( 'params' ) ) ) );
},
/**
* Gets element DOM for patching.
*
* @since 2.0.0
* @return {Object}
*/
getElementContent: function() {
var self = this;
switch ( this.model.get( 'type' ) ) {
case 'fusion_builder_column':
case 'fusion_builder_container':
case 'fusion_builder_column_inner':
return self.$el;
case 'element':
if ( 'multi_element_child' !== self.model.get( 'multi' ) ) {
return self.$el.find( '.fusion-builder-element-content' );
}
return self.$el.find( '.fusion-builder-child-element-content' );
}
},
/**
* Settings handler.
*
* @since 2.0.0
* @param {Object} event - The event.
* @return {void}
*/
settings: function( event ) {
var self = this,
viewSettings = {
model: this.model,
collection: this.collection
},
customSettingsViewName,
modalView,
parentView,
generated = 'generated_element' === this.model.get( 'type' ),
childElementClass = '',
dialogTitle = '',
resizePopupClass = localStorage.getItem( 'resizePopupClass' );
if ( event ) {
event.preventDefault();
}
this.onSettingsOpen();
customSettingsViewName = fusionAllElements[ this.model.get( 'element_type' ) ].custom_settings_view_name;
// Check for generated element child.
if ( 'multi_element_child' === this.model.get( 'multi' ) ) {
parentView = FusionPageBuilderViewManager.getView( this.model.get( 'parent' ) );
if ( parentView && 'generated_element' === parentView.model.get( 'type' ) ) {
generated = true;
viewSettings.model.set( 'type', 'generated_element' );
viewSettings.model.set( 'display', 'dialog' );
}
}
if ( 'undefined' !== typeof customSettingsViewName && '' !== customSettingsViewName ) {
modalView = new FusionPageBuilder[ customSettingsViewName ]( viewSettings );
} else {
modalView = new FusionPageBuilder.ElementSettingsView( viewSettings );
}
// Activate column spacing.
if ( 'fusion_builder_column' === this.model.get( 'element_type' ) || 'fusion_builder_column_inner' === this.model.get( 'element_type' ) ) {
this.columnSpacing();
this.paddingDrag();
this.marginDrag();
// Hides column size popup.
this.$el.removeClass( 'active' );
this.$el.closest( '.fusion-builder-container' ).removeClass( 'fusion-column-sizer-active' );
}
// Activate resize handles.
if ( 'fusion_builder_container' === this.model.get( 'element_type' ) ) {
this.paddingDrag();
this.marginDrag();
}
if ( 'fusion_builder_container' === this.model.get( 'element_type' ) || 'fusion_builder_column' === this.model.get( 'element_type' ) || 'fusion_builder_column_inner' === this.model.get( 'element_type' ) ) {
this.$el.addClass( 'fusion-builder-element-edited' );
}
childElementClass = 'undefined' !== this.model.get( 'multi' ) && 'multi_element_child' === this.model.get( 'multi' ) ? ' fusion-builder-child-element' : '';
dialogTitle = this.getDialogTitle();
// No need to render if it already is.
if ( ! FusionPageBuilderApp.SettingsHelpers.shouldRenderSettings( modalView ) ) {
return;
}
// If we want dialog.
if ( 'dialog' === FusionApp.preferencesData.editing_mode || generated ) {
jQuery( modalView.render().el ).dialog( {
title: dialogTitle,
width: FusionApp.dialog.dialogData.width,
height: FusionApp.dialog.dialogData.height,
position: FusionApp.dialog.dialogData.position,
dialogClass: 'fusion-builder-dialog fusion-builder-settings-dialog' + childElementClass,
minWidth: 327,
type: this.model.get( 'type' ),
dragStop: function( event, ui ) {
FusionApp.dialog.saveDialogPosition( ui.offset );
},
resizeStart: function() {
FusionApp.dialog.addResizingClasses();
},
resizeStop: function( event, ui ) {
var $dialog = jQuery( event.target ).closest( '.ui-dialog' ),
width = $dialog.find( '.fusion-tabs-menu > li' ).length;
if ( width ) {
width = 100 * width;
}
if ( width && ui.size.width > width ) {
$dialog.find( '.fusion-tabs-menu' ).addClass( 'show-text' );
} else {
$dialog.find( '.fusion-tabs-menu' ).removeClass( 'show-text' );
}
FusionApp.dialog.saveDialogSize( ui.size );
if ( 450 > ui.size.width && ! $dialog.hasClass( 'fusion-builder-dialog-narrow' ) ) {
$dialog.addClass( 'fusion-builder-dialog-narrow' );
} else if ( 450 <= ui.size.width && $dialog.hasClass( 'fusion-builder-dialog-narrow' ) ) {
$dialog.removeClass( 'fusion-builder-dialog-narrow' );
}
FusionApp.dialog.removeResizingClasses();
},
open: function( event ) {
var $dialogContent = jQuery( event.target ),
$dialog = $dialogContent.closest( '.ui-dialog' ),
width;
// On start can sometimes be laggy/late.
FusionApp.dialog.addResizingHoverEvent();
if ( modalView.$el.find( '.has-group-options' ).length ) {
$dialog.addClass( 'fusion-builder-group-options' );
}
$dialogContent.find( '.fusion-builder-section-name' ).blur();
jQuery( '.ui-dialog' ).not( $dialog ).hide();
jQuery( '.fusion-back-menu-item' ).on( 'click', function() {
modalView.openParent();
self.onSettingsClose();
} );
self.modalDialogMoreView = new FusionPageBuilder.modalDialogMore( { model: self.model } );
// We need to render context submenu on open.
FusionPageBuilderApp.SettingsHelpers.renderDialogMoreOptions( modalView );
if ( null !== resizePopupClass ) {
jQuery( 'body' ).addClass( resizePopupClass );
self.modalDialogMoreView.resizePopup( resizePopupClass );
}
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).addClass( 'fusion-dialog-ui-active' );
if ( 450 > $dialog.width() && ! $dialog.hasClass( 'fusion-builder-dialog-narrow' ) ) {
$dialog.addClass( 'fusion-builder-dialog-narrow' );
} else if ( 450 <= $dialog.width() && $dialog.hasClass( 'fusion-builder-dialog-narrow' ) ) {
$dialog.removeClass( 'fusion-builder-dialog-narrow' );
}
// Check if dialog is positioned outside of viewport and reposition it if needed.
if ( FusionApp.dialog.maybeRepositionDialog( $dialog ) ) {
FusionApp.dialog.saveDialogPosition( $dialog.offset() );
}
width = $dialog.find( '.fusion-tabs-menu > li' ).length;
if ( width ) {
width = 100 * width;
}
if ( width && $dialog.width() > width ) {
$dialog.find( '.fusion-tabs-menu' ).addClass( 'show-text' );
}
},
dragStart: function( event ) {
// Used to close any open drop-downs in TinyMce.
jQuery( event.target ).trigger( 'click' );
},
beforeClose: function( event ) {
FusionApp.dialogCloseResets( modalView );
self.modalDialogMoreView = null;
modalView.saveSettings( event );
FusionEvents.trigger( 'fusion-content-changed' );
}
} );
} else {
// Adding into sidebar view instead.
modalView.model.set( 'title', dialogTitle );
modalView.model.set( 'display', 'sidebar' );
FusionApp.sidebarView.renderElementSettings( modalView );
}
},
getDialogTitle: function() {
var dialogTitle = fusionAllElements[ this.model.get( 'element_type' ) ].name,
params;
if ( 'multi_element_child' === this.model.get( 'multi' ) ) {
params = jQuery.extend( true, {}, this.model.get( 'params' ) );
dialogTitle = 'Item';
if ( 'undefined' !== typeof params.title && params.title.length ) {
dialogTitle = params.title;
} else if ( 'undefined' !== typeof params.title_front && params.title_front.length ) {
dialogTitle = params.title_front;
} else if ( 'undefined' !== typeof params.name && params.name.length ) {
dialogTitle = params.name;
} else if ( 'undefined' !== typeof params.image && params.image.length ) {
dialogTitle = params.image;
// If contains backslash, retrieve only last part.
if ( -1 !== dialogTitle.indexOf( '/' ) && -1 === dialogTitle.indexOf( '[' ) ) {
dialogTitle = dialogTitle.split( '/' );
dialogTitle = dialogTitle.slice( -1 )[ 0 ];
}
} else if ( 'image' === this.model.attributes.element_name && 'undefined' !== typeof params.element_content && params.element_content.length ) {
dialogTitle = params.element_content;
// If contains backslash, retrieve only last part.
if ( -1 !== dialogTitle.indexOf( '/' ) && -1 === dialogTitle.indexOf( '[' ) ) {
dialogTitle = dialogTitle.split( '/' );
dialogTitle = dialogTitle.slice( -1 )[ 0 ];
}
} else if ( 'undefined' !== typeof params.video && params.video.length ) {
dialogTitle = params.video;
} else if ( 'undefined' !== typeof params.element_content && params.element_content.length ) {
dialogTitle = params.element_content;
}
// Remove HTML tags but keep quotation marks etc.
dialogTitle = dialogTitle.replace( /(<([^>]+)>)/ig, '' );
dialogTitle = ( dialogTitle && 15 < dialogTitle.length ) ? dialogTitle.substring( 0, 15 ) + '...' : dialogTitle;
dialogTitle = _.fusionUcFirst( dialogTitle );
}
return dialogTitle;
},
/**
* Extendable function for when settings is opened.
*
* @since 2.0.0
* @return {void}
*/
onSettingsOpen: function() {
},
/**
* Extendable function for when settings is closed.
*
* @since 2.0.0
* @return {void}
*/
onSettingsClose: function() {
var $dialog = jQuery( '.ui-dialog:not( .fusion-video-dialog ):not( .fusion-builder-preferences-dialog )' ).first();
// If there are opened dialogs which are resizable.
if ( 0 < $dialog.length && ! jQuery( 'body' ).hasClass( 'fusion-settings-dialog-large' ) ) {
// Change it's size.
jQuery( $dialog ).css( 'width', FusionApp.dialog.dialogData.width + 'px' );
jQuery( $dialog ).css( 'height', FusionApp.dialog.dialogData.height + 'px' );
// Reposition it.
jQuery( $dialog ).position( {
my: FusionApp.dialog.dialogData.position.my,
at: FusionApp.dialog.dialogData.position.at,
of: window
} );
}
},
/**
* Renders the content.
*
* @since 2.0.0
* @return {void}
*/
renderContent: function() {
},
/**
* Adds loading overlay while ajax is performing.
*
* @since 2.0.0
* @return {void}
*/
addLoadingOverlay: function() {
var contentType = 'element',
$elementContent;
if ( _.isObject( this.model.attributes ) ) {
if ( 'fusion_builder_container' === this.model.attributes.element_type ) {
contentType = 'container';
} else if ( 'fusion_builder_column' === this.model.attributes.element_type ) {
contentType = 'columns';
}
}
$elementContent = this.$el.find( '.fusion-builder-' + contentType + '-content' );
if ( ! $elementContent.hasClass( 'fusion-loader' ) ) {
$elementContent.addClass( 'fusion-loader' );
$elementContent.append( '' );
}
},
/**
* Removes loading overlay after ajax is done.
*
* @since 3.5
* @return {void}
*/
removeLoadingOverlay: function() {
var contentType = 'element',
$elementContent;
if ( _.isObject( this.model.attributes ) ) {
if ( 'fusion_builder_container' === this.model.attributes.element_type ) {
contentType = 'container';
} else if ( 'fusion_builder_column' === this.model.attributes.element_type ) {
contentType = 'columns';
}
}
$elementContent = this.$el.find( '.fusion-builder-' + contentType + '-content' );
if ( $elementContent.hasClass( 'fusion-loader' ) ) {
$elementContent.removeClass( 'fusion-loader' );
$elementContent.find( '.fusion-builder-loader' ).remove();
}
},
/**
* Removes an element.
*
* @since 2.0.0
* @param {Object} event - The event triggering the element removal.
* @return {void}
*/
removeElement: function( event ) {
var parentCid = this.model.get( 'parent' );
if ( event ) {
event.preventDefault();
FusionEvents.trigger( 'fusion-content-changed' );
}
// Remove element view
FusionPageBuilderViewManager.removeView( this.model.get( 'cid' ) );
// Destroy element model
this.model.destroy();
FusionEvents.trigger( 'fusion-element-removed', this.model.get( 'cid' ) );
// Update column trigger.
this.triggerColumn( parentCid );
// Destroy dynamic param model.
if ( this.dynamicParam ) {
this.dynamicParam.destroy();
}
this.remove();
},
/**
* Opens the library. Builds the settings for this view
* and then calls FusionPageBuilder.LibraryView and renders it.
*
* @since 2.0.0
* @param {Object} event - The js event.
* @return {void}
*/
openLibrary: function( event ) {
var view,
libraryModel = {
target: jQuery( event.currentTarget ).data( 'target' ),
focus: jQuery( event.currentTarget ).data( 'focus' ),
element_cid: this.model.get( 'cid' ),
element_name: 'undefined' !== typeof this.model.get( 'admin_label' ) && '' !== this.model.get( 'admin_label' ) ? this.model.get( 'admin_label' ) : ''
},
viewSettings = {
model: libraryModel
};
if ( event ) {
event.preventDefault();
event.stopPropagation();
FusionPageBuilderApp.sizesHide( event );
}
view = new FusionPageBuilder.LibraryView( viewSettings );
view.render();
// Make sure to close any context menus which may be open.
FusionPageBuilderApp.removeContextMenu();
},
/**
* Disable external links.
*
* @since 2.0.0
* @param {Object} event - The event.
* @return {void}
*/
disableLink: function( event ) {
if ( ! jQuery( event.target ).closest( '.fusion-builder-module-controls-container' ).length && 'lightbox' !== jQuery( event.currentTarget ).attr( 'target' ) ) {
event.preventDefault();
if ( FusionApp.modifierActive && ! jQuery( event.target ).parent().hasClass( 'fusion-lightbox' ) ) {
FusionApp.checkLink( event );
}
}
},
/**
* Creates droppable zone and makes element draggable.
*
* @since 2.0.0
* @return {void}
*/
droppableElement: function() {
var self = this,
$el = this.$el,
cid = this.model.get( 'cid' ),
$body = jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' );
if ( ! $el ) {
return;
}
if ( 'undefined' === typeof this.elementTarget || ! this.elementTarget.length ) {
this.elementTarget = this.$el.find( '.fusion-element-target' );
}
$el.draggable( {
appendTo: FusionPageBuilderApp.$el,
zIndex: 999999,
delay: 100,
cursorAt: { top: 15, left: 15 },
iframeScroll: true,
containment: $body,
cancel: '.fusion-live-editable, .fusion-builder-live-child-element:not( [data-fusion-no-dragging] ), .variations select, .awb-openstreet-map',
helper: function() {
var $classes = FusionPageBuilderApp.DraggableHelpers.draggableClasses( cid );
return jQuery( '
' );
},
start: function() {
$body.addClass( 'fusion-element-dragging fusion-active-dragging' );
$el.addClass( 'fusion-being-dragged' );
$el.prev( '.fusion-builder-live-element' ).find( '.target-after' ).addClass( 'target-disabled' );
},
stop: function() {
setTimeout( function() {
$body.removeClass( 'fusion-element-dragging fusion-active-dragging' );
}, 10 );
$el.removeClass( 'fusion-being-dragged' );
FusionPageBuilderApp.$el.find( '.target-disabled' ).removeClass( 'target-disabled' );
}
} );
this.elementTarget.droppable( {
tolerance: 'touch',
hoverClass: 'ui-droppable-active',
accept: '.fusion-builder-live-element, .fusion_builder_row_inner',
drop: function( event, ui ) {
var handleDropElement = self.handleDropElement.bind( self );
handleDropElement( ui.draggable, $el, jQuery( event.target ) );
}
} );
},
handleDropElement: function( $element, $targetEl, $dropTarget ) {
var parentCid = $dropTarget.closest( '.fusion-builder-column' ).data( 'cid' ),
columnView = FusionPageBuilderViewManager.getView( parentCid ),
elementCid = $element.data( 'cid' ),
elementView = FusionPageBuilderViewManager.getView( elementCid ),
MultiGlobalArgs,
newIndex;
// Move the actual html.
if ( $dropTarget.hasClass( 'target-after' ) ) {
$targetEl.after( $element );
} else {
$targetEl.before( $element );
}
newIndex = $element.parent().children( '.fusion-builder-live-element, .fusion_builder_row_inner' ).index( $element );
FusionPageBuilderApp.onDropCollectionUpdate( elementView.model, newIndex, parentCid );
// Save history state
FusionEvents.trigger( 'fusion-history-save-step', fusionBuilderText.moved + ' ' + fusionAllElements[ elementView.model.get( 'element_type' ) ].name + ' ' + fusionBuilderText.element );
// Handle multiple global elements.
MultiGlobalArgs = {
currentModel: elementView.model,
handleType: 'save',
attributes: elementView.model.attributes
};
fusionGlobalManager.handleMultiGlobal( MultiGlobalArgs );
FusionEvents.trigger( 'fusion-content-changed' );
columnView._equalHeights();
},
/**
* Destroy or disable the droppable and draggable.
*
* @since 2.0.0
* @return {void}
*/
disableDroppableElement: function() {
var $el = this.$el;
// If its been init, just disable.
if ( 'undefined' !== typeof $el.draggable( 'instance' ) ) {
$el.draggable( 'disable' );
}
// If its been init, just disable.
if ( 'undefined' !== typeof this.elementTarget && this.elementTarget.length && 'undefined' !== typeof this.elementTarget.droppable( 'instance' ) ) {
this.elementTarget.droppable( 'disable' );
}
},
/**
* Enable the droppable and draggable.
*
* @since 2.0.0
* @return {void}
*/
enableDroppableElement: function() {
var $el = this.$el;
// If they have been init, then just disable.
if ( 'undefined' !== typeof $el.draggable( 'instance' ) && 'undefined' !== typeof this.elementTarget && this.elementTarget.length && 'undefined' !== typeof this.elementTarget.droppable( 'instance' ) ) {
$el.draggable( 'enable' );
this.elementTarget.droppable( 'enable' );
} else {
// No sign of init, then need to call it.
this.droppableElement();
}
},
/**
* Gets edit label.
*
* @since 2.0.0
* @return {string}
*/
getEditLabel: function() {
var editLabel = fusionBuilderText.element_settings,
elementType = this.model.get( 'element_type' );
if ( 'undefined' !== typeof fusionAllElements[ elementType ] ) {
editLabel = fusionBuilderText.custom_element_settings;
editLabel = editLabel.replace( '%s', fusionAllElements[ elementType ].name );
}
return editLabel;
},
/**
* Simple prevent default function.
*
* @since 2.0.0
* @param {Object} event - Click event object.
* @return {void}
*/
preventDefault: function( event ) {
event.preventDefault();
},
/**
* Update element settings on drag (columns and containers).
*
* @since 2.0.0
* @param {string} selector - Selector of option.
* @param {string} value - Value to update to.
* @return {void}
*/
updateDragSettings: function( selector, value ) {
var $option = jQuery( '[data-element-cid="' + this.model.get( 'cid' ) + '"] ' + selector ),
$elementSettings,
$section;
if ( $option.length ) {
$elementSettings = $option.closest( '.fusion_builder_module_settings' );
if ( ! $elementSettings.find( '.fusion-tabs-menu a[href="#design"]' ).parent().hasClass( 'current' ) ) {
$elementSettings.find( '.fusion-tabs-menu a[href="#design"]' ).parent().trigger( 'click' );
}
$section = $elementSettings.find( '.fusion-tabs-menu a[href="#design"]' ).closest( '.fusion-sidebar-section, .ui-dialog-content' );
$section.scrollTop( $option.position().top + $section.scrollTop() );
$option.val( value ).trigger( 'change' );
}
},
baseInit: function() {
var elementType = this.model.get( 'element_type' );
this.initialValue = {};
this.logHistory = {};
if ( 'string' === typeof elementType && -1 === jQuery.inArray( elementType, FusionPageBuilderApp.inlineElements ) ) {
this.listenTo( FusionEvents, 'fusion-global-update-' + elementType, this.updateDefault );
this.listenTo( FusionEvents, 'fusion-extra-update-' + elementType, this.updateExtra );
}
this.initDynamicParams();
},
initDynamicParams: function() {
var self = this,
params = this.model.get( 'params' ),
dynamicData = params.dynamic_params;
this.dynamicParams = new FusionPageBuilder.DynamicParams( { elementView: this } );
if ( 'string' === typeof params.dynamic_params && '' !== params.dynamic_params ) {
try {
if ( FusionPageBuilderApp.base64Encode( FusionPageBuilderApp.base64Decode( dynamicData ) ) === dynamicData ) {
dynamicData = FusionPageBuilderApp.base64Decode( dynamicData );
dynamicData = _.unescape( dynamicData );
dynamicData = JSON.parse( dynamicData );
}
self.dynamicParams.setData( dynamicData );
} catch ( error ) {
console.log( error ); // jshint ignore:line
}
}
},
/**
* Check for element ajax callbacks and run them.
*
* @since 2.0.0
* @return {void}
*/
triggerAjaxCallbacks: function( skip ) {
var self = this,
AjaxCallbacks = {},
args = {
skip: 'undefined' === typeof skip ? false : skip
};
if ( 'undefined' !== typeof fusionAllElements[ this.model.get( 'element_type' ) ].has_ajax ) {
// Collect callbacks. Do not fire the same action twice.
_.each( fusionAllElements[ this.model.get( 'element_type' ) ].has_ajax, function( callback ) {
AjaxCallbacks = {};
AjaxCallbacks[ callback.action ] = {};
AjaxCallbacks[ callback.action ][ 'function' ] = callback[ 'function' ];
AjaxCallbacks[ callback.action ].param_name = callback.param_name;
AjaxCallbacks[ callback.action ].action = callback.action;
} );
// Trigger ajax callbacks to populate query_data attribute
_.each( AjaxCallbacks, function( callback ) {
FusionApp.callback[ callback[ 'function' ] ]( callback.param_name, self.model.attributes.params[ callback.param_name ], self.model.attributes, args, self.model.get( 'cid' ), callback.action, self.model, self );
} );
}
},
updateExtra: function() {
this.reRender();
},
updateDefault: function( param, value ) {
var modelData = jQuery.extend( this.model.attributes, {} ),
reRender = true,
callbackFunction = false,
params = this.model.get( 'params' );
// Only re-render if actually using default.
if ( ( 'undefined' === typeof params[ param ] || '' === params[ param ] || 'default' === params[ param ] ) && ! this.dynamicParams.hasDynamicParam( param ) ) {
callbackFunction = FusionPageBuilderApp.getCallbackFunction( modelData, param, value, this, true );
callbackFunction.args = 'undefined' === typeof callbackFunction.args ? {} : callbackFunction.args;
callbackFunction.args.skipRerender = false;
if ( false !== callbackFunction && 'function' === typeof FusionApp.callback[ callbackFunction[ 'function' ] ] ) {
reRender = this.doCallbackFunction( callbackFunction, false, param, value, modelData, true );
}
if ( reRender ) {
this.reRender();
}
}
},
historyUpdateParam: function( param, value ) {
var modelData = jQuery.extend( this.model.attributes, {} ),
reRender = true,
callbackFunction = false;
this.changeParam( param, value, false, true );
callbackFunction = FusionPageBuilderApp.getCallbackFunction( modelData, param, value, this, true );
if ( false !== callbackFunction && 'function' === typeof FusionApp.callback[ callbackFunction[ 'function' ] ] ) {
reRender = this.doCallbackFunction( callbackFunction, false, param, value, modelData, true );
}
if ( reRender ) {
this.reRender();
}
},
updateParam: function( param, value, event ) {
var modelData = jQuery.extend( this.model.attributes, {} ),
reRender = true,
callbackFunction = FusionPageBuilderApp.getCallbackFunction( modelData, param, value, this );
if ( false !== callbackFunction && 'function' === typeof FusionApp.callback[ callbackFunction[ 'function' ] ] ) {
reRender = this.doCallbackFunction( callbackFunction, event, param, value, modelData );
} else {
this.changeParam( param, value );
}
return reRender;
},
setInitialValue: function( param ) {
if ( 'undefined' !== typeof this.initialValue && 'undefined' === typeof this.initialValue[ param ] && 'undefined' !== typeof param ) {
this.initialValue[ param ] = 'undefined' !== typeof this.model.get( 'params' )[ param ] ? this.model.get( 'params' )[ param ] : '';
}
},
logChangeEvent: function( param, value, label ) {
this.logHistory._param = this.logHistory._param || {};
if ( ! ( param in this.logHistory._param ) ) {
this.logHistory._param[ param ] = _.debounce( _.bind( function( param, value, label ) {
var state = {
type: 'param',
param: param,
newValue: value,
cid: this.model.get( 'cid' )
},
elementMap = fusionAllElements[ this.model.get( 'element_type' ) ],
paramObject = elementMap.params[ param ],
paramTitle = 'object' === typeof paramObject ? paramObject.heading : param;
if ( 'undefined' !== typeof label ) {
paramTitle = label;
} else if ( 'object' !== typeof paramObject && jQuery( '.multi-builder-dimension #' + param ).length ) {
paramObject = elementMap.params[ jQuery( '.multi-builder-dimension #' + param ).closest( '.multi-builder-dimension' ).attr( 'id' ) ];
if ( 'object' === typeof paramObject && 'string' === typeof paramObject.heading ) {
paramTitle = paramObject.heading;
}
} else if ( 'object' !== typeof paramObject && jQuery( '.font_family #' + param ).length ) {
paramObject = elementMap.params[ jQuery( '.font_family #' + param ).closest( '.fusion-builder-option' ).attr( 'data-option-id' ) ];
if ( 'object' === typeof paramObject && 'string' === typeof paramObject.heading ) {
paramTitle = paramObject.heading;
}
} else if ( 'object' !== typeof paramObject && jQuery( '.typography [name="' + param + '"]' ).length ) {
paramObject = elementMap.params[ jQuery( '.typography [name="' + param + '"]' ).closest( '.fusion-builder-option' ).attr( 'data-option-id' ) ];
if ( 'object' === typeof paramObject && 'string' === typeof paramObject.heading ) {
paramTitle = paramObject.heading;
}
}
state.oldValue = this.initialValue[ param ];
delete this.initialValue[ param ];
this.model.trigger( 'change' );
FusionEvents.trigger( 'fusion-history-save-step', fusionBuilderText.edited + ' ' + elementMap.name + ' - ' + paramTitle, state );
}, this ), 500 );
}
this.logHistory._param[ param ]( param, value, label );
},
changeParam: function( param, value, label, silent ) {
var parentView;
if ( ! silent && ! this.model.get( 'inlineElement' ) ) {
this.setInitialValue( param );
this.model.attributes.params[ param ] = value;
// Update parent after param has been changed.
if ( 'multi_element_child' === this.model.get( 'multi' ) ) {
parentView = FusionPageBuilderViewManager.getView( this.model.get( 'parent' ) );
if ( parentView && 'function' === typeof parentView.updateElementContent ) {
parentView.updateElementContent();
}
}
this.logChangeEvent( param, value, label );
} else {
this.model.attributes.params[ param ] = value;
}
if ( 'function' === typeof this.updateInlineParams && 'fusion_builder_form_step' === this.model.get( 'element_type' ) ) {
this.updateInlineParams( param, value );
}
},
/**
* Gets callback function for option change.
*
* @since 2.0.0
* @return {void}
*/
doCallbackFunction: function( callbackFunction, event, paramName, paramValue, modelData, skipChange ) {
var reRender = true,
returnData;
callbackFunction.args = 'undefined' === typeof callbackFunction.args ? {} : callbackFunction.args;
callbackFunction.ajax = 'undefined' === typeof callbackFunction.ajax ? false : callbackFunction.ajax;
callbackFunction.action = 'undefined' === typeof callbackFunction.action ? false : callbackFunction.action;
skipChange = 'undefined' === typeof skipChange ? false : skipChange;
// If skip is set then param will not be changed.
callbackFunction.args.skip = skipChange;
// If ajax trigger via debounce, else do it here and retun data.
if ( callbackFunction.ajax ) {
reRender = false;
this.addLoadingOverlay();
this._triggerCallback( event, callbackFunction, paramName, paramValue, modelData.cid, modelData );
} else {
returnData = FusionApp.callback[ callbackFunction[ 'function' ] ]( paramName, paramValue, callbackFunction.args, this );
}
if ( 'undefined' !== typeof returnData && 'undefined' !== typeof returnData.render ) {
reRender = returnData.render;
}
return reRender;
},
/**
* Triggers a callback function.
*
* @since 2.0.0
* @param {Object} event - The event.
* @param {string|Object} callbackFunction - The callback function.
* @return {void}
*/
triggerCallback: function( event, callbackFunction, paramName, paramValue, cid, modelData ) {
if ( 'undefined' === typeof cid && 'undefined' !== typeof callbackFunction.cid ) {
cid = callbackFunction.cid;
}
if ( 'undefined' === typeof modelData ) {
modelData = jQuery.extend( this.model.attributes, {} );
}
// This is added due to the new elements causing max call stack. Not sure why but it shouldn't be necessary in any case.
if ( 'undefined' !== typeof modelData ) {
delete modelData.view;
}
if ( 'fusion_do_shortcode' !== callbackFunction[ 'function' ] ) {
FusionApp.callback[ callbackFunction[ 'function' ] ]( paramName, paramValue, modelData, callbackFunction.args, cid, callbackFunction.action, this.model, this );
} else {
FusionApp.callback[ callbackFunction[ 'function' ] ]( cid, callbackFunction.content, callbackFunction.parent );
}
},
addCssProperty: function ( selectors, property, value, important ) {
if ( 'object' === typeof selectors ) {
selectors = Object.values( selectors );
}
if ( 'object' === typeof selectors ) {
selectors = selectors.join( ',' );
}
if ( 'object' !== typeof this.dynamic_css[ selectors ] ) {
this.dynamic_css[ selectors ] = {};
}
if ( 'undefined' !== typeof important && important ) {
value += ' !important';
}
if ( 'undefined' === typeof this.dynamic_css[ selectors ][ property ] || ( 'undefined' !== typeof important && important ) || ! this.dynamic_css[ selectors ][ property ].includes( 'important' ) ) {
this.dynamic_css[ selectors ][ property ] = value;
}
},
/**
* Get a string with each of the option as a CSS variable, if the option is not default.
*
* @since 3.9
* @param {array} options The array with the options ids.
* @return {string}
*/
getCssVarsForOptions( options ) {
var css = '',
varName,
value,
callback_args,
key;
for ( key in options ) {
if ( ! options.hasOwnProperty( key ) || 'length' === key ) {
continue; // eslint-disable-line no-continue
}
value = options[ key ];
if ( 'object' === typeof value ) { // If the value is an array, then the CSS var name is the key.
if ( ! this.isDefault( key ) ) {
varName = '--awb-' + key.replaceAll( '_', '-' );
callback_args = ( 'object' === typeof value.args ? value.args : [ this.values[ key ] ] );
css += varName + ':' + value.callback.apply( null, callback_args ) + ';';
}
} else {
if ( ! this.isDefault( value ) ) { // eslint-disable-line no-lonely-if
varName = '--awb-' + value.replaceAll( '_', '-' );
css += varName + ':' + this.values[ value ] + ';';
}
}
}
return css;
},
/**
* Get a string with custom CSS variables, created from array key => value pairs.
*
* @since 3.9
* @param {Object} $options The object with the custom css vars. The property
* represents the option name, while the value represents the custom value.
* @return {string}
*/
getCustomCssVars( options, prefix ) {
var css = '',
varName,
property;
if ( 'undefined' === typeof prefix ) {
prefix = true;
}
for ( property in options ) {
if ( ! options.hasOwnProperty( property ) ) {
continue; // eslint-disable-line no-continue
}
if ( prefix ) {
varName = '--awb-' + property.replaceAll( '_', '-' );
} else {
varName = '--' + property;
}
css += varName + ':' + options[ property ] + ';';
}
return css;
},
/**
* Get declaration for typography vars with the given values.
*
* @since 3.9
* @param {string} titleTag An HTML tag, Ex: 'h2', 'h3', 'div'.. etc.
* @param {Object} nameValueMap The key is a css property, the array value is the CSS value.
* @return string
*/
getHeadingFontVars( titleTag, nameValueMap ) {
var varPrefix = '',
cssProp,
style = '';
if ( [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ].includes( titleTag ) ) {
varPrefix = '--' + titleTag + '_typography-';
} else if ( 'div' === titleTag || 'p' === titleTag ) {
varPrefix = '--body_typography-';
} else {
return style;
}
for ( cssProp in nameValueMap ) {
if ( nameValueMap[ cssProp ] && '' !== nameValueMap[ cssProp ] ) {
style += varPrefix + cssProp + ':' + nameValueMap[ cssProp ] + ';';
}
}
return style;
},
/**
* Get a string with all the border radius CSS variables.
* @since 3.9
* @param {array} options The array with the options ids.
* @return {string}
*/
getBorderRadiusVars( options ) {
var style = '',
varName,
edges = {
'border_radius_top_left': 'border-top-left-radius',
'border_radius_top_right': 'border-top-right-radius',
'border_radius_bottom_left': 'border-bottom-left-radius',
'border_radius_bottom_right': 'border-bottom-right-radius'
};
for ( varName in edges ) {
if ( options.hasOwnProperty( varName ) && '' !== options[ varName ] ) {
style += '--awb-' + edges[ varName ] + ':' + options[ varName ] + ';';
}
}
return style;
},
isDefault: function( param ) {
return this.values[ param ] === fusionAllElements[ this.model.get( 'element_type' ) ].defaults[ param ];
},
/**
* Get font styling vars, created from _.fusionGetFontStyle helper.
*
* @since 3.9
* @param string key typography options key.
* @param object values the values object.
* @return string
*/
getFontStylingVars( key, values ) {
let css = '';
const font_styles = _.fusionGetFontStyle( key, values, 'object' );
Object.keys( font_styles ).forEach( ( rule ) => {
const value = font_styles[ rule ];
key = key.replace( '_font', '' );
let name = key + '-' + rule;
name = name.replaceAll( '_', '-' );
css += `--awb-${name}: ${value};`;
} );
return css;
},
/**
* Get aspect ratio vars.
*
* @since 3.9
* @param object values the values object.
* @return string
*/
getAspectRatioVars( values ) {
if ( '' === values.aspect_ratio ) {
return '';
}
let css = '';
// Calc Ratio
if ( 'custom' === values.aspect_ratio && '' !== values.custom_aspect_ratio ) {
css += '--awb-aspect-ratio: 100 / ' + values.custom_aspect_ratio + ';';
} else {
const aspectRatio = values.aspect_ratio.split( '-' ),
width = aspectRatio[ 0 ] || '',
height = aspectRatio[ 1 ] || '';
css += `--awb-aspect-ratio: ${width / height};`;
}
//Ratio Position
if ( '' !== values.aspect_ratio_position ) {
css += '--awb-object-position:' + values.aspect_ratio_position + ';';
}
return css;
},
/**
* Check if parent using dynamic content.
*
* @since 3.11
* @param object values the values object.
* @return string
*/
isParentHasDynamicContent( values ) {
if ( values.dynamic_params ) {
let dynamicData = FusionPageBuilderApp.base64Decode( values.dynamic_params );
dynamicData = _.unescape( dynamicData );
dynamicData = JSON.parse( dynamicData );
return dynamicData.parent_dynamic_content ? true : false;
}
return false;
},
parseCSS: function () {
var css = '';
if ( 'object' !== typeof this.dynamic_css ) {
return '';
}
_.each( this.dynamic_css, function ( properties, selector ) {
if ( 'object' === typeof properties ) {
css += selector + '{';
_.each( properties, function ( value, property ) {
css += property + ':' + value + ';';
} );
css += '}';
}
} );
return css;
},
// Scroll to element and highlight it.
scrollHighlight: function( scroll = true, highlight = true ) {
var $trigger = jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( '.fusion-one-page-text-link' ),
$el = this.$el,
elementIdAdded = false,
$highlightedEl,
elId = $el.attr( 'id' );
scroll = 'undefined' === typeof scroll ? true : scroll;
if ( ! elId ) {
$el.attr( 'id', 'fusion-temporary-id-' + this.cid );
elId = 'fusion-temporary-id-' + this.cid;
elementIdAdded = true;
}
setTimeout( function() {
if ( scroll && $trigger.length && 'function' === typeof $trigger.fusion_scroll_to_anchor_target ) {
$trigger.attr( 'href', '#' + elId ).fusion_scroll_to_anchor_target( 15 );
}
if ( elementIdAdded ) {
setTimeout( function() {
$el.removeAttr( 'id' );
}, 10 );
}
if ( highlight ) {
$highlightedEl = $el;
// This is intended to be only for columns.
if ( $el.find( '> .fusion-column-wrapper' ).length ) {
$highlightedEl = $el.find( '> .fusion-column-wrapper' );
}
$highlightedEl.addClass( 'fusion-active-highlight' );
setTimeout( function() {
$highlightedEl.removeClass( 'fusion-active-highlight' );
}, 6000 );
}
}, 10 );
},
isString( s ) {
if ( 'string' === typeof s || s instanceof String ) {
return true;
}
return false;
}
} );
} );
}( jQuery ) );
;/* global FusionPageBuilderViewManager, FusionPageBuilderApp, FusionApp, FusionEvents, fusionBuilderText */
/* eslint no-shadow: 0 */
var FusionPageBuilder = FusionPageBuilder || {};
( function() {
jQuery( document ).ready( function() {
// Builder Row View
FusionPageBuilder.BaseRowView = window.wp.Backbone.View.extend( {
/**
* On init for both regular and nested columns.
*
* @since 3.0
* @return null
*/
baseRowInit: function() {
this._updateResponsiveColumnsOrder = _.debounce( this.updateResponsiveColumnsOrder, 100 );
},
reRender: function() {
this.render( true );
},
/**
* Calculate virtual rows.
*
* @since 2.0.0
* @return {null}
*/
createVirtualRows: function() {
var container = FusionPageBuilderApp.getParentContainer( this.model.get( 'parent' ) );
// If we are flex, no need for virtual rows.
if ( 'function' === typeof container.isFlex && container.isFlex() ) {
return;
}
this.updateVirtualRows();
this.assignColumn();
},
/**
* Set the initial column data to the model.
*
* @since 2.0.0
* @return {void}
*/
updateVirtualRows: function() {
var rows = {},
column = {},
columns = [],
count = 0,
index = 0,
oldRows = this.model.get( 'rows' ),
columnWidth;
this.model.children.each( function( child ) {
column = {};
columnWidth = child.attributes.params.type;
if ( ! columnWidth ) {
columnWidth = '1_1';
}
columnWidth = columnWidth.split( '_' );
columnWidth = columnWidth[ 0 ] / columnWidth[ 1 ];
count += columnWidth;
if ( 1 < count ) {
index += 1;
count = columnWidth;
}
column = {
cid: child.attributes.cid
};
if ( 'undefined' === typeof rows[ index ] ) {
rows[ index ] = [ column ];
} else {
rows[ index ].push( column );
}
columns[ child.attributes.cid ] = index;
} );
this.model.set( 'columns', columns );
this.model.set( 'rows', rows );
if ( 'object' === typeof oldRows ) {
this.model.set( 'oldRows', oldRows );
}
},
/**
* Change the column in the model.
*
* @since 2.0.0
* @param {Object} column - The column view.
* @return {void}
*/
assignColumn: function() {
var columnParams,
self = this,
oldRows = this.model.get( 'oldRows' ),
updatedCols = false,
emptySpacing = true;
// Reset first, last positions
this.model.children.each( function( column ) {
columnParams = jQuery.extend( true, {}, column.get( 'params' ) );
columnParams.first = false;
columnParams.last = false;
column.set( 'params', columnParams );
} );
// Loop over virtual rows
_.each( this.model.get( 'rows' ), function( row, rowIndex ) {
var total = row.length,
lastIndex = total - 1,
rowSame = true,
previousSpacing = '';
// Loop over columns inside virtual row
_.each( row, function( col, colIndex ) {
var columnFirst = false,
columnLast = false,
model = self.model.children.find( function( model ) {
return model.get( 'cid' ) == col.cid; // jshint ignore: line
} ),
params = jQuery.extend( true, {}, model.get( 'params' ) ),
spacing,
weightedSpacing;
// First index
if ( 0 === colIndex ) {
columnFirst = true;
}
if ( lastIndex === colIndex ) {
columnLast = true;
}
params.first = columnFirst;
params.last = columnLast;
// Check if we need legacy column spacing set.
if ( 'undefined' !== typeof params.spacing && FusionPageBuilderApp.loaded ) {
spacing = params.spacing;
if ( 'yes' === spacing ) {
spacing = '4%';
} else if ( 'no' === spacing ) {
spacing = '0px';
}
if ( ! params.last && '0px' !== spacing && 0 !== spacing && '0' !== spacing ) {
emptySpacing = false;
}
weightedSpacing = self.getWeightedSpacing( spacing, params, total );
// Only set params if both are unset.
if ( 'undefined' === typeof params.spacing_left && 'undefined' === typeof params.spacing_right ) {
// Use what is set as right spacing.
if ( ! params.last ) {
params.spacing_right = weightedSpacing;
}
// Check right spacing of previous column.
if ( '' !== previousSpacing ) {
params.spacing_left = self.getWeightedSpacing( previousSpacing, params, total );
}
}
previousSpacing = spacing;
} else {
emptySpacing = false;
}
model.set( 'params', params );
// Check if col is same as before.
if ( rowSame ) {
if ( 'object' !== typeof oldRows || 'undefined' === typeof oldRows[ rowIndex ] || 'undefined' === typeof oldRows[ rowIndex ][ colIndex ] || oldRows[ rowIndex ][ colIndex ].cid !== col.cid ) {
rowSame = false;
}
}
} );
if ( ! rowSame && FusionPageBuilderApp.loaded ) {
if ( false === updatedCols ) {
updatedCols = [];
}
_.each( row, function( col ) {
updatedCols.push( col.cid );
} );
}
} );
this.model.set( 'emptySpacing', emptySpacing );
this.model.set( 'updatedCols', updatedCols );
},
getVirtualRowByCID: function( cid ) {
var rows = this.model.get( 'rows' ),
columns = this.model.get( 'columns' ),
index = columns[ cid ],
row = rows[ index ];
return row;
},
/**
* First render, work out legacy column map only once.
*
* @since 2.0.0
* @return {Object} this
*/
legacyColumns: function() {
var container = FusionPageBuilderApp.getParentContainer( this.model.get( 'parent' ) ),
emptySpacing = false,
nestedRows = {};
// If we are not in need of legacy conversion then skip.
if ( ! container || ! container.needsLegacyConversion() ) {
return;
}
// Create map of row to get correct spacing.
this.updateVirtualRows();
this.assignColumn();
if ( ! this.nestedRow ) {
// This row is all empty spacing.
emptySpacing = this.model.get( 'emptySpacing' );
// Run through same process for nested rows.
this.$el.find( '.fusion-builder-row-inner' ).each( function() {
var nestedRowCid = jQuery( this ).attr( 'data-cid' ),
nestedView = FusionPageBuilderViewManager.getView( nestedRowCid );
// Store for later looping if necessary.
nestedRows[ nestedRowCid ] = nestedView;
// Update legacy maps and nested column styles.
nestedView.legacyColumns();
// If nested row is not empty spacing, parent row shouldn't be also.
if ( false === nestedView.model.get( 'emptySpacing' ) ) {
emptySpacing = false;
}
} );
// If its empty spacing and all nested rows also, we will set spacing on container and re-render.
if ( emptySpacing ) {
// Set the spacing on container.
container = FusionPageBuilderApp.getParentContainer( this.model.get( 'parent' ) );
if ( container ) {
container.setEmptySpacing();
}
// If we have nested rows, update them visually.
if ( 'object' === typeof nestedRows && ! _.isEmpty( nestedRows ) ) {
_.each( nestedRows, function( nestedRow ) {
nestedRow.recalculateMargins();
} );
}
// Update parent row visually.
this.recalculateMargins();
}
}
// Update visual appearance for direct children columns.
this.model.children.each( function( child ) {
var view = FusionPageBuilderViewManager.getView( child.attributes.cid );
view.setArgs();
view.validateArgs();
view.setExtraArgs();
view.setColumnMapData();
view.setResponsiveColumnStyles();
view.$el.find( '.fusion-column-responsive-styles' ).last().html( view.responsiveStyles );
} );
// Set param on container to stop it rerunning.
if ( container && 'function' === typeof container.setType ) {
container.setType();
}
},
getHalfSpacing: function( value ) {
var unitlessSpacing = parseFloat( value ),
unitlessHalf = unitlessSpacing / 2;
return value.replace( unitlessSpacing, unitlessHalf );
},
validateColumnWidth: function( columnSize ) {
var fractions;
if ( 'undefined' === typeof columnSize ) {
columnSize = '1_3';
}
// Fractional value.
if ( -1 !== columnSize.indexOf( '_' ) ) {
fractions = columnSize.split( '_' );
return parseFloat( fractions[ 0 ] ) / parseFloat( fractions[ 1 ] );
}
// Greater than one, assume percentage and divide by 100.
if ( 1 < parseFloat( columnSize ) ) {
return parseFloat( columnSize ) / 100;
}
return columnSize;
},
getWeightedSpacing: function( value, params, total ) {
var width = parseFloat( this.validateColumnWidth( params.type ) ),
unitlessSpacing = parseFloat( value ),
unitlessWeighted;
total = 'undefined' === typeof total || false === total ? false : parseInt( total );
if ( false !== total && 3 > total ) {
unitlessWeighted = unitlessSpacing * width;
} else {
unitlessWeighted = unitlessSpacing / 2;
}
return value.replace( unitlessSpacing, unitlessWeighted );
},
updateColumnsPreview: function() {
var container = FusionPageBuilderApp.getParentContainer( this.model.get( 'parent' ) ),
updatedCols = this.model.get( 'updatedCols' ),
self = this;
// Update flex column preview here.
if ( 'function' === typeof container.isFlex && container.isFlex() ) {
return;
}
if ( true === FusionPageBuilderApp.loaded ) {
this.model.children.each( function( child ) {
var view,
singleRow,
columnRow;
if ( false === updatedCols || _.contains( updatedCols, child.attributes.cid ) ) {
view = FusionPageBuilderViewManager.getView( child.attributes.cid );
singleRow = self.getVirtualRowByCID( view.model.get( 'cid' ) );
columnRow = [];
// Update first/last classes
view.$el.removeClass( 'fusion-column-last' );
view.$el.removeClass( 'fusion-column-first' );
if ( true === view.model.attributes.params.last ) {
view.$el.addClass( 'fusion-column-last' );
}
if ( true === view.model.attributes.params.first ) {
view.$el.addClass( 'fusion-column-first' );
}
// Update column spacing.
_.each( singleRow, function( cid ) {
var model,
value;
cid = cid.cid;
model = self.collection.find( function( model ) {
return model.get( 'cid' ) == cid; // jshint ignore: line
} );
value = model.attributes.params.spacing;
columnRow.push( value );
} );
view.columnSpacingPreview( columnRow );
}
} );
}
},
/**
* Sets the row data.
*
* @since 2.0.0
* @return {void}
*/
setRowData: function() {
this.createVirtualRows();
this.updateColumnsPreview();
},
setSingleRowData: function( cid ) {
var row = this.getVirtualRowByCID( cid ),
view;
_.each( row, function( column ) {
view = FusionPageBuilderViewManager.getView( column.cid );
view.reRender();
} );
},
/**
* Mode change for container.
*
* @since 3.0
* @return {void}
*/
modeChange: function() {
this.setRowData();
this.reRender( true );
this.reRenderColumns();
// Refresh nested rows if they exist.
if ( ! this.nestedRow ) {
this.reRenderNestedRows();
}
},
/**
* Mode change for container.
*
* @since 3.0
* @return {void}
*/
updateInnerStyles: function() {
this.setRowData();
this.reRender( true );
if ( this.nestedRow ) {
this.appendChildren( false );
}
this.model.children.each( function( child ) {
var cid = child.attributes.cid;
var column = FusionPageBuilderViewManager.getView( cid );
if ( column ) {
column.updateInnerStyles();
}
} );
// Refresh nested rows if they exist.
if ( ! this.nestedRow ) {
this.$el.find( '.fusion_builder_row_inner' ).each( function( ) {
var cid = jQuery( this ).attr( 'data-cid' ),
row = FusionPageBuilderViewManager.getView( cid );
if ( row ) {
row.updateInnerStyles();
}
} );
}
this.delegateChildEvents();
},
/**
* Re-render the nested rows.
*
* @since 3.0
* @return {void}
*/
reRenderNestedRows: function() {
this.$el.find( '.fusion_builder_row_inner' ).each( function( ) {
var cid = jQuery( this ).attr( 'data-cid' ),
row = FusionPageBuilderViewManager.getView( cid );
if ( 'object' === typeof row ) {
row.modeChange();
row.appendChildren();
}
} );
},
/**
* Re-render columns
*
* @since 3.0
* @return {void}
*/
reRenderColumns: function() {
var cid,
view;
this.model.children.each( function( child ) {
cid = child.attributes.cid;
view = FusionPageBuilderViewManager.getView( cid );
if ( view ) {
view.reRender();
}
} );
},
/**
* Updates columns' order params.
* @return {void}
*/
updateResponsiveColumnsOrder: function( draggedColumn, columns, targetColumnCID, insertAfterTargetColumn ) {
var viewportSize = FusionApp.getPreviewWindowSize(),
draggedColumnCID = parseInt( draggedColumn.data( 'cid' ) ),
draggedColumnOrder = parseInt( draggedColumn.css( 'order' ) ),
columnsArray = [],
index = 0,
columnView;
if ( 'large' === viewportSize ) {
return;
}
jQuery( columns ).each( function( scopedIndex, column ) {
// TODO: handle case when multiple columns have same order set.
if ( draggedColumnCID !== jQuery( column ).data( 'cid' ) ) {
columnsArray.push( [ parseInt( jQuery( column ).data( 'cid' ) ), parseInt( jQuery( column ).css( 'order' ) ) ] );
}
} );
// Sort columns by CSS order.
columnsArray.sort( function( col1, col2 ) {
return col1[ 1 ] - col2[ 1 ];
} );
// Find index (position) of target column.
for ( index = 0; index < columnsArray.length; index++ ) {
if ( targetColumnCID === columnsArray[ index ][ 0 ] ) {
break;
}
}
// In case we're inserting before target column.
if ( ! insertAfterTargetColumn ) {
index--;
}
// Insert dragged column in it's place. Note that index is position in 'splice' context (not array index).
columnsArray.splice( index + 1, 0, [ draggedColumnCID, draggedColumnOrder ] );
// Index is not longer relevant, using it just as iterator.
for ( index = 0; index < columnsArray.length; index++ ) {
// Get column view by CID.
columnView = FusionPageBuilderViewManager.getView( columnsArray[ index ][ 0 ] );
// Update order param and value.
columnView.model.attributes.params[ 'order_' + viewportSize ] = index;
columnView.values[ 'order_' + viewportSize ] = index;
// Update column's responsive styles.
columnView.setResponsiveColumnStyles();
columnView.$el.find( '.fusion-column-responsive-styles' ).last().html( columnView.responsiveStyles );
// Update EO panel if opened.
if ( jQuery( '.fusion-builder-module-settings[data-element-cid="' + columnsArray[ index ][ 0 ] + '"' ) ) {
FusionEvents.trigger( 'fusion-param-changed-' + columnView.model.get( 'cid' ), 'order_' + viewportSize, index );
}
}
// Trigger change and add history event.
FusionEvents.trigger( 'fusion-history-save-step', fusionBuilderText.column + ' Order Changed' );
},
scrollHighlight: function( scroll = true, highlight = true ) {
var $trigger = jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( '.fusion-one-page-text-link' ),
$el = this.$el,
elementIdAdded = false,
elId = $el.attr( 'id' );
scroll = 'undefined' === typeof scroll ? true : scroll;
if ( ! elId ) {
$el.attr( 'id', 'fusion-temporary-id-' + this.cid );
elId = 'fusion-temporary-id-' + this.cid;
elementIdAdded = true;
}
setTimeout( function() {
if ( scroll && $trigger.length && 'function' === typeof $trigger.fusion_scroll_to_anchor_target ) {
$trigger.attr( 'href', '#' + elId ).fusion_scroll_to_anchor_target( 15 );
}
if ( elementIdAdded ) {
setTimeout( function() {
$el.removeAttr( 'id' );
}, 10 );
}
if ( highlight ) {
$el.addClass( 'fusion-active-highlight' );
setTimeout( function() {
$el.removeClass( 'fusion-active-highlight' );
}, 6000 );
}
}, 10 );
}
} );
} );
}( jQuery ) );
;/* global FusionApp, fusionBuilderText, fusionAllElements, cssua, FusionPageBuilderViewManager, FusionPageBuilderApp, FusionEvents, fusionSettings */
/* eslint no-unused-vars: 0 */
/* eslint no-shadow: 0 */
var FusionPageBuilder = FusionPageBuilder || {};
( function() {
jQuery( document ).ready( function() {
// Nested Column View
FusionPageBuilder.BaseColumnView = FusionPageBuilder.BaseView.extend( {
/**
* On init for both regular and nested columns.
*
* @since 3.0
* @return null
*/
baseColumnInit: function() {
this.model.children = new FusionPageBuilder.Collection();
this.listenTo( FusionEvents, 'fusion-param-changed-' + this.model.get( 'cid' ), this.onOptionChange );
this.listenTo( this.model.children, 'add', this.addChildView );
// Responsive control updates on resize.
this.listenTo( FusionEvents, 'fusion-preview-viewport-update', this.onPreviewResize );
this._triggerCallback = _.debounce( _.bind( this.triggerCallback, this ), 200 );
this._toolTipHide = _.debounce( _.bind( this.toolTipHide, this ), 500 );
this._refreshJs = _.debounce( _.bind( this.refreshJs, this ), 300 );
this._equalHeights = _.debounce( _.bind( this.equalHeights, this ), 300 );
this.deprecatedParams();
// Hold the DOM elements for resizables.
this.marginResize = {};
this.paddingResize = {};
},
/**
* Runs before view DOM is patched.
*
* @since 2.0.0
* @return null
*/
beforePatch: function() {}, // eslint-disable-line no-empty-function
/**
* Runs after view DOM is patched.
*
* @since 2.0.0
* @return null
*/
afterPatch: function() {
var self = this;
if ( 'undefined' !== typeof this.model.attributes.selectors ) {
if ( this.model.get( 'dragging' ) ) {
this.model.attributes.selectors.style += ';display: none;';
this.model.attributes.selectors[ 'class' ] += ' ignore-me-column';
}
this.$el.removeAttr( 'data-animationType' );
this.$el.removeAttr( 'data-animationDuration' );
this.$el.removeAttr( 'data-animationOffset' );
this.setElementAttributes( this.$el, this.model.attributes.selectors );
}
if ( this.forceAppendChildren ) {
this.appendChildren();
this.forceAppendChildren = false;
}
setTimeout( function() {
self.droppableColumn();
}, 300 );
this._refreshJs();
},
/**
* Delegates multiple child elements.
*
* @since 2.0.0
* @return {void}
*/
delegateChildEvents: function() {
var cid,
view;
this.model.children.each( function( child ) {
cid = child.attributes.cid;
view = FusionPageBuilderViewManager.getView( cid );
view.delegateEvents();
// Re init for elements.
if ( 'function' === typeof view.droppableElement ) {
view.droppableElement();
}
// Re init for nested row.
if ( 'function' === typeof view.droppableColumn ) {
view.droppableColumn();
}
// Multi elements
if ( 'undefined' !== typeof view.model.get( 'multi' ) && 'multi_element_parent' === view.model.get( 'multi' ) ) {
view.delegateChildEvents();
view.sortableChildren();
}
} );
},
updateInnerStyles: function() {
this.setArgs();
this.validateArgs();
this.setExtraArgs();
this.setColumnMapData();
this.setResponsiveColumnStyles();
this.$el.find( '.fusion-column-responsive-styles' ).last().html( this.responsiveStyles );
const attr = this.buildAttr();
this.$el.attr( 'style', attr.style );
this.delegateChildEvents();
},
/**
* Checks if the width is custom.
*
* @since 2.1
* @return {bool}
*/
isCustomWidth: function ( width ) {
if ( 'string' === typeof width && ( width.includes( 'px' ) || width.includes( 'calc' ) ) ) {
return true;
}
return false;
},
/**
* Updates now deprecated params and adds BC checks.
*
* @since 2.1
* @return {void}
*/
deprecatedParams: function() {
var params = this.model.get( 'params' ),
alphaBackgroundColor = 1,
radiaDirectionsNew = { 'bottom': 'center bottom', 'bottom center': 'center bottom', 'left': 'left center', 'right': 'right center', 'top': 'center top', 'center': 'center center', 'center left': 'left center' },
borderSize;
// Correct radial direction params.
if ( 'undefined' !== typeof params.radial_direction && ( params.radial_direction in radiaDirectionsNew ) ) {
params.radial_direction = radiaDirectionsNew[ params.radial_direction ];
}
// No align self set but ignore equal heights is on.
if ( 'undefined' === typeof params.align_self && 'undefined' !== typeof params.min_height && 'none' === params.min_height ) {
params.align_self = 'flex-start';
}
// No align content set, but legacy center_content is on.
if ( 'undefined' === typeof params.align_content && 'undefined' !== typeof params.center_content && 'yes' === params.center_content ) {
params.align_content = 'center';
}
// Border sizes.
if ( ( 'undefined' === typeof params.border_sizes_top || 'undefined' === typeof params.border_sizes_bottom || 'undefined' === typeof params.border_sizes_left || 'undefined' === typeof params.border_sizes_right ) && 'string' === typeof params.border_size ) {
if ( 'all' === params.border_position ) {
borderSize = _.fusionGetValueWithUnit( params.border_size );
params.border_sizes_top = borderSize;
params.border_sizes_bottom = borderSize;
params.border_sizes_left = borderSize;
params.border_sizes_right = borderSize;
} else {
params[ 'border_sizes_' + params.border_position ] = _.fusionGetValueWithUnit( params.border_size );
}
delete params.border_size;
}
this.model.set( 'params', params );
},
/**
* Handle margin adjustments on drag.
*
* @since 2.0.0
* @return {void}
*/
marginDrag: function() {
var $el = this.$el,
self = this,
directions = { top: 's', bottom: 's' },
parentWidth = 'fusion_builder_column_inner' === this.model.get( 'type' ) ? $el.closest( '.fusion-builder-row-container-inner' ).width() : $el.closest( '.fusion-row' ).width(),
isFlex = false,
widthType = self.getVisibleWidth(),
$spacers = this.$el.find( '> .fusion-column-wrapper > .fusion-column-spacers, > .fusion-column-margins' );
// If flex we also use left and right.
if ( 'undefined' !== typeof this.isFlex && true === this.isFlex ) {
directions = { top: 's', bottom: 's', left: 'e', right: 'w' };
isFlex = true;
}
// If class is set, do not init again.
if ( this.$el.hasClass( 'resizable-active' ) ) {
return;
}
// Single post card, margin is not used.
if ( 'fusion_builder_column_inner' !== this.model.get( 'type' ) && 'post_cards' === FusionApp.data.fusion_element_type ) {
return;
}
_.each( directions, function( handle, direction ) {
var optionKey = FusionApp.getResponsiveOptionKey( 'top' === direction || 'bottom' === direction ? 'margin_' + direction : 'spacing_' + direction, self.isFlex ),
actualDimension = self.values[ optionKey ],
percentSpacing = false;
// No value, use half column spacing (not upsized).
if ( isFlex && ( ! actualDimension || '' === actualDimension ) && ( 'top' === direction || 'bottom' === direction ) ) {
if ( self.values[ 'margin_' + direction ] ) {
actualDimension = self.values[ 'margin_' + direction ];
}
if ( optionKey.includes( 'small' ) && '' !== self.values[ 'margin_' + direction + '_medium' ] ) {
actualDimension = self.values[ 'margin_' + direction + '_medium' ];
}
}
if ( ! actualDimension ) {
actualDimension = self.getHalfSpacing();
}
// Check if using a percentage.
percentSpacing = -1 !== actualDimension.indexOf( '%' );
// If percentage, get the actual px dimension.
if ( percentSpacing ) {
actualDimension = ( parentWidth / 100 ) * parseFloat( actualDimension );
}
// Overlap checks.
if ( 'bottom' === direction ) {
if ( 20 > parseInt( actualDimension, 10 ) ) {
$spacers.find( '.fusion-column-margin-bottom, .fusion-column-padding-bottom' ).addClass( 'fusion-overlap' );
} else {
$spacers.find( '.fusion-column-margin-bottom, .fusion-column-padding-bottom' ).removeClass( 'fusion-overlap' );
}
}
// Find element and display it.
self.marginResize[ direction ] = $spacers.find( '.fusion-column-margin-' + direction );
self.marginResize[ direction ].css( 'display', 'block' );
// Set initial width or height.
if ( 'left' === direction || 'right' === direction ) {
if ( percentSpacing && 'custom' === widthType ) {
self.marginResize[ direction ].width( 0 );
} else {
self.marginResize[ direction ].width( actualDimension );
}
} else {
self.marginResize[ direction ].height( actualDimension );
}
// Init resizable.
self.marginResize[ direction ].resizable( {
handles: handle,
minHeight: 0,
minWidth: 0,
grid: ( percentSpacing ) ? [ parentWidth / 1000, 10 ] : '',
resize: function( event, ui ) {
var optionKey = FusionApp.getResponsiveOptionKey( 'top' === direction || 'bottom' === direction ? 'margin_' + direction : 'spacing_' + direction, self.isFlex ),
percentSpacing = 'undefined' !== typeof self.values[ optionKey ] ? -1 !== self.values[ optionKey ].indexOf( '%' ) : false,
$resizer = jQuery( ui.element ),
value = 'top' === direction || 'bottom' === direction ? ui.size.height : ui.size.width;
// If nothing is set and left and right, check row column spacing
if ( '' === self.values[ optionKey ] && ( 'left' === direction || 'right' === direction ) ) {
percentSpacing = -1 !== self.getHalfSpacing().indexOf( '%' );
}
// Active class to prevent multiple inits.
$resizer.closest( '.fusion-builder-column:not( .resizable-active )' ).addClass( 'resizable-active' );
// Work out value.
value = 0 > value ? 0 : value;
value = value + 'px';
if ( percentSpacing ) {
value = 0 === parseFloat( value ) ? '0%' : ( Math.round( parseFloat( parseFloat( value ) / ( parentWidth / 1000 ) ) ) / 10 ) + '%';
}
// Bottom margin overlap
if ( 'bottom' === direction ) {
if ( 20 > ui.size.height ) {
$resizer.addClass( 'fusion-overlap' );
$spacers.find( '.fusion-column-padding-bottom' ).addClass( 'fusion-overlap' );
} else {
$resizer.removeClass( 'fusion-overlap' );
$spacers.find( '.fusion-column-padding-bottom' ).removeClass( 'fusion-overlap' );
}
}
// Display tooltip.
$resizer.find( '.fusion-spacing-tooltip, .fusion-column-spacing' ).addClass( 'active' );
$resizer.find( '.fusion-spacing-tooltip' ).text( value );
// Update open settings modal.
self.updateDragSettings( '#' + optionKey, value );
},
stop: function( event, ui ) {
var $resizer = jQuery( ui.element );
$resizer.closest( '.fusion-builder-column' ).removeClass( 'resizable-active' );
$resizer.find( '.fusion-spacing-tooltip, .fusion-column-spacing' ).removeClass( 'active' );
// Delete all spacing resizable within because parent width has changed.
if ( $resizer.find( '.fusion-builder-column-inner' ).find( '.fusion-element-spacing .ui-resizable' ).length ) {
$resizer.closest( '.fusion-builder-column-inner' ).find( '.fusion-element-spacing .ui-resizable' ).resizable( 'destroy' );
}
}
} );
} );
},
/**
* Handle padding adjustments on drag.
*
* @since 2.0.0
* @return {void}
*/
paddingDrag: function() {
var $el = this.$el,
self = this,
directions = { top: 's', right: 'w', bottom: 's', left: 'e' },
percentSpacing = false,
parentWidth = $el.find( '> .fusion-column-wrapper' ).first().width(),
$spacers = this.$el.find( '> .fusion-column-wrapper > .fusion-column-spacers, > .fusion-column-margins' ),
valueAllowed = ( parentWidth / 100 ),
isFlex = false,
value,
actualDimension;
if ( this.$el.hasClass( 'resizable-active' ) ) {
return;
}
if ( 'undefined' !== typeof this.isFlex && true === this.isFlex ) {
isFlex = true;
}
_.each( directions, function( handle, direction ) {
var optionKey = FusionApp.getResponsiveOptionKey( 'padding_' + direction, isFlex ),
actualDimension = self.values[ optionKey ] || self.values[ 'padding_' + direction ],
percentSpacing = false;
if ( ! isFlex && ! actualDimension ) {
actualDimension = '0px';
}
// Check if using a percentage.
percentSpacing = 'undefined' !== typeof actualDimension ? -1 !== actualDimension.indexOf( '%' ) : false;
if ( percentSpacing ) {
// Get actual dimension and set.
actualDimension = ( parentWidth / 100 ) * parseFloat( actualDimension );
}
if ( 'bottom' !== direction && ( isFlex || 'top' === direction ) ) {
if ( 20 > parseInt( actualDimension, 10 ) ) {
$spacers.find( '.fusion-column-margin-' + direction + ', .fusion-column-padding-' + direction ).addClass( 'fusion-overlap' );
} else {
$spacers.find( '.fusion-column-margin-' + direction + ', .fusion-column-padding-' + direction ).removeClass( 'fusion-overlap' );
}
}
self.paddingResize[ direction ] = $spacers.find( '.fusion-column-padding-' + direction );
self.paddingResize[ direction ].css( 'display', 'block' );
if ( 'top' === direction || 'bottom' === direction ) {
self.paddingResize[ direction ].height( actualDimension );
} else {
self.paddingResize[ direction ].width( actualDimension );
}
self.paddingResize[ direction ].resizable( {
handles: handle,
minHeight: 0,
minWidth: 0,
resize: function( event, ui ) {
var optionKey = FusionApp.getResponsiveOptionKey( 'padding_' + direction, isFlex ),
actualDimension = self.values[ optionKey ],
dimension = 'top' === direction || 'bottom' === direction ? 'height' : 'width',
$resizer = jQuery( ui.element );
// Recheck in case unit is changed in the modal.
percentSpacing = 'undefined' !== typeof actualDimension ? -1 !== actualDimension.indexOf( '%' ) : false;
// Force to grid amount.
if ( percentSpacing ) {
ui.size[ dimension ] = Math.round( ui.size[ dimension ] / valueAllowed ) * valueAllowed;
}
$resizer.closest( '.fusion-builder-column' ).addClass( 'resizable-active' );
// Change format of value.
value = ui.size[ dimension ];
value = 0 > value ? 0 : value;
value = value + 'px';
if ( percentSpacing ) {
value = 0 === parseFloat( value ) ? '0%' : Math.round( parseFloat( parseFloat( value ) / ( parentWidth / 100 ) ) ) + '%';
}
// Overlaps top left, right.
if ( 'top' === direction ) {
if ( 20 > ui.size.height ) {
$resizer.addClass( 'fusion-overlap' );
$spacers.find( '.fusion-column-margin-top' ).addClass( 'fusion-overlap' );
} else {
$resizer.removeClass( 'fusion-overlap' );
$spacers.find( '.fusion-column-margin-top' ).removeClass( 'fusion-overlap' );
}
} else if ( 'right' === direction ) {
if ( 20 > ui.size.width && ( isFlex || 20 > $spacers.find( '.fusion-column-spacing .fusion-spacing-value' ).width() ) ) {
$resizer.addClass( 'fusion-overlap' );
$spacers.find( '.fusion-column-spacing, .fusion-column-margin-right' ).addClass( 'fusion-overlap' );
} else {
$resizer.removeClass( 'fusion-overlap' );
$spacers.find( '.fusion-column-spacing, .fusion-column-margin-right' ).removeClass( 'fusion-overlap' );
}
} else if ( 'left' === direction && isFlex ) {
if ( 20 > ui.size.width ) {
$resizer.addClass( 'fusion-overlap' );
$spacers.find( '.fusion-column-margin-left' ).addClass( 'fusion-overlap' );
} else {
$resizer.removeClass( 'fusion-overlap' );
$spacers.find( '.fusion-column-margin-left' ).removeClass( 'fusion-overlap' );
}
}
// Set values.
$resizer.find( '.fusion-spacing-tooltip, .fusion-column-spacing' ).addClass( 'active' );
$resizer.find( '.fusion-spacing-tooltip' ).text( value );
// Update open modal.
self.updateDragSettings( '#' + optionKey, value );
},
stop: function( event, ui ) {
var $resizer = jQuery( ui.element );
$resizer.closest( '.fusion-builder-column' ).removeClass( 'resizable-active' );
$resizer.find( '.fusion-spacing-tooltip, .fusion-column-spacing' ).removeClass( 'active' );
// Delete all spacing resizable within because parent width has changed.
if ( $resizer.find( '.fusion-builder-column-inner' ).find( '.fusion-element-spacing .ui-resizable' ).length ) {
$resizer.closest( '.fusion-builder-column-inner' ).find( '.fusion-element-spacing .ui-resizable' ).resizable( 'destroy' );
}
}
} );
} );
},
/**
* Destroy column's resizables.
*
* @since 2.0.0
* @return {void}
*/
destroyResizable: function() {
this.destroySpacingResizable();
this.destroyMarginResizable();
this.destroyPaddingResizable();
},
/**
* Destroy column's spacing resizable.
*
* @since 2.0.0
* @return {void}
*/
destroySpacingResizable: function() {
var $columnSpacer;
$columnSpacer = this.$el.find( '> .fusion-column-spacing .fusion-spacing-value' );
if ( $columnSpacer.hasClass( 'ui-resizable' ) ) {
$columnSpacer.resizable( 'destroy' );
$columnSpacer.hide();
this.columnSpacer = false;
}
},
/**
* Destroy column's margin resizable.
*
* @since 2.0.0
* @return {void}
*/
destroyMarginResizable: function() {
_.each( this.marginResize, function( $marginResize ) {
if ( $marginResize.length && $marginResize.hasClass( 'ui-resizable' ) && -1 !== $marginResize.attr( 'class' ).indexOf( 'fusion-column-margin-' ) ) {
$marginResize.resizable( 'destroy' );
$marginResize.hide();
}
} );
},
/**
* Destroy column's padding resizable.
*
* @since 2.0.0
* @return {void}
*/
destroyPaddingResizable: function() {
_.each( this.paddingResize, function( $paddingResize ) {
if ( $paddingResize.length && $paddingResize.hasClass( 'ui-resizable' ) && -1 !== $paddingResize.attr( 'class' ).indexOf( 'fusion-column-padding-' ) ) {
$paddingResize.resizable( 'destroy' );
$paddingResize.hide();
}
} );
},
/**
* Changes the column spacing.
*
* @since 2.0.0
* @param {Object} event - The event.
* @return {void}
*/
columnSpacing: function( event ) {
var percentSpacing = false,
$el = this.$el,
self = this,
$spacers = this.$el.find( '> .fusion-column-wrapper > .fusion-column-spacers' ),
marginDirection = FusionPageBuilderApp.$el.hasClass( 'rtl' ) ? 'left' : 'right',
parentWidth,
marginRight,
container,
columnSpacing,
existingSpacing,
modelSpacing,
$columnSpacer,
maxWidth,
rightPadding,
rightOverlap;
// We don't need column spacing when flex container is used.
if ( 'undefined' !== typeof this.isFlex && true === this.isFlex ) {
return;
}
$columnSpacer = this.$el.find( '> .fusion-column-spacing .fusion-spacing-value' );
if ( event && 'event' !== event ) {
event.preventDefault();
}
// If responsive mode and columns are 1/1 hide and return.
if ( jQuery( '#fb-preview' ).width() < FusionApp.settings.content_break_point && FusionApp.settings.responsive ) {
$columnSpacer.hide();
return;
}
$columnSpacer.show();
// If this is the last column in a virtual row, then no handles.
if ( this.$el.hasClass( 'fusion-column-last' ) ) {
return;
}
// No resizer for fallback method.
if ( 'yes' === this.model.attributes.params.spacing || 'no' === this.model.attributes.params.spacing ) {
return;
}
existingSpacing = this.model.attributes.params.spacing;
if ( 'undefined' === typeof existingSpacing || '' === existingSpacing ) {
existingSpacing = '4%';
}
if ( 'no' === existingSpacing ) {
existingSpacing = '0';
}
// Already created spacer and not %, no need to continue.
if ( this.columnSpacer && -1 === existingSpacing.indexOf( '%' ) ) {
return;
}
// Get the container width.
container = FusionPageBuilderViewManager.getView( this.model.get( 'parent' ) );
if ( 'fusion_builder_column_inner' === this.model.get( 'type' ) ) {
parentWidth = container.$el.find( '.fusion-builder-row-container-inner' ).width();
} else {
parentWidth = container.$el.find( '.fusion-row' ).width();
}
// Already created spacer, % is being used and width is the same, no need to continue.
if ( this.columnSpacer && parentWidth === this.parentWidth ) {
return;
}
// Store parent width to compare.
this.parentWidth = parentWidth;
// Get the column right margin. In real usage use the model attribute.
columnSpacing = existingSpacing;
marginRight = existingSpacing;
// Set column spacing width.
if ( -1 !== existingSpacing.indexOf( '%' ) ) {
percentSpacing = true;
marginRight = parseFloat( marginRight ) / 100.0;
columnSpacing = marginRight * parentWidth;
}
// Set max width spacing.
maxWidth = parentWidth - 100;
// Destroy in case it's already active
if ( $columnSpacer.hasClass( 'ui-resizable' ) ) {
$columnSpacer.resizable( 'destroy' );
}
$columnSpacer.width( columnSpacing );
$columnSpacer.resizable( {
handles: FusionPageBuilderApp.$el.hasClass( 'rtl' ) ? 'w' : 'e',
minWidth: 0,
maxWidth: maxWidth,
grid: ( percentSpacing ) ? [ parentWidth / 100, 10 ] : '',
create: function() {
if ( 0 === $el.find( '> .fusion-column-spacing .fusion-spacing-value' ).width() ) {
$el.find( '> .fusion-column-spacing' ).addClass( 'empty' );
} else if ( $el.find( '> .fusion-column-spacing.empty' ).length ) {
$el.find( '> .fusion-column-spacing' ).removeClass( 'empty' );
}
},
resize: function( event, ui ) {
ui.size.width = 0 > ui.size.width ? 0 : ui.size.width;
if ( 0 === modelSpacing ) {
$el.find( '> .fusion-column-spacing' ).addClass( 'empty' );
} else if ( $el.find( '> .fusion-column-spacing.empty' ).length ) {
$el.find( '> .fusion-column-spacing' ).removeClass( 'empty' );
}
modelSpacing = ui.size.width + 'px';
if ( percentSpacing ) {
modelSpacing = Math.round( parseFloat( ui.size.width / ( parentWidth / 100 ) ) ) + '%';
}
$el.css( 'margin-' + marginDirection, modelSpacing );
// Update open modal.
if ( jQuery( '[data-element-cid="' + self.model.get( 'cid' ) + '"]' ).length ) {
jQuery( '[data-element-cid="' + self.model.get( 'cid' ) + '"] [data-option-id="spacing"] #spacing' ).val( modelSpacing ).trigger( 'change' );
}
$el.find( '> .fusion-column-spacing .fusion-spacing-tooltip, > .fusion-column-spacing' ).addClass( 'active' );
$el.find( '> .fusion-column-spacing .fusion-spacing-tooltip' ).text( modelSpacing );
$el.addClass( 'active-drag' );
self._toolTipHide();
// Right padding overlap.
if ( 20 > ui.size.width && 20 > $spacers.find( '.fusion-column-padding-' + marginDirection ).width() ) {
jQuery( ui.element ).parent().addClass( 'fusion-overlap' );
$spacers.find( '.fusion-column-padding-' + marginDirection ).addClass( 'fusion-overlap' );
} else {
jQuery( ui.element ).parent().removeClass( 'fusion-overlap' );
$spacers.find( '.fusion-column-padding-' + marginDirection ).removeClass( 'fusion-overlap' );
}
},
stop: function( event, ui ) { // jshint ignore: line
$el.removeClass( 'active-drag' );
}
} );
rightPadding = 'undefined' === typeof this.model.attributes.params.padding_right || '' === this.model.attributes.params.padding_right ? '0px' : this.model.attributes.params.padding_right;
rightOverlap = ( 20 > parseInt( rightPadding, 10 ) && ( '0%' === rightPadding || -1 === rightPadding.indexOf( '%' ) ) && ( 20 > parseInt( columnSpacing, 10 ) ) ) ? 'fusion-overlap' : '';
if ( '' !== rightOverlap ) {
$spacers.find( '.fusion-column-padding-right' ).addClass( 'fusion-overlap' );
$el.find( '> .fusion-column-spacing' ).addClass( 'fusion-overlap' );
} else {
$spacers.find( '.fusion-column-padding-right' ).removeClass( 'fusion-overlap' );
$el.find( '> .fusion-column-spacing' ).removeClass( 'fusion-overlap' );
}
// Column spacer created
this.columnSpacer = true;
},
/**
* Changes the size of a column.
*
* @since 2.0.0
* @param {Object} event - The event triggering the change in size.
* @return {void}
*/
sizeSelect: function( event ) {
var columnSize,
fractionSize,
container = FusionPageBuilderViewManager.getView( this.model.get( 'parent' ) ),
viewport = jQuery( '#fb-preview' ).attr( 'data-viewport' ),
index = [ 'desktop', 'tablet', 'mobile' ].findIndex( function ( vp ) {
return viewport.includes( vp );
} ),
widthKeys = [ 'type', 'type_medium', 'type_small' ];
if ( event ) {
event.preventDefault();
}
columnSize = jQuery( event.target ).data( 'column-size' );
// Check if there's a setings view and veify if it's the one corresponding to this element.
if ( FusionPageBuilderApp.SettingsHelpers.openSettingsView && FusionPageBuilderApp.SettingsHelpers.openSettingsView.model.cid === this.model.cid ) {
if ( FusionPageBuilderApp.SettingsHelpers.openSettingsView.tabsRendered.design ) {
return FusionPageBuilderApp.SettingsHelpers.openSettingsView.$el.find( '.fusion-option-' + widthKeys[ index ] + ' .ui-button[data-value="' + columnSize + '"]' ).trigger( 'click' );
}
jQuery( FusionPageBuilderApp.SettingsHelpers.openSettingsView.$el.find( '.width-value' )[ index ] ).val( columnSize );
}
// Update model.
this.model.attributes.params[ widthKeys[ index ] ] = columnSize;
this.$el.find( '.column-sizes' ).hide();
this.$el.removeClass( 'active' );
this.$el.attr( 'data-column-size', columnSize );
fractionSize = columnSize.replace( '_', '/' );
// Necessary for re-sizing then cloning.
this.reRender();
container.setRowData();
if ( 'fusion_builder_column_inner' !== this.model.get( 'type' ) ) {
this.renderSectionSeps();
}
this.$el.find( '.column-sizes .column-size' ).removeClass( 'active-size' );
this.$el.find( '.column-size-' + columnSize ).addClass( 'active-size' );
this.$el.closest( '.fusion-builder-container' ).removeClass( 'fusion-column-sizer-active' );
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).trigger( 'fusion-column-resized', this.model.get( 'cid' ) );
FusionEvents.trigger( 'fusion-column-resized' );
// Save history state
FusionEvents.trigger( 'fusion-history-save-step', fusionBuilderText.resized_column + ' ' + fractionSize );
},
/**
* Checks if the value is in pixels.
*
* @since 2.0.0
* @param {string} value - The value we want to check.
* @return {boolean}
*/
pxCheck: function( value ) {
if ( 'undefined' === typeof value ) {
return false;
}
// If 0, then consider valid.
if ( '0' === value || 0 === value ) {
return true;
}
return ( -1 !== value.indexOf( 'px' ) ) ? true : false;
},
/**
* Checks if the value is using %.
*
* @since 2.0.0
* @param {string} value - The value we want to check.
* @return {boolean}
*/
percentageCheck: function( value ) {
if ( 'undefined' === typeof value ) {
return false;
}
// If 0, then consider valid.
if ( '0' === value || 0 === value ) {
return true;
}
return ( -1 !== value.indexOf( '%' ) ) ? true : false;
},
/**
* Adds 2 values.
*
* @since 2.0.0
* @param {string|number|double} a - The 1st value.
* @param {string|number|double} b - The 2nd value.
* @return {number}
*/
addValues: function( a, b ) {
return parseFloat( a ) + parseFloat( b );
},
/**
* Add a module.
*
* @since 2.0.0
* @param {Object} event - The event triggering the module addition.
* @return {void}
*/
addModule: function( event ) {
var view,
viewSettings,
closestParent;
if ( event ) {
event.preventDefault();
event.stopPropagation();
FusionPageBuilderApp.sizesHide( event );
}
FusionPageBuilderApp.parentColumnId = this.model.get( 'cid' );
viewSettings = {
model: this.model,
collection: this.collection,
view: this,
attributes: {
'data-parent_cid': this.model.get( 'cid' )
}
};
if ( ! jQuery( event.currentTarget ).closest( '.fusion-builder-empty-column' ).length ) {
closestParent = jQuery( event.currentTarget ).closest( '.fusion-builder-live-element' );
if ( closestParent.length ) {
viewSettings.targetElement = closestParent;
} else {
viewSettings.targetElement = jQuery( event.currentTarget ).closest( '.fusion-builder-nested-element' );
}
}
view = new FusionPageBuilder.ElementLibraryView( viewSettings );
jQuery( view.render().el ).dialog( {
title: 'Select Element',
draggable: false,
modal: true,
resizable: false,
dialogClass: 'fusion-builder-dialog fusion-builder-large-library-dialog fusion-builder-element-library-dialog',
resizeStart: function( event, ui ) {
FusionApp.dialog.addResizingClasses();
},
resizeStop: function( event, ui ) {
FusionApp.dialog.removeResizingClasses();
},
open: function( event, ui ) { // jshint ignore: line
FusionApp.dialog.resizeDialog();
// On start can sometimes be laggy/late.
FusionApp.dialog.addResizingHoverEvent();
},
close: function( event, ui ) { // jshint ignore: line
view.remove();
}
} );
},
/**
* Get dynamic values.
*
* @since 2.0.0
* @return {Object}
*/
getDynamicAtts: function( values ) {
var self = this;
if ( 'undefined' !== typeof this.dynamicParams && this.dynamicParams && ! _.isEmpty( this.dynamicParams.getAll() ) ) {
_.each( this.dynamicParams.getAll(), function( data, id ) {
var value = self.dynamicParams.getParamValue( data );
if ( 'undefined' !== typeof value && false !== value ) {
values[ id ] = value;
}
} );
}
return values;
},
/**
* Get the template.
*
* @since 2.0.0
* @return {void}
*/
getTemplate: function() {
var atts = this.getTemplateAtts();
return this.template( atts );
},
setArgs: function() {
var params = jQuery.extend( true, {}, this.model.get( 'params' ) ),
values;
// Make sure initial width is correctly inherited.
if ( 'undefined' === typeof params.type ) {
params.type = this.model.attributes.params.type;
}
if ( fusionAllElements[ this.model.get( 'type' ) ] ) {
values = jQuery.extend( true, {}, fusionAllElements[ this.model.get( 'type' ) ].defaults, _.fusionCleanParameters( params ) );
}
// If no blend mode is defined, check if we should set to overlay.
if ( 'undefined' === typeof params.background_blend_mode && '' !== params.background_color && 1 > values.alpha_background_color && 0 !== values.alpha_background_color && '' !== params.background_image ) {
values.background_blend_mode = 'overlay';
}
// If padding (combined all 4) is not set in params, then use individual variables.
if ( 'undefined' === typeof params.padding ) {
values = _.fusionGetPadding( values );
}
this.values = this.getDynamicAtts( values );
},
validateArgs: function() {
var borderRadius;
// Alpha related checks.
this.values.alpha_background_color = jQuery.AWB_Color( this.values.background_color ).alpha();
this.values.alpha_gradient_start_color = jQuery.AWB_Color( this.values.gradient_start_color ).alpha();
this.values.alpha_gradient_end_color = jQuery.AWB_Color( this.values.gradient_end_color ).alpha();
if ( '' !== this.values.margin_bottom ) {
this.values.margin_bottom = _.fusionGetValueWithUnit( this.values.margin_bottom );
}
if ( '' !== this.values.margin_top ) {
this.values.margin_top = _.fusionGetValueWithUnit( this.values.margin_top );
}
if ( this.values.border_size ) {
this.values.border_size = _.fusionValidateAttrValue( this.values.border_size, 'px' );
}
if ( '' !== this.values.padding ) {
this.values.padding = _.fusionGetValueWithUnit( this.values.padding );
}
if ( '' !== this.values.border_sizes_top ) {
this.values.border_sizes_top = _.fusionGetValueWithUnit( this.values.border_sizes_top );
}
if ( '' !== this.values.border_sizes_bottom ) {
this.values.border_sizes_bottom = _.fusionGetValueWithUnit( this.values.border_sizes_bottom );
}
if ( '' !== this.values.border_sizes_top ) {
this.values.border_sizes_left = _.fusionGetValueWithUnit( this.values.border_sizes_left );
}
if ( '' !== this.values.border_sizes_top ) {
this.values.border_sizes_right = _.fusionGetValueWithUnit( this.values.border_sizes_right );
}
// Border radius validation.
this.values.border_radius_top_left = this.values.border_radius_top_left ? _.fusionGetValueWithUnit( this.values.border_radius_top_left ) : '0px';
this.values.border_radius_top_right = this.values.border_radius_top_right ? _.fusionGetValueWithUnit( this.values.border_radius_top_right ) : '0px';
this.values.border_radius_bottom_left = this.values.border_radius_bottom_left ? _.fusionGetValueWithUnit( this.values.border_radius_bottom_left ) : '0px';
this.values.border_radius_bottom_right = this.values.border_radius_bottom_right ? _.fusionGetValueWithUnit( this.values.border_radius_bottom_right ) : '0px';
borderRadius = this.values.border_radius_top_left + ' ' + this.values.border_radius_top_right + ' ' + this.values.border_radius_bottom_right + ' ' + this.values.border_radius_bottom_left;
this.values.border_radius = '0px 0px 0px 0px' === borderRadius ? '' : borderRadius;
this.values.border_position = 'all' !== this.values.border_position ? '-' + this.values.border_position : '';
if ( '' === this.values.background_color_hover && '' !== this.values.background_color ) {
this.values.background_color_hover = this.values.background_color;
}
},
validatePercentageMargin: function( value, columnSize, values ) {
value = 'undefined' === typeof value ? '' : value;
columnSize = 'undefined' === typeof columnSize ? 1 : columnSize;
values = 'undefined' === typeof values ? this.values : values;
if ( -1 !== value.indexOf( '%' ) && this.isCustomWidth( columnSize ) ) {
return '0px';
}
// If value is in percentage and not calc, make it relative to container.
if ( 0 < parseFloat( columnSize ) && -1 !== value.indexOf( '%' ) && -1 === value.indexOf( 'calc' ) ) {
// If all are in % just work it out.
if ( -1 !== values.column_spacing.indexOf( '%' ) && -1 === values.column_spacing.indexOf( 'calc' ) ) {
return ( parseFloat( value ) / parseFloat( columnSize ) / 100 * ( 100 - parseFloat( values.column_spacing ) ) ) + '%';
}
// Not all % then we need to use calc.
return 'calc( ' + ( parseFloat( value ) / parseFloat( columnSize ) / 100 ) + ' * calc( 100% - ' + values.column_spacing + ' ) )';
}
return value;
},
setExtraArgs: function() {
var container = FusionPageBuilderApp.getParentContainer( this.model.get( 'parent' ) ),
containerParams,
containerValues;
this.values.flex = false;
this.values.column_spacing = '4%';
this.values.flex_align_items = 'flex-start';
if ( 'object' === typeof container ) {
containerParams = _.fusionCleanParameters( container.model.get( 'params' ) );
containerValues = jQuery.extend( true, {}, fusionAllElements.fusion_builder_container.defaults, containerParams );
this.values.flex = 'flex' === containerValues.type;
this.values.column_spacing = containerValues.flex_column_spacing;
this.values.flex_align_items = containerValues.flex_align_items;
}
this.values.column_counter = this.model.get( 'cid' );
this.values.hover_or_link = ( 'none' !== this.values.hover_type && '' !== this.values.hover_type ) || '' !== this.values.link;
this.values.shortcode_classname = 'fusion_builder_column' === this.model.get( 'type' ) ? 'fusion-builder-live-column' : 'fusion-builder-live-nested-column';
// Store for later use.
this.isFlex = this.values.flex;
},
setColumnMapData: function() {
var self = this,
containerSpacingOffset,
unitlessSpacing,
unitlessHalf,
halfSpacing,
emptyOffset,
container,
currentRow,
containerRows,
spacings,
total,
lastIndex,
model,
columnSpacing,
widthKey,
spacingLeftKey,
spacingRightKey,
extras;
// If we are flex, we do not have a column map.
if ( this.values.flex ) {
this.setColumnSize();
extras = jQuery.extend( true, {}, fusionAllElements.fusion_builder_column.extras );
// Medium inherit from large or validate if set.
if ( '' === this.values.type_medium || 0 === parseFloat( this.values.type_medium ) ) {
this.values.type_medium = 'inherit_from_large' === extras.col_width_medium ? this.values.column_size : 1;
} else {
this.values.type_medium = this.validateColumnSize( this.values.type_medium );
}
// Small default to 1 or validate if set.
if ( '' === this.values.type_small || 0 === parseFloat( this.values.type_small ) ) {
this.values.type_small = 'inherit_from_large' === extras.col_width_small ? this.values.column_size : 1;
} else {
this.values.type_small = this.validateColumnSize( this.values.type_small );
}
// Not full width medium, inherit from large if set.
if ( 1 !== parseInt( this.values.type_medium ) ) {
if ( '' === this.values.spacing_left_medium ) {
this.values.spacing_left_medium = this.values.spacing_left;
}
if ( '' === this.values.spacing_right_medium ) {
this.values.spacing_right_medium = this.values.spacing_right;
}
}
// Full width small, inherit from medium or large if set.
if ( 1 !== parseInt( this.values.type_small ) ) {
if ( '' === this.values.spacing_left_small ) {
this.values.spacing_left_small = '' !== this.values.spacing_left_medium ? this.values.spacing_left_medium : this.values.spacing_left;
}
if ( '' === this.values.spacing_right_small ) {
this.values.spacing_right_small = '' !== this.values.spacing_right_medium ? this.values.spacing_right_medium : this.values.spacing_right;
}
}
// Half the spacing on container.
halfSpacing = this.getHalfSpacing();
// Validate left and right margins that are set.
_.each( [ 'large', 'medium', 'small' ], function( width ) {
// Need to calc for each because column width may be different and that changes things.
widthKey = 'large' === width ? 'column_size' : 'type_' + width;
emptyOffset = self.validatePercentageMargin( halfSpacing, self.values[ widthKey ] );
// We have a value, validate it, else we use the empty offset.
spacingLeftKey = 'large' === width ? 'spacing_left' : 'spacing_left_' + width;
if ( '' !== self.values[ spacingLeftKey ] ) {
self.values[ 'upsized_' + spacingLeftKey ] = self.validatePercentageMargin( self.values[ spacingLeftKey ], self.values[ widthKey ] );
} else {
self.values[ 'upsized_' + spacingLeftKey ] = emptyOffset;
}
spacingRightKey = 'large' === width ? 'spacing_right' : 'spacing_right_' + width;
if ( '' !== self.values[ spacingRightKey ] ) {
self.values[ 'upsized_' + spacingRightKey ] = self.validatePercentageMargin( self.values[ spacingRightKey ], self.values[ widthKey ] );
} else {
self.values[ 'upsized_' + spacingRightKey ] = emptyOffset;
}
} );
return;
}
container = FusionPageBuilderViewManager.getView( this.model.get( 'parent' ) );
containerRows = container.model.get( 'rows' );
currentRow = container.getVirtualRowByCID( this.model.get( 'cid' ) );
if ( 'yes' === this.values.spacing || '' === this.values.spacing ) {
this.values.spacing = '4%';
} else if ( 'no' === this.values.spacing ) {
this.values.spacing = '0px';
}
this.values.spacing = _.fusionGetValueWithUnit( this.values.spacing );
this.values.widthOffset = '';
this.values.currentRowNumberOfColumns = false;
function fallbackCheck( value ) {
return ( 'yes' === value || 'no' === value );
}
// Pop off the last because it can't have spacing.
if ( 'undefined' !== typeof currentRow ) {
// currentRow = currentRow.slice( 0, -1 );
this.values.currentRowNumberOfColumns = currentRow.length + 1;
}
this.values.fallback = false;
if ( 'object' === typeof currentRow ) {
this.values.fallback = currentRow.every( fallbackCheck );
}
this.setColumnSize();
// Nested column check
if ( 'object' === typeof currentRow ) {
spacings = [];
total = currentRow.length;
lastIndex = total - 1;
_.each( currentRow, function( column, index ) {
if ( lastIndex !== index ) {
model = container.model.children.find( function( model ) {
return model.get( 'cid' ) == column.cid; // jshint ignore: line
} );
columnSpacing = model.attributes.params.spacing;
columnSpacing = ( 'undefined' === typeof columnSpacing || '' === columnSpacing ) ? '4%' : columnSpacing;
spacings.push( columnSpacing );
}
if ( 1 === total ) {
spacings.push( '' );
}
} );
spacings = spacings.join( ' + ' );
// If no fallback make sure to replace mixed values.
if ( ! this.values.fallback ) {
spacings = spacings.replace( /yes/g, '4%' ).replace( /no/g, '0%' );
}
this.values.widthOffset = '( ( ' + spacings + ' ) * ' + this.values.column_size + ' ) ';
}
this.setSpacingStyling();
},
getHalfSpacing: function () {
var unitlessSpacing = parseFloat( this.values.column_spacing ),
unitlessHalf = unitlessSpacing / 2;
return this.values.column_spacing.replace( unitlessSpacing, unitlessHalf );
},
setColumnSize: function() {
var sizeClass;
// Column size value
switch ( this.values.type ) {
case '1_1':
sizeClass = 'fusion-one-full';
break;
case '1_4':
sizeClass = 'fusion-one-fourth';
break;
case '3_4':
sizeClass = 'fusion-three-fourth';
break;
case '1_2':
sizeClass = 'fusion-one-half';
break;
case '1_3':
sizeClass = 'fusion-one-third';
break;
case '2_3':
sizeClass = 'fusion-two-third';
break;
case '1_5':
sizeClass = 'fusion-one-fifth';
break;
case '2_5':
sizeClass = 'fusion-two-fifth';
break;
case '3_5':
sizeClass = 'fusion-three-fifth';
break;
case '4_5':
sizeClass = 'fusion-four-fifth';
break;
case '5_6':
sizeClass = 'fusion-five-sixth';
break;
case '1_6':
sizeClass = 'fusion-one-sixth';
break;
}
this.values.column_size = this.validateColumnSize( this.values.type );
this.values.size_class = sizeClass;
},
validateColumnSize: function( columnSize ) {
var fractions;
if ( 'undefined' === typeof columnSize ) {
columnSize = '1_3';
}
// Fractional value.
if ( -1 !== columnSize.indexOf( '_' ) ) {
fractions = columnSize.split( '_' );
return parseFloat( fractions[ 0 ] ) / parseFloat( fractions[ 1 ] );
}
// Greater than one, assume percentage and divide by 100.
if ( 1 < parseFloat( columnSize ) && -1 == columnSize.indexOf( 'px' ) && -1 == columnSize.indexOf( 'calc' ) ) {
return parseFloat( columnSize ) / 100;
}
// Return if not float.
return columnSize;
},
setSpacingStyling: function() {
var spacingDirection,
width = ( this.values.column_size * 100 ) + '%',
mapOldSpacing = {
0.1666: '13.3333%',
0.8333: '82.6666%',
0.2: '16.8%',
0.4: '37.6%',
0.6: '58.4%',
0.8: '79.2%',
0.25: '22%',
0.75: '74%',
0.3333: '30.6666%',
0.6666: '65.3333%',
0.5: '48%',
1: '100%'
};
this.values.column_spacing_style = '';
this.values.spacing_classes = '';
if ( 0 === parseFloat( this.values.spacing ) ) {
this.values.spacing_classes = 'fusion-spacing-no';
}
if ( ! this.values.last && ! ( this.values.fallback && '0px' === this.values.spacing ) ) {
spacingDirection = 'right';
if ( FusionPageBuilderApp.$el.hasClass( 'rtl' ) ) {
spacingDirection = 'left';
}
if ( ! this.values.fallback ) {
this.values.column_spacing_style = 'width:' + width + ';width:calc(' + width + ' - ' + this.values.widthOffset + ');margin-' + spacingDirection + ': ' + this.values.spacing + ';';
} else {
this.values.column_spacing_style = 'width:' + mapOldSpacing[ this.values.column_size ] + '; margin-' + spacingDirection + ': ' + this.values.spacing + ';';
}
} else if ( 'undefined' !== typeof this.values.currentRowNumberOfColumns && 1 < this.values.currentRowNumberOfColumns ) {
if ( ! this.values.fallback ) {
this.values.column_spacing_style = 'width:' + width + ';width:calc(' + width + ' - ' + this.values.widthOffset + ');';
} else if ( '0px' !== this.values.spacing && 'undefined' !== typeof mapOldSpacing[ this.values.column_size ] ) {
this.values.column_spacing_style = 'width:' + mapOldSpacing[ this.values.column_size ] + ';';
} else {
this.values.column_spacing_style = 'width:' + width + ';';
}
} else if ( 'undefined' === typeof this.values.currentRowNumberOfColumns && 'undefined' !== mapOldSpacing[ this.values.column_size ] ) {
this.values.column_spacing_style = 'width:' + mapOldSpacing[ this.values.column_size ] + ';';
}
},
getResponsiveColumnVars: function() {
var self = this,
cssVars = [];
this.responsiveStyles = '';
if ( ! this.values.flex ) {
return;
}
_.each( [ 'large', 'medium', 'small' ], function( size ) {
var widthKey,
keyBase,
orderKey,
flex_grow_key,
flex_shrink_key,
spacingKey;
// Width.
widthKey = 'large' === size ? 'column_size' : 'type_' + size;
if ( 'string' === typeof self.values[ widthKey ] && ( self.values[ widthKey ].indexOf( 'px' ) || self.values[ widthKey ].indexOf( 'px' ) ) ) {
cssVars[ 'width-' + size ] = self.values[ widthKey ];
} else if ( '' !== self.values[ widthKey ] && 'auto' !== self.values[ widthKey ] && 0 < parseFloat( self.values[ widthKey ] ) ) {
cssVars[ 'width-' + size ] = ( parseFloat( self.values[ widthKey ] ) * 100 ) + '%';
} else if ( 'auto' === self.values[ widthKey ] ) {
cssVars[ 'width-' + size ] = 'auto';
}
// Order.
orderKey = 'large' === size ? 'order' : 'order_' + size;
if ( '' !== self.values[ orderKey ] ) {
cssVars[ 'order-' + size ] = parseInt( self.values[ orderKey ] );
}
flex_grow_key = 'large' === size ? 'flex_grow' : 'flex_grow_' + size;
flex_shrink_key = 'large' === size ? 'flex_shrink' : 'flex_shrink_' + size;
if ( 0 < parseInt( self.values[ flex_grow_key ] ) ) {
cssVars[ flex_grow_key ] = parseInt( self.values[ flex_grow_key ] );
}
if ( 0 < parseInt( self.values[ flex_shrink_key ] ) ) {
cssVars[ flex_shrink_key ] = parseInt( self.values[ flex_shrink_key ] );
}
_.each( [ 'top', 'right', 'bottom', 'left' ], function( direction ) {
// Margin.
keyBase = 'left' === direction || 'right' === direction ? 'upsized_spacing' : 'margin';
spacingKey = 'large' === size ? keyBase + '_' + direction : keyBase + '_' + direction + '_' + size;
if ( '' !== self.values[ spacingKey ] ) {
if ( 'margin' === keyBase ) {
cssVars[ 'margin-' + direction + '-' + size ] = self.values[ spacingKey ];
} else if ( 'upsized_spacing' === keyBase ) {
if ( -1 !== self.values[ spacingKey ].indexOf( '%' ) && 'custom' === self.getVisibleWidth() ) {
cssVars[ 'spacing-' + direction + '-' + size ] = '0px';
} else {
cssVars[ 'spacing-' + direction + '-' + size ] = _.fusionGetValueWithUnit( self.values[ spacingKey ] );
}
}
}
} );
} );
return this.getCustomCssVars( cssVars );
},
setResponsiveColumnStyles: function() {
var self = this,
extras = jQuery.extend( true, {}, fusionAllElements.fusion_builder_column.extras );
this.responsiveStyles = '';
if ( ! this.values.flex ) {
return;
}
_.each( [ 'large', 'medium', 'small' ], function( size ) {
var uiWrapperStyles = '',
dragStyles = '',
columnStyles = '',
keyBase,
orderKey,
spacingKey;
// Order.
orderKey = 'large' === size ? 'order' : 'order_' + size;
if ( '' !== self.values[ orderKey ] ) {
columnStyles += 'order : ' + parseInt( self.values[ orderKey ] ) + ';';
}
_.each( [ 'top', 'right', 'bottom', 'left' ], function( direction ) {
// Margin.
keyBase = 'left' === direction || 'right' === direction ? 'upsized_spacing' : 'margin';
spacingKey = 'large' === size ? keyBase + '_' + direction : keyBase + '_' + direction + '_' + size;
if ( '' !== self.values[ spacingKey ] ) {
if ( 'left' === direction ) {
uiWrapperStyles += direction + ':' + self.values[ spacingKey ] + ';';
}
if ( 'left' === direction || 'right' === direction ) {
dragStyles += direction + ':' + self.values[ spacingKey ] + ';';
}
}
} );
// Wrap CSS selectors
if ( '' !== columnStyles ) {
columnStyles = '.fusion-body .' + self.values.shortcode_classname + '-' + self.values.column_counter + '{' + columnStyles + '}';
}
if ( '' !== uiWrapperStyles ) {
uiWrapperStyles = '.fusion-body .fusion-flex-container .fusion-row .' + self.values.shortcode_classname + '-' + self.values.column_counter + ' > .fusion-builder-module-controls-type-column {' + uiWrapperStyles + '}';
}
if ( '' !== dragStyles ) {
dragStyles = '.fusion-flex-container .fusion-row .' + self.values.shortcode_classname + '-' + self.values.column_counter + '.fusion-being-dragged:after, .fusion-builder-live .fusion-flex-container .fusion-nested-columns.editing .' + self.values.shortcode_classname + '-' + self.values.column_counter + ':hover:after {' + dragStyles + '}';
}
// Large styles, no wrapping needed.
if ( 'large' === size ) {
self.responsiveStyles += uiWrapperStyles + dragStyles + columnStyles;
} else {
// Medium and Small size screen styles.
self.responsiveStyles += '@media only screen and (max-width:' + extras[ 'visibility_' + size ] + 'px) {' + uiWrapperStyles + dragStyles + columnStyles + '}';
}
} );
},
buildAttr: function() {
var attr = {
'class': 'fusion-layout-column ' + this.model.get( 'type' ) + ' ' + this.values.shortcode_classname + '-' + this.values.column_counter + ' fusion-builder-column-live-' + this.values.column_counter,
'style': this.getStyleVars()
};
// Sticky column.
if ( 'on' === this.values.sticky ) {
attr[ 'class' ] += ' awb-sticky';
if ( '' !== this.values.sticky_offset && 0 !== this.values.sticky_offset ) {
// If its not a selector then get value and set to css variable.
if ( ! this.values.sticky_offset.includes( '.' ) && ! this.values.sticky_offset.includes( '#' ) ) {
attr.style += '--awb-sticky-offset:' + _.fusionGetValueWithUnit( this.values.sticky_offset ) + ';';
} else {
attr[ 'data-sticky-offset' ] = this.values.sticky_offset;
}
}
// Not ideal, but easier to join and keep the rest of the logic the same.
if ( 'object' === typeof this.values.sticky_devices ) {
this.values.sticky_devices = this.values.sticky_devices.join( ',' );
}
if ( 'string' === typeof this.values.sticky_devices && '' !== this.values.sticky_devices ) {
this.values.sticky_devices = this.values.sticky_devices.replaceAll( '-visibility', '' ).split( ',' );
this.values.sticky_devices.forEach( ( stickyDevice ) => {
attr[ 'class' ] += ' awb-sticky-' + stickyDevice.replaceAll( ' ', '' );
} );
}
}
if ( 'on' === this.values.absolute ) {
attr[ 'class' ] += ' awb-absolute';
}
// Flexbox column.
if ( this.values.flex ) {
attr[ 'class' ] += ' fusion-flex-column';
// Alignment of column vertically.
if ( 'auto' !== this.values.align_self ) {
attr[ 'class' ] += ' fusion-flex-align-self-' + this.values.align_self;
}
} else {
if ( '' !== this.values.type && this.values.type.includes( '_ ' ) ) {
attr[ 'class' ] += ' ' + this.model.get( 'type' ) + '_' + this.values.type;
attr[ 'class' ] += ' ' + this.values.type;
}
// Class for the specific size of column.
if ( '' !== this.values.size_class ) {
attr[ 'class' ] += ' ' + this.values.size_class;
}
// First column.
if ( this.values.first ) {
attr[ 'class' ] += ' fusion-column-first';
}
// Last column.
if ( this.values.last ) {
attr[ 'class' ] += ' fusion-column-last';
}
// Special calcs for spacing.
if ( '' !== this.values.spacing_classes ) {
attr[ 'class' ] += this.values.spacing_classes;
}
// Column spacing style, margin and width.
if ( '' !== this.values.column_spacing_style ) {
attr.style += this.values.column_spacing_style;
}
}
// Custom CSS class.
if ( '' !== this.values[ 'class' ] ) {
attr[ 'class' ] += ' ' + this.values[ 'class' ];
}
// Min height for newly created columns by the converter.
if ( 'none' === this.values.min_height ) {
attr[ 'class' ] += ' fusion-column-no-min-height';
}
// Visibility classes.
let visibilityValue = this.values.hide_on_mobile;
// Get Render logics Array.
const renderLogicsDevices = this.getRenderLogicsDevices();
if ( renderLogicsDevices.length && 'on' === FusionApp.preferencesData.rendering_logic ) {
const rlDevicesEqual = [];
const rlDevicesNotEqual = [];
renderLogicsDevices.forEach( ( r ) => {
switch ( r.value ) {
case 'desktop':
if ( 'equal' === r.comparison ) {
rlDevicesEqual.push( 'large-visibility' );
} else {
rlDevicesNotEqual.push( 'large-visibility' );
}
break;
case 'tablet':
if ( 'equal' === r.comparison ) {
rlDevicesEqual.push( 'medium-visibility' );
} else {
rlDevicesNotEqual.push( 'medium-visibility' );
}
break;
case 'mobile':
if ( 'equal' === r.comparison ) {
rlDevicesEqual.push( 'small-visibility' );
} else {
rlDevicesNotEqual.push( 'small-visibility' );
}
break;
case 'mobile_tablet':
if ( 'equal' === r.comparison ) {
rlDevicesEqual.push( 'medium-visibility' );
rlDevicesEqual.push( 'small-visibility' );
} else {
rlDevicesNotEqual.push( 'medium-visibility' );
rlDevicesNotEqual.push( 'small-visibility' );
}
break;
}
} );
if ( rlDevicesEqual.length ) {
attr[ 'class' ] = _.fusionVisibilityAtts( rlDevicesEqual.join( ',' ), attr[ 'class' ] );
}
if ( rlDevicesNotEqual.length ) {
visibilityValue = visibilityValue.split( ',' ).filter( ( v ) => !rlDevicesNotEqual.includes( v ) );
}
}
// Visibility classes.
attr[ 'class' ] = _.fusionVisibilityAtts( visibilityValue, attr[ 'class' ] );
attr[ 'class' ] += _.fusionGetStickyClass( this.values.sticky_display );
// Hover type or link.
if ( this.values.hover_or_link ) {
attr[ 'class' ] += ' fusion-column-inner-bg-wrapper';
}
// TODO: check why it is looking at animation type/class.
if ( this.values.hover_or_link && '' !== this.values.animation_type && 'liftup' === this.values.hover_type ) {
attr[ 'class' ] += ' fusion-column-hover-type-liftup';
}
// Lift up and border.
if ( 'liftup' === this.values.hover_type && '' !== this.values.border_style ) {
attr[ 'class' ] += ' fusion-column-liftup-border';
}
attr = _.fusionAnimations( this.values, attr );
if ( '' !== this.values.id ) {
attr.id = this.values.id;
}
if ( this.values.motion_effects ) {
attr[ 'data-motion-effect' ] = true;
}
return attr;
},
buildWrapperAttr: function() {
var attr = {
'class': 'fusion-column-wrapper fusion-column-wrapper-live-' + this.values.column_counter,
'style': ''
};
// Image URL for empty dimension calculations.
attr[ 'data-bg-url' ] = this.values.background_image;
// Box shadow.
if ( 'liftup' !== this.values.hover_type && '' !== this.values.box_shadow ) {
attr[ 'class' ] += ' fusion-column-has-shadow'; // Move this to appropriate.
}
// Flex.
if ( this.values.flex ) {
if ( '' !== this.values.align_content ) {
attr[ 'class' ] += ' fusion-flex-justify-content-' + this.values.align_content;
attr[ 'class' ] += ' fusion-content-layout-' + this.values.content_layout;
if ( 'row' === this.values.content_layout && 'flex-start' !== this.values.valign_content ) {
attr[ 'class' ] += ' fusion-flex-align-items-' + this.values.valign_content;
}
if ( 'wrap' !== this.values.content_wrap ) {
attr[ 'class' ] += ' fusion-content-' + this.values.content_wrap;
}
}
}
return attr;
},
buildHoverWrapperAttr: function() {
var attr = {
'class': 'fusion-column-inner-bg hover-type-' + this.values.hover_type,
'style': ''
};
return attr;
},
buildAnchorAttr: function() {
var attr = {};
attr[ 'class' ] = 'fusion-column-anchor';
if ( '' !== this.values.link ) {
attr.href = this.values.link;
}
if ( '_blank' === this.values.target ) {
attr.rel = 'noopener noreferrer';
attr.target = '_blank';
} else if ( 'lightbox' === this.values.target ) {
attr[ 'data-rel' ] = 'iLightbox';
}
if ( '' !== this.values.link_description ) {
attr[ 'aria-label' ] = this.values.link_description;
}
return attr;
},
buildHoverInnerWrapperAttr: function() {
var attr = {
'class': 'fusion-column-inner-bg-image',
'style': ''
};
return attr;
},
getStyleVars: function() {
var cssVars = [
'z_index',
'z_index_hover'
],
borderVars,
innerVarPrefix,
customCssVars = {};
cssVars.padding_top = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_right = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_bottom = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_left = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_top_medium = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_right_medium = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_bottom_medium = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_left_medium = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_top_small = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_right_small = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_bottom_small = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_left_small = { 'callback': _.fusionGetValueWithUnit };
// Overflow.
if ( '' !== this.values.overflow ) {
customCssVars.overflow = this.values.overflow;
} else if ( this.values.border_radius ) {
customCssVars.overflow = 'hidden';
}
// Some variables needs to be placed directly on column, some on an inner div helper.
// This is a quick way to not check for "hover_or_link" every time.
innerVarPrefix = ( this.values.hover_or_link ? 'inner-' : '' );
if ( 'on' === this.values.absolute && 'on' !== this.values.sticky ) {
customCssVars[ 'container-position' ] = 'absolute';
cssVars.absolute_top = { 'callback': _.fusionGetValueWithUnit };
cssVars.absolute_right = { 'callback': _.fusionGetValueWithUnit };
cssVars.absolute_bottom = { 'callback': _.fusionGetValueWithUnit };
cssVars.absolute_left = { 'callback': _.fusionGetValueWithUnit };
}
if ( '' !== this.values.background_color && ( '' === this.values.background_image || 0 !== this.values.alpha_background_color ) ) {
customCssVars[ innerVarPrefix + 'bg-color' ] = this.values.background_color;
}
if ( '' !== this.values.background_color_hover ) {
customCssVars[ innerVarPrefix + 'bg-color-hover' ] = this.values.background_color_hover;
}
if ( '' !== this.values.background_color_medium ) {
customCssVars[ innerVarPrefix + 'bg-color-medium' ] = this.values.background_color_medium;
}
if ( '' !== this.values.background_color_medium_hover ) {
customCssVars[ innerVarPrefix + 'bg-color-medium-hover' ] = this.values.background_color_medium_hover;
}
if ( '' !== this.values.background_color_small ) {
customCssVars[ innerVarPrefix + 'bg-color-small' ] = this.values.background_color_small;
}
if ( '' !== this.values.background_color_small_hover ) {
customCssVars[ innerVarPrefix + 'bg-color-small-hover' ] = this.values.background_color_small_hover;
}
if ( '' !== this.values.background_image ) {
customCssVars[ innerVarPrefix + 'bg-image' ] = 'url(\'' + this.values.background_image + '\')';
}
if ( '' !== this.values.background_image_medium ) {
customCssVars[ innerVarPrefix + 'bg-image-medium' ] = 'url(\'' + this.values.background_image_medium + '\')';
}
if ( '' !== this.values.background_image_small ) {
customCssVars[ innerVarPrefix + 'bg-image-small' ] = 'url(\'' + this.values.background_image_small + '\')';
}
if ( '' !== _.getGradientString( this.values, 'column' ) ) {
customCssVars[ innerVarPrefix + 'bg-image' ] = _.getGradientString( this.values, 'column' );
if ( '' !== this.values.background_image_medium ) {
customCssVars[ innerVarPrefix + 'bg-image_medium' ] = _.getGradientString( this.values, 'column', 'medium' );
}
if ( '' !== this.values.background_image_small ) {
customCssVars[ innerVarPrefix + 'bg-image_small' ] = _.getGradientString( this.values, 'column', 'small' );
}
}
if ( this.values.background_position && ! this.isDefault( 'background_position' ) ) {
customCssVars[ innerVarPrefix + 'bg-position' ] = this.values.background_position;
}
if ( this.values.background_position_medium ) {
customCssVars[ innerVarPrefix + 'bg-position-medium' ] = this.values.background_position_medium;
}
if ( this.values.background_position_small ) {
customCssVars[ innerVarPrefix + 'bg-position-small' ] = this.values.background_position_small;
}
if ( ! this.isDefault( 'background_blend_mode' ) ) {
customCssVars[ innerVarPrefix + 'bg-blend' ] = this.values.background_blend_mode;
}
if ( this.values.background_blend_mode_medium ) {
customCssVars[ innerVarPrefix + 'bg-blend-medium' ] = this.values.background_blend_mode_medium;
}
if ( this.values.background_blend_mode_small ) {
customCssVars[ innerVarPrefix + 'bg-blend-small' ] = this.values.background_blend_mode_small;
}
if ( '' !== this.values.background_repeat ) {
customCssVars[ innerVarPrefix + 'bg-repeat' ] = this.values.background_repeat;
}
if ( '' !== this.values.background_repeat ) {
customCssVars[ innerVarPrefix + 'bg-repeat' ] = this.values.background_repeat;
}
if ( '' !== this.values.background_repeat_medium ) {
customCssVars[ innerVarPrefix + 'bg-repeat-medium' ] = this.values.background_repeat_medium;
}
if ( '' !== this.values.background_repeat_small ) {
customCssVars[ innerVarPrefix + 'bg-repeat-small' ] = this.values.background_repeat_small;
}
if ( 'no-repeat' === this.values.background_repeat ) {
customCssVars[ innerVarPrefix + 'bg-size' ] = 'cover';
}
if ( '' !== this.values.background_size ) {
const backgroundSize = 'custom' === this.values.background_size ? this.values.background_custom_size : this.values.background_size;
customCssVars[ innerVarPrefix + 'bg-size' ] = backgroundSize;
}
if ( '' !== this.values.background_size_medium ) {
const backgroundSizeMedium = 'custom' === this.values.background_size_medium ? this.values.background_custom_size_medium : this.values.background_size_medium;
customCssVars[ innerVarPrefix + 'bg-size-medium' ] = backgroundSizeMedium;
}
if ( '' !== this.values.background_size_small ) {
const backgroundSizeSmall = 'custom' === this.values.background_size_small ? this.values.background_custom_size_small : this.values.background_size_small;
customCssVars[ innerVarPrefix + 'bg-size-small' ] = backgroundSizeSmall;
}
borderVars = this.getBorderVars();
if ( 'yes' === this.values.box_shadow ) {
if ( 'liftup' === this.values.hover_type ) {
customCssVars.inner_bg_box_shadow = _.fusionGetBoxShadowStyle( this.values ).trim();
} else {
customCssVars.box_shadow = _.fusionGetBoxShadowStyle( this.values ).trim();
}
}
const transformVars = _.fusionGetTransformVars( this.values, '--awb-transform', '--awb-transform-hover', '--awb-transform-parent-hover' );
if ( this.values.transform_origin && '50% 50%' !== this.values.transform_origin ) {
customCssVars.transform_origin = this.values.transform_origin;
}
const filterVars = _.getFilterVars( this.values );
if ( ! this.isDefault( 'transition_duration' ) || ! this.isDefault( 'transition_easing' ) ) {
customCssVars.transition = _.fusionGetTransitionStyle( this.values );
}
return this.getCssVarsForOptions( cssVars ) + this.getCustomCssVars( customCssVars ) + borderVars + transformVars + filterVars + this.getResponsiveColumnVars();
},
getBorderVars: function() {
var customCssVars = {},
borderOnInner = ( 'liftup' === this.values.hover_type ? true : false );
if ( '' !== this.values.border_color ) {
customCssVars[ 'border-color' ] = this.values.border_color;
if ( borderOnInner ) {
customCssVars[ 'inner-border-color' ] = this.values.border_color;
}
if ( this.values.border_color_hover ) {
customCssVars[ 'border-color-hover' ] = this.values.border_color_hover;
if ( borderOnInner ) {
customCssVars[ 'inner-border-color-hover' ] = this.values.border_color_hover;
}
}
if ( this.values.border_sizes_top ) {
customCssVars[ 'border-top' ] = this.values.border_sizes_top;
if ( borderOnInner ) {
customCssVars[ 'inner-border-top' ] = this.values.border_sizes_top;
}
}
if ( this.values.border_sizes_right ) {
customCssVars[ 'border-right' ] = this.values.border_sizes_right;
if ( borderOnInner ) {
customCssVars[ 'inner-border-right' ] = this.values.border_sizes_right;
}
}
if ( this.values.border_sizes_bottom ) {
customCssVars[ 'border-bottom' ] = this.values.border_sizes_bottom;
if ( borderOnInner ) {
customCssVars[ 'inner-border-bottom' ] = this.values.border_sizes_bottom;
}
}
if ( this.values.border_sizes_left ) {
customCssVars[ 'border-left' ] = this.values.border_sizes_left;
if ( borderOnInner ) {
customCssVars[ 'inner-border-left' ] = this.values.border_sizes_left;
}
}
if ( '' !== this.values.border_style ) {
customCssVars[ 'border-style' ] = this.values.border_style;
if ( borderOnInner ) {
customCssVars[ 'inner-border-style' ] = this.values.border_style;
}
}
}
if ( '' !== this.values.border_radius ) {
customCssVars.border_radius = this.values.border_radius;
if ( ( 'zoomin' === this.values.hover_type || 'zoomout' === this.values.hover_type || '' !== this.values.link ) ) {
customCssVars[ 'inner-bg-border-radius' ] = this.values.border_radius;
}
// Lift up and border radius we need to apply radius to lift up markup.
if ( this.values.hover_or_link && 'liftup' === this.values.hover_type ) {
customCssVars[ 'liftup-border-radius' ] = this.values.border_radius;
}
}
if ( ( 'zoomin' === this.values.hover_type || 'zoomout' === this.values.hover_type || this.values.link ) && '' !== this.values.border_radius ) {
customCssVars[ 'inner-bg-overflow' ] = 'hidden';
}
return this.getCustomCssVars( customCssVars );
},
/**
* Fires when preview are is resized.
*
* @since 3.0
* @return {void}
*/
onPreviewResize: function() {
// Update size indicator in toolbar.
this.updateSizeIndicators();
if ( ! FusionPageBuilderApp.getParentContainer( this ).isFlex() ) {
return;
}
// Update margin and padding indicators if we are editing this.
if ( this.$el.hasClass( 'fusion-builder-element-edited' ) ) {
this.updateBoxModelIndicators();
}
},
/**
* Updates column sizes controls.
*
* @since 3.0
* @return {void}
*/
updateSizeIndicators: function() {
var columnSize = this.getVisibleWidth();
this.$el.find( '.column-sizes .column-size' ).removeClass( 'active-size' );
if ( columnSize.includes( '_' ) ) {
this.$el.find( '.column-size-' + columnSize ).addClass( 'active-size' );
}
if ( 'custom' === columnSize ) {
columnSize = '';
}
this.$el.find( '.fusion-column-size-label' ).html( columnSize.replace( '_', '/' ) );
},
/**
* Updates column sizes controls.
*
* @since 3.0
* @return {void}
*/
updateBoxModelIndicators: function() {
this.destroyMarginResizable();
this.destroyPaddingResizable();
this.marginDrag();
this.paddingDrag();
},
/**
* Parses width to readable string.
*
* @since 3.0
* @param {String} width
* @return {String}
*/
parseWidthLabel: function( width ) {
if ( 'undefined' === typeof width ) {
width = '1_1';
}
if ( 'auto' === width ) {
return 'auto';
}
if ( ! width.includes( '_' ) && ! width.includes( 'px' ) && ! width.includes( 'calc' ) ) {
return width.split( '.' )[ 0 ] + '%';
}
if ( width.includes( 'px' ) || width.includes( 'calc' ) ) {
return 'custom';
}
return width;
},
/**
* Returns visible column width.
*
* @since 3.0
* @return {String}
*/
getVisibleWidth: function() {
var param, defaultVal, previewFrame, legacyBreakpoint;
// Legacy support.
if ( ! FusionPageBuilderApp.getParentContainer( this ).isFlex() ) {
previewFrame = jQuery( '#fb-preview' )[ 0 ];
legacyBreakpoint = getComputedStyle( previewFrame.contentDocument.documentElement ).getPropertyValue( '--content_break_point' );
if ( legacyBreakpoint && legacyBreakpoint >= previewFrame.offsetWidth ) {
return '1_1';
}
return this.model.attributes.params.type;
}
param = FusionApp.getResponsiveOptionKey( 'type', true );
// Default for medium and small sizes.
if ( 'type' !== param && ! this.model.attributes.params[ param ] ) {
// Return large value.
defaultVal = fusionAllElements.fusion_builder_column.extras[ 'col_width_' + param.replace( 'type_', '' ) ];
if ( 'inherit_from_large' === defaultVal ) {
return this.parseWidthLabel( this.model.attributes.params.type );
}
return '1_1';
}
return this.parseWidthLabel( this.model.attributes.params[ param ] );
},
getTemplateAtts: function() {
var styleSelector,
data = {},
wrapperAttr;
this.setArgs();
this.responsiveStyles = '';
this.styles = '';
this.validateArgs();
this.setExtraArgs();
this.setColumnMapData();
// Sets styles for responsive options.
if ( this.values.flex ) {
this.setResponsiveColumnStyles();
}
let columnSelector = '.fusion-builder-column-live-' + this.model.get( 'cid' );
if ( 'fusion_builder_column_inner' === this.model.get( 'type' ) ) {
columnSelector = '.fusion-builder-live-nested-column-' + this.model.get( 'cid' );
}
// Get the filter style
if ( 'fusion_builder_column' === this.model.get( 'type' ) ) {
styleSelector = columnSelector;
} else {
styleSelector = { regular: columnSelector, hover: columnSelector + ':hover' };
}
// Get Transform selector.
let transformSelector = '';
let transformEditSelector = '';
if ( 'fusion_builder_column' === this.model.get( 'type' ) ) {
transformSelector = columnSelector;
transformEditSelector = columnSelector + '.fusion-builder-element-edited';
} else {
transformSelector = { regular: columnSelector, hover: columnSelector + ':hover' };
transformEditSelector = { regular: '.fusion-builder-element-edited' + columnSelector, hover: '.fusion-builder-element-edited' + columnSelector + ':hover' };
}
data.wrapperAttr = this.buildWrapperAttr();
data.center_content = this.values.center_content;
data.hoverWrapperAttr = this.buildHoverWrapperAttr();
data.anchorAttr = this.buildAnchorAttr();
data.hoverInnerWrapperAttr = this.buildHoverInnerWrapperAttr();
data.styles = this.styles;
data.nestedClass = 'fusion_builder_column_inner' === this.model.get( 'type' ) ? ' fusion-nested-column-content' : '';
data.cid = this.model.get( 'cid' );
data.hoverOrLink = this.values.hover_or_link;
data.layout = this.getVisibleWidth().replace( '_', '/' );
data.isFlex = ( 'undefined' !== typeof this.values.flex ) ? this.values.flex : false;
data.responsiveStyles = 'undefined' !== typeof this.responsiveStyles ? this.responsiveStyles : '';
data.isGlobal = ( 'undefined' !== typeof this.values.fusion_global ) ? 'yes' : 'no';
data.hideMargin = 'fusion_builder_column_inner' !== this.model.get( 'type' ) && 'post_cards' === FusionApp.data.fusion_element_type;
data.column_tag = this.values.column_tag;
data.hasBgSlider = this.values.background_slider_images;
data.bgSlider = _.fusionGetBackgroundSliderElement( this, 'column' );
wrapperAttr = this.buildAttr();
// Flag as having filters.
if ( '' !== _.getFilterVars( this.values ) ) {
wrapperAttr[ 'class' ] += ' fusion-has-filters';
}
// Main wrapper is the actual view.
this.model.set( 'selectors', wrapperAttr );
return data;
},
/**
* Toggles the 'active' class.
*
* @since 2.0.0
* @param {Object} event - The event triggering the class toggling.
* @return {void}
*/
sizesShow: function( event ) {
var parentContainer = this.$el.closest( '.fusion-builder-container' ),
sizesPopover = this.$el.find( '.column-sizes' ),
columnOffsetTop = 0,
html, header, headerBottom, conditional;
if ( event ) {
event.preventDefault();
event.stopPropagation();
}
sizesPopover.removeClass( 'fusion-expand-to-bottom' );
// This needs to be the way it is setup, as nested cols could trigger sizing on several cols at once.
if ( ! this.$el.hasClass( 'active' ) ) {
this.$el.addClass( 'active' );
parentContainer.addClass( 'fusion-column-sizer-active' );
columnOffsetTop = this.$el.offset().top;
html = this.$el.closest( 'html' );
conditional = false;
if ( html.children( 'body' ).hasClass( 'fusion-top-header' ) ) {
if ( jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( '.fusion-footer-parallax' ).length ) {
sizesPopover.on( 'mouseenter', function() {
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( '#main' ).css( 'z-index', 'auto' );
if ( 'fixed' === jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( '.fusion-footer-parallax' ).css( 'position' ) ) {
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( '.fusion-footer-parallax' ).css( 'z-index', '-1' );
if ( jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( '#sliders-container' ).find( '.tfs-slider[data-parallax="1"]' ).length ) {
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( '#sliders-container' ).css( 'z-index', 'auto' );
}
}
} );
sizesPopover.on( 'mouseleave', function() {
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( '#main' ).css( 'z-index', '' );
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( '.fusion-footer-parallax' ).css( 'z-index', '' );
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( '#sliders-container' ).css( 'z-index', '' );
} );
}
header = html.find( '.fusion-header-wrapper' );
headerBottom = 0;
if ( header.length ) {
headerBottom = header.offset().top + header.outerHeight();
}
conditional = 106 > columnOffsetTop - headerBottom;
}
if ( 54 > columnOffsetTop - 121 || conditional || sizesPopover.parents( '.fusion-fullwidth' ).hasClass( 'bg-parallax-parent' ) ) {
sizesPopover.addClass( 'fusion-expand-to-bottom' );
}
} else {
this.$el.removeClass( 'active' );
parentContainer.removeClass( 'fusion-column-sizer-active' );
sizesPopover.off( 'mouseover' ).off( 'mouseleave' );
}
},
/**
* Toggle class to show content in bottom
*
* @since 2.0.0
* @return {void}
*/
offsetClass: function() {
if ( 100 > this.$el.offset().top ) {
this.$el.addClass( 'fusion-content-bottom' );
} else if ( 100 < this.$el.offset().top && this.$el.hasClass( 'fusion-content-bottom' ) ) {
this.$el.removeClass( 'fusion-content-bottom' );
}
},
/**
* Column spacing dimensions version.
*
* @since 2.0.0
* @return {void}
*/
fallbackColumnSpacing: function( $placeholder, allNo ) {
var columnSize = '100%',
fullcolumnSize = columnSize,
existingSpacing = '0%',
columnWidth = this.model.attributes.params.type,
spacingDirection;
if ( 'yes' === this.model.attributes.params.spacing ) {
existingSpacing = '4%';
}
columnWidth = this.model.attributes.params.type;
switch ( columnWidth ) {
case '1_1':
columnSize = '100%';
fullcolumnSize = '100%';
break;
case '1_4':
columnSize = '22%';
fullcolumnSize = '25%';
break;
case '3_4':
columnSize = '74%';
fullcolumnSize = '75%';
break;
case '1_2':
columnSize = '48%';
fullcolumnSize = '50%';
break;
case '1_3':
columnSize = '30.6666%';
fullcolumnSize = '33.3333%';
break;
case '2_3':
columnSize = '65.3333%';
fullcolumnSize = '66.6666%';
break;
case '1_5':
columnSize = '16.8%';
fullcolumnSize = '20%';
break;
case '2_5':
columnSize = '37.6%';
fullcolumnSize = '40%';
break;
case '3_5':
columnSize = '58.4%';
fullcolumnSize = '60%';
break;
case '4_5':
columnSize = '79.2%';
fullcolumnSize = '80%';
break;
case '5_6':
columnSize = '82.6666%';
fullcolumnSize = '83.3333%';
break;
case '1_6':
columnSize = '13.3333%';
fullcolumnSize = '16.6666%';
break;
}
if ( '4%' !== existingSpacing && ( ! this.model.attributes.params.last || allNo ) ) {
columnSize = fullcolumnSize;
}
this.$el.css( 'width', columnSize );
$placeholder.css( 'width', columnSize );
spacingDirection = 'right';
if ( FusionPageBuilderApp.$el.hasClass( 'rtl' ) ) {
spacingDirection = 'left';
}
$placeholder.css( 'margin-' + spacingDirection, existingSpacing );
this.$el.css( 'margin-' + spacingDirection, existingSpacing );
},
/**
* Column spacing dimensions version.
*
* @since 2.0.0
* @return {void}
*/
dimensionColumnSpacing: function( columnRow, columnWidth, $placeholder ) {
var decimalWidth,
check,
spacingWidth,
existingSpacing,
spacings = [],
spacingDirection;
// Remove last from calcs.
columnRow.pop();
columnWidth = columnWidth[ 0 ] / columnWidth[ 1 ];
decimalWidth = columnWidth;
if ( 'object' === typeof columnRow ) {
check = columnRow.every( this.pxCheck );
if ( check ) {
spacingWidth = ( columnRow.reduce( this.addValues, 0 ) * decimalWidth ) + 'px';
this.$el.css( 'width', 'calc( ' + ( columnWidth * 100 ) + '% - ' + spacingWidth + ' )' );
$placeholder.css( 'width', 'calc( ' + ( columnWidth * 100 ) + '% - ' + spacingWidth + ' )' );
} else if ( columnRow.every( this.percentageCheck ) ) {
columnWidth = ( columnWidth * 100 ) - ( columnRow.reduce( this.addValues, 0 ) * decimalWidth );
this.$el.css( 'width', columnWidth + '%' );
$placeholder.css( 'width', columnWidth + '%' );
} else {
_.each( columnRow, function( space ) {
space = ( 'undefined' === typeof space || '' === space ) ? '4%' : space;
spacings.push( space );
} );
spacingWidth = spacings.join( ' + ' );
this.$el.css( 'width', 'calc( ' + ( columnWidth * 100 ) + '% - ( ( ' + spacingWidth + ' ) * ' + decimalWidth + ' )' );
$placeholder.css( 'width', 'calc( ' + ( columnWidth * 100 ) + '% - ( ( ' + spacingWidth + ' ) * ' + decimalWidth + ' )' );
}
}
existingSpacing = this.model.attributes.params.spacing;
if ( 'undefined' === typeof this.model.attributes.params.spacing || 'yes' === this.model.attributes.params.spacing || '' === this.model.attributes.params.spacing ) {
existingSpacing = '4%';
}
if ( 'no' === this.model.attributes.params.spacing ) {
existingSpacing = '0';
}
spacingDirection = 'right';
if ( FusionPageBuilderApp.$el.hasClass( 'rtl' ) ) {
spacingDirection = 'left';
}
$placeholder.css( 'margin-' + spacingDirection, existingSpacing );
this.$el.css( 'margin-' + spacingDirection, existingSpacing );
},
/**
* Check if value is valid for column spacing.
*
* @since 2.0.0
* @return {void}
*/
validColumnSpacing: function( value ) {
if ( 'yes' !== value && 'no' !== value && ! ( /\d/ ).test( value ) && '' !== value ) {
return false;
}
return true;
},
/**
* Filter out DOM before patching.
*
* @since 2.0.0
* @return {void}
*/
patcherFilter: function( diff ) {
var filteredDiff = [],
self = this;
_.each( diff, function( info ) {
if ( 'removeElement' === info.action ) {
if ( 'undefined' !== typeof info.element.attributes[ 'class' ] &&
(
-1 !== info.element.attributes[ 'class' ].indexOf( 'fusion-column-content-centered' ) ||
-1 !== info.element.attributes[ 'class' ].indexOf( 'fusion-builder-column-content' ) ||
-1 !== info.element.attributes[ 'class' ].indexOf( 'fusion-column-wrapper' )
)
) {
self.forceAppendChildren = true;
filteredDiff.push( info );
} else if (
'undefined' !== typeof info.element.attributes[ 'class' ] &&
(
-1 !== info.element.attributes[ 'class' ].indexOf( 'fusion-spacing-value' ) ||
-1 !== info.element.attributes[ 'class' ].indexOf( 'fusion-element-spacing' ) ||
-1 !== info.element.attributes[ 'class' ].indexOf( 'fusion-builder-live-element' ) ||
-1 !== info.element.attributes[ 'class' ].indexOf( 'fusion_builder_row_inner' )
)
) {
// ignore
} else {
filteredDiff.push( info );
}
} else if ( 'addElement' === info.action ) {
if ( 'undefined' !== typeof info.element.attributes[ 'class' ] &&
(
-1 !== info.element.attributes[ 'class' ].indexOf( 'fusion-column-content-centered' ) ||
-1 !== info.element.attributes[ 'class' ].indexOf( 'fusion-builder-column-content' ) ||
-1 !== info.element.attributes[ 'class' ].indexOf( 'fusion-column-wrapper' )
)
) {
self.forceAppendChildren = true;
filteredDiff.push( info );
} else if ( 'undefined' !== typeof info.element.attributes[ 'class' ] && ( -1 !== info.element.attributes[ 'class' ].indexOf( 'fusion-spacing-value' ) || -1 !== info.element.attributes[ 'class' ].indexOf( 'fusion-element-spacing' ) ) ) {
// ignore
} else {
filteredDiff.push( info );
}
} else {
filteredDiff.push( info );
}
} );
return filteredDiff;
},
/**
* Adds a delay to the change trigger to accomodate equal-heights implementation.
*
* @since 2.0.0
* @param {number|string} cid - The CID of the element.
* @return {void}
*/
equalHeights: function( cid ) {
cid = 'undefined' === typeof cid ? this.model.attributes.cid : cid;
setTimeout( function() {
jQuery( document ).trigger( 'fusion-content-changed', cid );
jQuery( window ).trigger( 'fusion-content-changed', cid );
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).trigger( 'fusion-content-changed', cid );
}, 300 );
},
/**
* Removes the 'active' class.
*
* @since 2.0.0
* @return {void}
*/
toolTipHide: function() {
this.$el.find( '.fusion-spacing-tooltip, .fusion-column-spacing' ).removeClass( 'active' );
},
/**
* Resize spacer on window resize event.
*
* @since 2.0.0
* @return {void}
*/
resizeSpacer: function() {
if ( this.columnSpacer ) {
this.columnSpacing();
}
},
/**
* Preview column-spacing changes.
*
* @since 2.0.0
* @param {Object} columnRow - The row.
* @return {void}
*/
columnSpacingPreview: function( columnRow ) {
var columnWidth = 'undefined' !== typeof this.model.attributes.params.type ? this.model.attributes.params.type.split( '_' ) : [ '1', '1' ],
fallback = true,
origValue,
$placeholder = jQuery( '.fusion-builder-column-placeholder[data-cid="' + this.model.get( 'cid' ) + '"]' ),
allNo = true;
_.each( columnRow, function( value, index ) {
origValue = value;
value = ( 'yes' === value ) ? '4%' : value;
value = ( 'no' === value ) ? '0' : value;
fallback = fallback && origValue !== value;
allNo = allNo && 0 === parseInt( value, 10 );
columnRow[ index ] = value;
} );
if ( ! fallback ) {
this.dimensionColumnSpacing( columnRow, columnWidth, $placeholder );
} else {
this.fallbackColumnSpacing( $placeholder, allNo );
}
},
/**
* Gets the column content.
* Alias of getColumnContent method.
*
* @since 2.0.0
* @return {string}
*/
getContent: function() {
return this.getColumnContent();
},
/**
* Sets the attributes of an element.
*
* @since 2.0.0
* @param {Object} element - The element we're updating.
* @param {Object} attributes - The attributes we're setting/updating.
* @return {void}
*/
setElementAttributes: function( element, attributes ) {
var self = this;
element.removeClass( this.currentClasses );
if ( 'object' === typeof attributes && element.length ) {
_.each( attributes, function( values, attribute ) {
if ( 'class' === attribute ) {
self.currentClasses = values;
element.addClass( values );
} else if ( 'id' === attribute ) {
element.attr( 'id', values );
} else if ( 'style' === attribute ) {
element.attr( 'style', values );
} else if ( -1 !== attribute.indexOf( 'data' ) ) {
attribute = attribute.replace( /_/g, '-' );
element.attr( attribute, values );
}
} );
}
},
/**
* check if String is JSON string.
*
* @since 3.7
* @return boolean
*/
IsJsonString: function( str ) {
try {
const json = JSON.parse( str );
return ( 'object' === typeof json );
} catch ( e ) {
return false;
}
},
/**
* Get render logics devices.
*
* @since 3.7
* @return boolean
*/
getRenderLogicsDevices: function( value ) {
//console.warn( JSON.parse( value ));
value = value || this.values.render_logics;
let renderLogics = value && this.IsJsonString( atob( value ) ) ? JSON.parse( atob( value ) ) : [];
// Get device Render logics only.
renderLogics = renderLogics.filter( ( r ) => 'device_type' === r.field );
return renderLogics;
}
} );
} );
}( jQuery ) );
;/* global FusionPageBuilderViewManager, fusionAppConfig, fusionAppConfig, FusionApp, fusionGlobalManager, fusionBuilderText, FusionPageBuilderApp, FusionPageBuilderElements, FusionEvents, fusionAllElements */
/* eslint no-unused-vars: 0 */
var FusionPageBuilder = FusionPageBuilder || {};
( function() {
jQuery( document ).ready( function() {
// Column View
FusionPageBuilder.ColumnView = FusionPageBuilder.BaseColumnView.extend( {
template: FusionPageBuilder.template( jQuery( '#fusion-builder-column-template' ).html() ),
events: {
'click .fusion-builder-column-settings:not(.fusion-builder-column-inner .fusion-builder-column-setting)': 'settings',
'click .fusion-builder-column-size:not(.fusion-builder-column-inner .fusion-builder-column-size)': 'sizesShow',
'hover .fusion-builder-column-content': 'offsetClass',
'click .column-size:not(.fusion-builder-column-inner .column-size)': 'sizeSelect',
'click .fusion-builder-add-element:not(.fusion-builder-column-inner .fusion-builder-add-element)': 'addModule',
'click .fusion-builder-column-remove:not(.fusion-builder-column-inner .fusion-builder-column-remove)': 'removeColumn',
'click .fusion-builder-column-clone:not(.fusion-builder-column-inner .fusion-builder-column-clone)': 'cloneColumn',
'click .fusion-builder-column-save:not(.fusion-builder-column-inner .fusion-builder-column-save)': 'openLibrary',
'click .fusion-builder-column-drag:not(.fusion-builder-column-inner .fusion-builder-column-drag)': 'preventDefault'
},
/**
* Init.
*
* @since 2.0.0
* @return {void}
*/
initialize: function() {
var params = this.model.get( 'params' ),
spacing = '' !== params.spacing ? spacing : '4%';
this.renderedYet = false;
this.columnSpacer = false;
this.forceAppendChildren = false;
this.listenTo( FusionEvents, 'fusion-view-update-fusion_builder_column', this.reRender );
this.$el.attr( 'data-cid', this.model.get( 'cid' ) );
this.$el.attr( 'id', 'fusion-column-' + this.model.get( 'cid' ) );
this.$el.attr( 'data-column-size', this.model.attributes.params.type );
this.$el.attr( 'data-column-spacing', spacing );
if ( 'undefined' !== typeof this.model.attributes.params && 'undefined' !== typeof this.model.attributes.params.fusion_global ) {
this.$el.attr( 'fusion-global-layout', this.model.attributes.params.fusion_global );
this.$el.removeClass( 'fusion-global-column' ).addClass( 'fusion-global-column' );
}
this.currentClasses = '';
this.baseColumnInit();
this.baseInit();
},
/**
* Renders the view.
*
* @since 2.0.0
* @return {Object} this
*/
render: function() {
var self = this,
data = this.getTemplateAtts(),
columnSize = '';
this.$el.html( this.template( data ) );
if ( 'undefined' !== typeof this.model.attributes.selectors ) {
this.setElementAttributes( this.$el, this.model.attributes.selectors );
}
// Add active column size CSS class
columnSize = this.model.attributes.params.type;
// TODO Check size and update class according.
this.updateSizeIndicators();
this.appendChildren();
setTimeout( function() {
self.droppableColumn();
}, 100 );
// Don't refresh on first render.
if ( this.renderedYet ) {
this._refreshJs();
}
this.renderedYet = true;
return this;
},
droppableColumn: function() {
var self = this,
$el = this.$el,
cid,
$droppables,
$body;
if ( ! $el ) {
return;
}
cid = this.model.get( 'cid' );
$droppables = $el.find( '.fusion-column-target' );
$body = jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' );
$el.draggable( {
appendTo: FusionPageBuilderApp.$el,
zIndex: 999999,
delay: 100,
cursorAt: { top: 15, left: 15 },
iframeScroll: true,
containment: $body,
cancel: '.fusion-builder-live-element, .fusion_builder_row_inner',
helper: function() {
var $classes = FusionPageBuilderApp.DraggableHelpers.draggableClasses( cid ),
style = '';
if ( $el.css( 'margin-top' ) ) {
style = 'style="transform: translateY(' + $el.css( 'margin-top' ) + ');"';
}
return jQuery( '' );
},
start: function() {
$body.addClass( 'fusion-column-dragging fusion-active-dragging' );
$el.addClass( 'fusion-being-dragged' );
if ( 'large' !== FusionApp.getPreviewWindowSize() ) {
$body.addClass( 'fusion-column-dragging-responsive-mode' );
$el.closest( '.fusion-builder-container' ).addClass( 'fusion-has-active-drop-targets' );
}
},
stop: function() {
setTimeout( function() {
$body.removeClass( 'fusion-column-dragging fusion-active-dragging' );
}, 10 );
$el.removeClass( 'fusion-being-dragged' );
if ( 'large' !== FusionApp.getPreviewWindowSize() ) {
$el.closest( '.fusion-builder-container' ).removeClass( 'fusion-has-active-drop-targets' );
$body.removeClass( 'fusion-column-dragging-responsive-mode' );
}
}
} );
$droppables.droppable( {
tolerance: 'touch',
hoverClass: 'ui-droppable-active',
accept: '.fusion-builder-column',
drop: function( event, ui ) {
var handleDropColumn = self.handleDropColumn.bind( self );
handleDropColumn( ui.draggable, $el, jQuery( event.target ) );
}
} );
$el.find( '.fusion-element-target-column' ).droppable( {
tolerance: 'touch',
hoverClass: 'ui-droppable-active',
accept: '.fusion-builder-live-element, .fusion_builder_row_inner',
drop: function( event, ui ) {
var handleElementDropInsideColumn = self.handleElementDropInsideColumn.bind( self );
handleElementDropInsideColumn( ui.draggable, $el );
}
} );
},
handleElementDropInsideColumn: function( $element, $targetEl ) {
var elementView = FusionPageBuilderViewManager.getView( $element.data( 'cid' ) ),
newIndex,
MultiGlobalArgs;
// Move the actual html.
$targetEl.find( '.fusion-builder-column-content:not(.fusion_builder_row_inner .fusion-builder-column-content ):not( .fusion-nested-column-content )' ).append( $element );
newIndex = $element.parent().children( '.fusion-builder-live-element, .fusion_builder_row_inner' ).index( $element );
FusionPageBuilderApp.onDropCollectionUpdate( elementView.model, newIndex, this.model.get( 'cid' ) );
FusionEvents.trigger( 'fusion-history-save-step', fusionBuilderText.moved + ' ' + fusionAllElements[ elementView.model.get( 'element_type' ) ].name + ' ' + fusionBuilderText.element );
// Handle multiple global elements.
MultiGlobalArgs = {
currentModel: elementView.model,
handleType: 'save',
attributes: elementView.model.attributes
};
fusionGlobalManager.handleMultiGlobal( MultiGlobalArgs );
FusionEvents.trigger( 'fusion-content-changed' );
this._equalHeights();
},
handleDropColumn: function( $column, $targetEl, $dropTarget ) {
var destinationRow,
columnCid = $column.data( 'cid' ),
columnView = FusionPageBuilderViewManager.getView( columnCid ),
originalCid = columnView.model.get( 'parent' ),
parentCid = $targetEl.closest( '.fusion-builder-row' ).data( 'cid' ),
originalView,
newIndex;
if ( 'large' !== FusionApp.getPreviewWindowSize() && 'undefined' !== typeof this.isFlex && true === this.isFlex ) {
// Update columns' order.
FusionPageBuilderViewManager.getView( this.model.get( 'parent' ) )._updateResponsiveColumnsOrder(
$column,
$targetEl.closest( '.fusion-builder-row' ).children( '.fusion-builder-column' ),
parseInt( $dropTarget.closest( '.fusion-builder-column' ).data( 'cid' ) ),
$dropTarget.hasClass( 'target-after' )
);
return;
}
// Move the actual html.
if ( $dropTarget.hasClass( 'target-after' ) ) {
$targetEl.after( $column );
} else {
$targetEl.before( $column );
}
destinationRow = FusionPageBuilderViewManager.getView( parentCid );
newIndex = $column.parent().children( '.fusion-builder-column' ).index( $column );
FusionPageBuilderApp.onDropCollectionUpdate( columnView.model, newIndex, parentCid );
// Update destination row which is this current one.
destinationRow.setRowData();
// If destination row and original row are different, update original as well.
if ( parentCid !== originalCid ) {
originalView = FusionPageBuilderViewManager.getView( originalCid );
originalView.setRowData();
}
FusionEvents.trigger( 'fusion-history-save-step', fusionBuilderText.column + ' Order Changed' );
setTimeout( function() {
// If different container type we re-render so that it corrects for new situation.
if ( 'object' !== typeof originalView || FusionPageBuilderApp.sameContainerTypes( originalView.model.get( 'parent' ), destinationRow.model.get( 'parent' ) ) ) {
columnView.droppableColumn();
} else {
FusionEvents.trigger( 'fusion-close-settings-' + columnView.model.get( 'cid' ) );
columnView.reRender();
}
}, 300 );
},
/**
* Things to do, places to go when options change.
*
* @since 2.0.0
* @param {string} paramName - The name of the parameter that changed.
* @param {mixed} paramValue - The value of the option that changed.
* @param {Object} event - The event triggering the option change.
* @return {void}
*/
onOptionChange: function( paramName, paramValue, event ) {
var rowView,
parentCID = this.model.get( 'parent' ),
cid = this.model.get( 'cid' ),
dimensionType = _.find( [ 'spacing_', 'margin_', 'padding_' ], function( type ) {
return paramName.includes( type );
} ),
reInitDraggables = false,
view = {},
values = {},
alphaBackgroundColor = 1;
// Reverted to history step or user entered value manually.
if ( 'undefined' === typeof event || ( 'undefined' !== typeof event && ( 'change' !== event.type || ( 'change' === event.type && 'undefined' !== typeof event.srcElement ) ) ) ) {
reInitDraggables = true;
}
if ( 'spacing' === paramName ) {
this.model.attributes.params[ paramName ] = paramValue;
// Only update preview if it a valid unit.
if ( this.validColumnSpacing( paramValue ) ) {
rowView = FusionPageBuilderViewManager.getView( parentCID );
rowView.setSingleRowData( cid );
}
if ( true === reInitDraggables ) {
if ( 'yes' === paramValue || 'no' === paramValue ) {
this.destroySpacingResizable();
} else {
this.columnSpacer = false;
this.columnSpacing();
}
}
}
if ( dimensionType ) {
this.model.attributes.params[ paramName ] = paramValue;
if ( true === reInitDraggables ) {
if ( 'padding_' === dimensionType ) {
this.destroyPaddingResizable();
this.paddingDrag();
} else {
this.destroyMarginResizable();
this.marginDrag();
}
}
}
if ( 'padding' === paramName ) {
if ( -1 === jQuery( event.target ).attr( 'name' ).indexOf( '_' ) ) {
this.model.attributes.params[ paramName ] = paramValue;
this.renderSectionSeps( event );
this._refreshJs();
}
}
if ( 'padding_left' === paramName || 'padding_right' === paramName ) {
this.renderSectionSeps( event );
}
if ( [ 'border_size', 'border_color', 'border_style', 'border_position' ].includes( paramName ) ) {
this.model.attributes.params[ paramName ] = paramValue;
}
if ( 'render_logics' === paramName ) {
this.reRender();
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).trigger( 'fusion-column-resized', this.model.get( 'cid' ) );
FusionEvents.trigger( 'fusion-column-resized' );
}
},
/**
* Render the section separators.
*
* @since 2.0.0
* @return {void}
*/
renderSectionSeps: function() {
var elements = FusionPageBuilderViewManager.getChildViews( this.model.get( 'cid' ) );
_.each( elements, function( element ) {
if ( 'fusion_section_separator' === element.model.get( 'element_type' ) ) {
element.reRender();
}
} );
},
/**
* Triggers a refresh.
*
* @since 2.0.0
* @return void
*/
refreshJs: function() {
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).trigger( 'fusion-element-render-fusion_builder_column', this.model.attributes.cid );
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).trigger( 'fusion-reinit-background-slider', this.model.attributes.cid );
},
/**
* Changes the border styles for the element.
*
* @since 2.0.0
* @param {Object} event - The event.
* @return {void}
*/
borderStyle: function( event ) {
var borderSize = this.model.attributes.params.border_size + 'px',
borderColor = this.model.attributes.params.border_color,
borderStyle = this.model.attributes.params.border_style,
borderPosition = this.model.attributes.params.border_position,
positions = [ 'top', 'right', 'bottom', 'left' ],
self = this,
$target = ( 'lift_up' === this.model.attributes.params.hover_type ) ? self.$el.find( '.fusion-column-wrapper, .fusion-column-inner-bg-image' ) : self.$el.find( '.fusion-column-wrapper' );
if ( event ) {
event.preventDefault();
}
self.$el.find( '.fusion-column-wrapper, .fusion-column-inner-bg-image' ).css( 'border', '' );
if ( 'all' === borderPosition ) {
_.each( positions, function( position ) {
$target.css( 'border-' + position, borderSize + ' ' + borderStyle + ' ' + borderColor );
} );
} else {
_.each( positions, function( position ) {
if ( position === borderPosition ) {
$target.css( 'border-' + position, borderSize + ' ' + borderStyle + ' ' + borderColor );
} else {
$target.css( 'border-' + position, 'none' );
}
} );
}
},
/**
* Clones a column.
*
* @since 2.0.0
* @param {Object} event - The event.
* @param {bool} forceManually - Force manually, even if it's not an event, to update history and trigger content changes.
* @return {void}
*/
cloneColumn: function( event, forceManually ) {
var columnAttributes = jQuery.extend( true, {}, this.model.attributes ),
$thisColumn,
container;
if ( event ) {
event.preventDefault();
}
columnAttributes.created = 'manually';
columnAttributes.cid = FusionPageBuilderViewManager.generateCid();
columnAttributes.targetElement = this.$el;
columnAttributes.cloned = true;
columnAttributes.at_index = FusionPageBuilderApp.getCollectionIndex( this.$el );
FusionPageBuilderApp.collection.add( columnAttributes );
// Parse column elements
$thisColumn = this.$el;
$thisColumn.find( '.fusion-builder-live-element:not(.fusion-builder-column-inner .fusion-builder-live-element), .fusion-builder-nested-element' ).each( function() {
var $thisModule,
moduleCID,
module,
elementAttributes,
$thisInnerRow,
innerRowCID,
innerRowView;
// Standard element
if ( jQuery( this ).hasClass( 'fusion-builder-live-element' ) ) {
$thisModule = jQuery( this );
moduleCID = 'undefined' === typeof $thisModule.data( 'cid' ) ? $thisModule.find( '.fusion-builder-data-cid' ).data( 'cid' ) : $thisModule.data( 'cid' );
// Get model from collection by cid
module = FusionPageBuilderElements.find( function( model ) {
return model.get( 'cid' ) == moduleCID; // jshint ignore: line
} );
// Clone model attritubes
elementAttributes = jQuery.extend( true, {}, module.attributes );
elementAttributes.created = 'manually';
elementAttributes.cid = FusionPageBuilderViewManager.generateCid();
elementAttributes.parent = columnAttributes.cid;
elementAttributes.from = 'fusion_builder_column';
// Don't need target element, position is defined from order.
delete elementAttributes.targetElementPosition;
FusionPageBuilderApp.collection.add( elementAttributes );
// Inner row/nested element
} else if ( jQuery( this ).hasClass( 'fusion_builder_row_inner' ) ) {
$thisInnerRow = jQuery( this );
innerRowCID = 'undefined' === typeof $thisInnerRow.data( 'cid' ) ? $thisInnerRow.find( '.fusion-builder-data-cid' ).data( 'cid' ) : $thisInnerRow.data( 'cid' );
innerRowView = FusionPageBuilderViewManager.getView( innerRowCID );
// Clone inner row
if ( 'undefined' !== typeof innerRowView ) {
innerRowView.cloneNestedRow( 'clone', columnAttributes.cid );
}
}
} );
// If column is cloned manually
if ( event || forceManually ) {
FusionEvents.trigger( 'fusion-history-save-step', fusionBuilderText.cloned + ' ' + fusionBuilderText.column );
container = FusionPageBuilderViewManager.getView( this.model.get( 'parent' ) );
container.createVirtualRows();
container.updateColumnsPreview();
FusionEvents.trigger( 'fusion-content-changed' );
}
this._refreshJs();
},
/**
* Append the column's children to its content.
*
* @since 2.0.0
* @return {void}
*/
appendChildren: function() {
var self = this,
cid,
view;
this.model.children.each( function( child ) {
cid = child.attributes.cid;
view = FusionPageBuilderViewManager.getView( cid );
self.$el.find( '.fusion-builder-column-content:not(.fusion_builder_row_inner .fusion-builder-column-content ):not( .fusion-nested-column-content )' ).append( view.$el );
} );
this.delegateChildEvents();
},
/**
* Gets the column contents.
*
* @since 2.0.0
* @param {Object} $thisColumn - The jQuery object of the element.
* @return {string}
*/
getColumnContent: function() {
var shortcode = '',
columnParams = {},
self = this,
ColumnAttributesCheck;
_.each( this.model.get( 'params' ), function( value, name ) {
columnParams[ name ] = ( 'undefined' === value || 'undefined' === typeof value ) ? '' : value;
} );
// Legacy support for new column options
ColumnAttributesCheck = {
min_height: '',
last: 'no',
hover_type: 'none',
link: '',
border_position: 'all'
};
_.each( ColumnAttributesCheck, function( value, name ) {
if ( 'undefined' === typeof columnParams[ name ] ) {
columnParams[ name ] = value;
}
} );
this.beforeGenerateShortcode();
// Build column shortcode
shortcode += '[fusion_builder_column type="' + this.model.attributes.params.type + '"';
_.each( columnParams, function( value, name ) {
if ( ( 'on' === fusionAppConfig.removeEmptyAttributes && '' !== value ) || 'off' === fusionAppConfig.removeEmptyAttributes ) {
shortcode += ' ' + name + '="' + value + '"';
}
} );
shortcode += ']';
// Find elements inside this column
this.$el.find( '.fusion-builder-live-element:not(.fusion-builder-column-inner .fusion-builder-live-element), .fusion-builder-nested-element' ).each( function() {
var $thisRowInner;
// Find standard elements
if ( jQuery( this ).hasClass( 'fusion-builder-live-element' ) ) {
shortcode += FusionPageBuilderApp.generateElementShortcode( jQuery( this ), false );
// Find inner rows
} else {
$thisRowInner = FusionPageBuilderViewManager.getView( jQuery( this ).data( 'cid' ) );
if ( 'undefined' !== typeof $thisRowInner ) {
shortcode += $thisRowInner.getInnerRowContent();
}
}
} );
shortcode += '[/fusion_builder_column]';
return shortcode;
},
/**
* Removes a column.
*
* @since 2.0.0
* @param {Object} event - The event triggering the column removal.
* @param {bool} forceManually - Force manually, even if it's not an event, to update history and trigger content changes.
* @return {void}
*/
removeColumn: function( event, forceManually ) {
var elements,
rowView,
parentCID = this.model.get( 'parent' );
if ( event ) {
event.preventDefault();
}
elements = FusionPageBuilderViewManager.getChildViews( this.model.get( 'cid' ) );
_.each( elements, function( element ) {
if ( 'fusion_builder_row' === element.model.get( 'type' ) || 'fusion_builder_row_inner' === element.model.get( 'type' ) ) {
element.removeRow();
} else {
element.removeElement();
}
} );
FusionPageBuilderViewManager.removeView( this.model.get( 'cid' ) );
this._equalHeights( parentCID );
FusionEvents.trigger( 'fusion-element-removed', this.model.get( 'cid' ) );
this.model.destroy();
this.remove();
// If the column is deleted manually
if ( event || forceManually ) {
// Update preview for spacing.
rowView = FusionPageBuilderViewManager.getView( parentCID );
rowView.setRowData();
FusionEvents.trigger( 'fusion-history-save-step', fusionBuilderText.deleted + ' ' + fusionBuilderText.column );
FusionEvents.trigger( 'fusion-content-changed' );
rowView.$el.find( '.fusion-builder-module-controls-container a' ).trigger( 'mouseleave' );
}
},
/**
* Adds a child view.
*
* @since 2.0.0
* @param {Object} element - The element.
* @return {void}
*/
addChildView: function( element ) {
var view,
viewSettings = {
model: element,
collection: FusionPageBuilderElements,
attributes: {
'data-cid': element.get( 'cid' )
}
},
containerSuffix = ':not(.fusion_builder_row_inner .fusion-builder-column-content)';
if ( 'undefined' !== typeof element.get( 'multi' ) && 'multi_element_parent' === element.get( 'multi' ) ) {
if ( 'undefined' !== typeof FusionPageBuilder[ element.get( 'element_type' ) ] ) {
view = new FusionPageBuilder[ element.get( 'element_type' ) ]( viewSettings );
} else {
view = new FusionPageBuilder.ParentElementView( viewSettings );
}
} else if ( 'undefined' !== typeof FusionPageBuilder[ element.get( 'element_type' ) ] ) {
view = new FusionPageBuilder[ element.get( 'element_type' ) ]( viewSettings );
} else if ( 'fusion_builder_row_inner' === element.get( 'element_type' ) ) {
view = new FusionPageBuilder.InnerRowView( viewSettings );
} else {
view = new FusionPageBuilder.ElementView( viewSettings );
}
// Add new view to manager.
FusionPageBuilderViewManager.addView( element.get( 'cid' ), view );
if ( 'undefined' !== typeof this.model && 'fusion_builder_column_inner' === this.model.get( 'type' ) ) {
containerSuffix = '';
}
if ( ! _.isUndefined( element.get( 'targetElement' ) ) && 'undefined' === typeof element.get( 'from' ) ) {
if ( 'undefined' === typeof element.get( 'targetElementPosition' ) || 'after' === element.get( 'targetElementPosition' ) ) {
element.get( 'targetElement' ).after( view.render().el );
} else {
element.get( 'targetElement' ).before( view.render().el );
}
} else if ( 'undefined' === typeof element.get( 'targetElementPosition' ) || 'end' === element.get( 'targetElementPosition' ) ) {
if ( 'fusion_widget' === view.model.get( 'element_type' ) ) {
// eslint-disable-next-line vars-on-top
var renderedView = view.render();
renderedView.$el.find( 'script' ).remove();
this.$el.find( '.fusion-builder-column-content' + containerSuffix ).append( renderedView.el );
} else {
this.$el.find( '.fusion-builder-column-content' + containerSuffix ).append( view.render().el );
}
} else {
this.$el.find( '.fusion-builder-column-content' + containerSuffix ).find( '.fusion-builder-empty-column' ).first().after( view.render().el );
}
// Check if we should open the settings or not.
if ( 'off' !== window.FusionApp.preferencesData.open_settings && 'undefined' !== typeof element.get( 'added' ) ) {
if ( 'fusion_builder_row_inner' === element.get( 'type' ) ) {
view.editRow();
} else {
view.settings();
}
}
},
/**
* Get the save label.
*
* @since 2.0.0
* @return {string}
*/
getSaveLabel: function() {
return fusionBuilderText.save_column;
},
/**
* Returns the 'columns' string.
*
* @since 2.0.0
* @return {string}
*/
getCategory: function() {
return 'columns';
},
/**
* Column spacing dimensions version.
*
* @since 2.0.0
* @return {void}
*/
fallbackColumnSpacing: function( $placeholder, allNo ) {
var columnSize = '100%',
fullcolumnSize = columnSize,
existingSpacing = '0%',
columnWidth = this.model.attributes.params.type;
if ( 'yes' === this.model.attributes.params.spacing ) {
existingSpacing = '4%';
}
columnWidth = this.model.attributes.params.type;
switch ( columnWidth ) {
case '1_1':
columnSize = '100%';
fullcolumnSize = '100%';
break;
case '1_4':
columnSize = '22%';
fullcolumnSize = '25%';
break;
case '3_4':
columnSize = '74%';
fullcolumnSize = '75%';
break;
case '1_2':
columnSize = '48%';
fullcolumnSize = '50%';
break;
case '1_3':
columnSize = '30.6666%';
fullcolumnSize = '33.3333%';
break;
case '2_3':
columnSize = '65.3333%';
fullcolumnSize = '66.6666%';
break;
case '1_5':
columnSize = '16.8%';
fullcolumnSize = '20%';
break;
case '2_5':
columnSize = '37.6%';
fullcolumnSize = '40%';
break;
case '3_5':
columnSize = '58.4%';
fullcolumnSize = '60%';
break;
case '4_5':
columnSize = '79.2%';
fullcolumnSize = '80%';
break;
case '5_6':
columnSize = '82.6666%';
fullcolumnSize = '83.3333%';
break;
case '1_6':
columnSize = '13.3333%';
fullcolumnSize = '16.6666%';
break;
}
if ( '4%' !== existingSpacing && ( ! this.model.attributes.params.last || allNo ) ) {
columnSize = fullcolumnSize;
}
this.$el.css( 'width', columnSize );
$placeholder.css( 'width', columnSize );
$placeholder.css( 'margin-right', existingSpacing );
this.$el.css( 'margin-right', existingSpacing );
},
/**
* Checks if column layout type is block.
*
* @since 3.0.0
* @return {Boolean}
*/
isBlockLayout: function() {
return this.values && 'block' === this.values.content_layout;
}
} );
} );
}( jQuery ) );
;/* global FusionApp, FusionPageBuilderApp, FusionPageBuilderViewManager, fusionAllElements, fusionBuilderText, FusionEvents, FusionPageBuilderElements */
/* jshint -W020 */
/* eslint no-shadow: 0 */
var FusionPageBuilder = FusionPageBuilder || {};
( function() {
jQuery( document ).ready( function() {
// Builder Container View
FusionPageBuilder.ContainerView = FusionPageBuilder.BaseView.extend( {
template: FusionPageBuilder.template( jQuery( '#fusion-builder-container-template' ).html() ),
className: function() {
var classes = 'fusion-builder-container fusion-builder-data-cid',
values = _.fusionCleanParameters( jQuery.extend( true, {}, this.model.get( 'params' ) ) );
if ( 'yes' === values.hundred_percent_height_scroll && 'yes' === values.hundred_percent_height ) {
classes += ' scrolling-helper';
}
if ( this.isFlex ) {
classes += ' fusion-builder-flex-container';
}
if ( values.status && 'draft' === values.status ) {
classes += ' fusion-builder-container-status-draft';
}
// Absolute container.
if ( 'undefined' !== typeof values.absolute && 'on' === values.absolute ) {
classes += ' fusion-builder-absolute-container-wrapper';
}
return classes;
},
events: {
'click .fusion-builder-container-settings': 'settings',
'click .fusion-builder-container-remove': 'removeContainer',
'click .fusion-builder-container-clone': 'cloneContainer',
'click .fusion-builder-container-add': 'addContainer',
'click .fusion-builder-container-save': 'openLibrary',
'click .fusion-builder-publish-tooltip': 'publish',
'click .fusion-builder-unglobal-tooltip': 'unglobalize',
'click .fusion-builder-container-drag': 'preventDefault'
},
/**
* Init.
*
* @since 2.0.0
* @return {void}
*/
initialize: function() {
var cid = this.model.get( 'cid' ),
el = this.$el;
el.attr( 'data-cid', cid );
el.attr( 'id', 'fusion-container-' + cid );
if ( 'undefined' !== typeof this.model.attributes.params && 'undefined' !== typeof this.model.attributes.params.fusion_global ) {
el.attr( 'fusion-global-layout', this.model.attributes.params.fusion_global );
this.$el.removeClass( 'fusion-global-container' ).addClass( 'fusion-global-container' );
}
this.listenTo( FusionEvents, 'fusion-view-update-fusion_builder_container', this.reRender );
this.listenTo( FusionEvents, 'fusion-param-changed-' + this.model.get( 'cid' ), this.onOptionChange );
// Responsive control updates on resize.
this.listenTo( FusionEvents, 'fusion-preview-viewport-update', this.onPreviewResize );
this._triggerCallback = _.debounce( _.bind( this.triggerCallback, this ), 200 );
this.model.children = new FusionPageBuilder.Collection();
this.listenTo( this.model.children, 'add', this.addChildView );
this.renderedYet = FusionPageBuilderApp.loaded;
this._refreshJs = _.debounce( _.bind( this.refreshJs, this ), 300 );
this._triggerScrollUpdate = _.debounce( _.bind( this.triggerScrollUpdate, this ), 300 );
this._reInitSticky = _.debounce( _.bind( this.reInitSticky, this ), 300 );
this._updateInnerStyles = _.debounce( _.bind( this.updateInnerStyles, this ), 500 );
this.scrollingSections = false;
this.settingsControlsOffset = 0;
this.width = el.width();
el.on( 'mouseenter', _.bind( this.setSettingsControlsOffset, this ) );
this.correctStackingContextForFilters();
this.deprecatedParams();
this.baseInit();
this.reInitDraggables = false;
},
/**
* Set correct top offset for the container setting controls.
*
* @since 2.0
* @param {boolean} forced - Whether to force an update and bypass checks.
* @return {void}
*/
setSettingsControlsOffset: function( forced ) {
var offset = 15,
customOffset;
if ( ( 'undefined' !== typeof forced || 0 === this.settingsControlsOffset || this.width !== this.$el.width() ) && ( 'undefined' !== typeof window.frames[ 0 ].getStickyHeaderHeight || 'undefined' !== typeof window.frames[ 0 ].fusionGetStickyOffset ) ) {
// if we have sticky enabled, get its height.
if ( 'off' !== FusionApp.preferencesData.sticky_header && 'on' !== this.values.sticky ) {
// If we have a custom header, use function to retrieve lowest point.
if ( jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( '.fusion-tb-header' ).length && 'function' === typeof window.frames[ 0 ].fusionGetStickyOffset ) {
customOffset = window.frames[ 0 ].fusionGetStickyOffset();
if ( customOffset ) {
offset += customOffset;
}
} else if ( 'undefined' !== typeof window.frames[ 0 ].getStickyHeaderHeight ) {
offset += window.frames[ 0 ].getStickyHeaderHeight( true );
}
}
this.settingsControlsOffset = offset + 'px';
this.width = this.$el.width();
this.$el.find( '.fusion-builder-module-controls-container-wrapper .fusion-builder-module-controls-type-container' ).css( 'top', this.settingsControlsOffset );
}
if ( this.$el.find( '.fusion-builder-empty-container' ).is( ':visible' ) ) {
this.$el.find( '.fusion-builder-module-controls-container-wrapper .fusion-builder-module-controls-type-container' ).css( 'margin-top', '8.5px' );
} else {
this.$el.find( '.fusion-builder-module-controls-container-wrapper .fusion-builder-module-controls-type-container' ).css( 'margin-top', '' );
}
},
/**
* Corrects the stacking context if filters are used, to make all elements accessible.
*
* @since 2.2
* @return {void}
*/
correctStackingContextForFilters: function() {
var parent = this.$el;
this.$el.on( 'mouseenter', '.fusion-fullwidth', function() {
if ( 'none' !== jQuery( this ).css( 'filter' ) ) {
parent.addClass( 'fusion-has-filters' );
}
} );
this.$el.on( 'mouseleave', '.fusion-fullwidth', function() {
if ( ! parent.hasClass( 'fusion-container-editing-child' ) ) {
parent.removeClass( 'fusion-has-filters' );
}
} );
},
/**
* Renders the view.
*
* @since 2.0.0
* @return {Object} this
*/
render: function() {
var self = this,
data = this.getTemplateAtts();
this.$el.html( this.template( data ) );
this.appendChildren();
if ( this.renderedYet ) {
this._refreshJs();
// Trigger equal height columns js
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).trigger( 'fusion-option-change-equal_height_columns', this.model.attributes.cid );
}
this.onRender();
this.renderedYet = true;
setTimeout( function() {
self.droppableContainer();
}, 100 );
this._triggerScrollUpdate();
return this;
},
/**
* Adds drop zones for continers and makes container draggable.
*
* @since 2.0.0
* @return {void}
*/
droppableContainer: function() {
var $el = this.$el,
self = this,
cid = this.model.get( 'cid' ),
$body = jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' );
if ( ! $el ) {
return;
}
$el.draggable( {
appendTo: FusionPageBuilderApp.$el,
zIndex: 999999,
delay: 100,
cursorAt: { top: 15, left: 15 },
iframeScroll: true,
containment: $body,
cancel: '.fusion-builder-column',
helper: function() {
var $classes = FusionPageBuilderApp.DraggableHelpers.draggableClasses( cid );
return jQuery( '
' );
},
start: function() {
$body.addClass( 'fusion-container-dragging fusion-active-dragging' );
$el.addClass( 'fusion-being-dragged' );
// Add a class to hide the unnecessary target after.
if ( $el.prev( '.fusion-builder-container' ).length ) {
$el.prev( '.fusion-builder-container' ).addClass( 'hide-target-after' );
}
if ( $el.prev( '.fusion-fusion-builder-next-pager' ).length ) {
$el.prev( '.fusion-fusion-builder-next-page' ).addClass( 'hide-target-after' );
}
},
stop: function() {
setTimeout( function() {
$body.removeClass( 'fusion-container-dragging fusion-active-dragging' );
}, 10 );
$el.removeClass( 'fusion-being-dragged' );
FusionPageBuilderApp.$el.find( '.hide-target-after' ).removeClass( 'hide-target-after' );
}
} );
$el.find( '.fusion-container-target' ).droppable( {
tolerance: 'touch',
hoverClass: 'ui-droppable-active',
accept: '.fusion-builder-container, .fusion-builder-next-page, .fusion-checkout-form, .fusion-builder-form-step',
drop: function( event, ui ) {
self.handleDropContainer( ui.draggable, $el, jQuery( event.target ) );
}
} );
},
handleDropContainer( $column, $targetEl, $dropTarget ) {
// Move the actual html.
if ( jQuery( $dropTarget ).hasClass( 'target-after' ) ) {
$targetEl.after( $column );
} else {
$targetEl.before( $column );
}
FusionEvents.trigger( 'fusion-content-changed' );
FusionPageBuilderApp.scrollingContainers();
FusionEvents.trigger( 'fusion-history-save-step', fusionBuilderText.full_width_section + ' Order Changed' );
},
/**
* Get the template.
*
* @since 2.0.0
* @return {void}
*/
getTemplate: function() {
var atts = this.getTemplateAtts();
return this.template( atts );
},
/**
* Remove deprecated params.
*
* @since 2.0.0
* @return {void}
*/
deprecatedParams: function() {
var params = this.model.get( 'params' ),
defaults = fusionAllElements.fusion_builder_container.defaults,
values = jQuery.extend( true, {}, defaults, params ),
alphaBackgroundColor = 1,
radiaDirectionsNew = { 'bottom': 'center bottom', 'bottom center': 'center bottom', 'left': 'left center', 'right': 'right center', 'top': 'center top', 'center': 'center center', 'center left': 'left center' };
params = _.fusionContainerMapDeprecatedArgs( params );
// If no blend mode is defined, check if we should set to overlay.
if ( 'undefined' === typeof params.background_blend_mode && '' !== values.background_color ) {
alphaBackgroundColor = jQuery.AWB_Color( values.background_color ).alpha();
if ( 1 > alphaBackgroundColor && 0 !== alphaBackgroundColor && ( '' !== params.background_image || '' !== params.video_bg ) ) {
params.background_blend_mode = 'overlay';
}
}
// Check if we have an old border-size. If we do, then we need to migrate it to the new options
// and delete the old param.
if ( 'undefined' !== typeof params.border_size ) {
if ( '' !== params.border_size ) {
params.border_sizes_top = parseInt( params.border_size ) + 'px';
params.border_sizes_bottom = parseInt( params.border_size ) + 'px';
params.border_sizes_left = '0px';
params.border_sizes_right = '0px';
}
delete params.border_size;
}
// Correct radial direction params.
if ( 'undefined' !== typeof params.radial_direction && ( params.radial_direction in radiaDirectionsNew ) ) {
params.radial_direction = radiaDirectionsNew[ values.radial_direction ];
}
// No column align, but equal heights is on, set to stretch.
if ( 'undefined' === typeof params.flex_align_items && 'undefined' !== typeof params.equal_height_columns && 'yes' === params.equal_height_columns ) {
params.flex_align_items = 'stretch';
}
// No align content, but it is 100% height and centered.
if ( 'undefined' === typeof params.align_content && 'undefined' !== typeof params.hundred_percent_height && 'yes' === params.hundred_percent_height && 'undefined' !== typeof params.hundred_percent_height_center_content && 'yes' === params.hundred_percent_height_center_content ) {
params.align_content = 'center';
}
// If legacy mode is off, remove param, causes it to run migration and then setType is called.
if ( ( 'undefined' === typeof params.type || 'flex' !== params.type ) && 'undefined' !== typeof fusionAllElements.fusion_builder_container.extras.container_legacy_support && ( 0 === fusionAllElements.fusion_builder_container.extras.container_legacy_support || '0' === fusionAllElements.fusion_builder_container.extras.container_legacy_support || false === fusionAllElements.fusion_builder_container.extras.container_legacy_support ) ) {
delete params.type;
}
this.model.set( 'params', params );
},
/**
* Set type to ensure migration does not run on front-end.
*
* @since 3.0
* @return {Void}
*/
setType: function() {
var params = this.model.get( 'params' ),
defaults = fusionAllElements.fusion_builder_container.defaults;
if ( 'undefined' === typeof params.type ) {
params.type = defaults.type;
}
this.model.set( 'params', params );
},
/**
* Get dynamic values.
*
* @since 2.0.0
* @return {Object}
*/
getDynamicAtts: function( values ) {
var self = this;
if ( 'undefined' !== typeof this.dynamicParams && this.dynamicParams && ! _.isEmpty( this.dynamicParams.getAll() ) ) {
_.each( this.dynamicParams.getAll(), function( data, id ) {
var value = self.dynamicParams.getParamValue( data );
if ( 'undefined' !== typeof value && false !== value ) {
values[ id ] = value;
}
} );
}
return values;
},
setValues: function() {
var element = fusionAllElements[ this.model.get( 'element_type' ) ],
defaults = fusionAllElements.fusion_builder_container.defaults,
params = jQuery.extend( true, {}, this.model.get( 'params' ) ),
extras = {},
values = {},
borderRadius;
extras = jQuery.extend( true, {}, fusionAllElements.fusion_builder_container.extras );
// If 100 page template.
if ( ( FusionPageBuilderApp.$el.hasClass( 'single-awb_off_canvas' ) || FusionPageBuilderApp.$el.find( '#main' ).hasClass( 'width-100' ) ) && 'undefined' !== typeof extras.container_padding_100 ) {
defaults.padding_top = extras.container_padding_100.top;
defaults.padding_right = extras.container_padding_100.right;
defaults.padding_bottom = extras.container_padding_100.bottom;
defaults.padding_left = extras.container_padding_100.left;
} else if ( ! FusionPageBuilderApp.$el.find( '#main' ).hasClass( 'width-100' ) && 'undefined' !== typeof extras.container_padding_default ) {
defaults.padding_top = extras.container_padding_default.top;
defaults.padding_right = extras.container_padding_default.right;
defaults.padding_bottom = extras.container_padding_default.bottom;
defaults.padding_left = extras.container_padding_default.left;
}
params = _.fusionCleanParameters( params );
// Set values & extras
if ( element && 'undefined' !== typeof element.defaults ) {
values = jQuery.extend( true, {}, defaults, params );
}
// Default value is an array, so we need to convert it to string.
if ( Array.isArray( values.absolute_devices ) ) {
values.absolute_devices = values.absolute_devices.join( ',' );
}
values = this.getDynamicAtts( values );
this.defaults = defaults;
this.values = values;
this.params = params;
if ( 'on' === this.values.sticky ) {
this.values.background_parallax = 'none';
this.values.fade = 'no';
}
this.values.border_radius_top_left = this.values.border_radius_top_left ? _.fusionGetValueWithUnit( this.values.border_radius_top_left ) : '0px';
this.values.border_radius_top_right = this.values.border_radius_top_right ? _.fusionGetValueWithUnit( this.values.border_radius_top_right ) : '0px';
this.values.border_radius_bottom_left = this.values.border_radius_bottom_left ? _.fusionGetValueWithUnit( this.values.border_radius_bottom_left ) : '0px';
this.values.border_radius_bottom_right = this.values.border_radius_bottom_right ? _.fusionGetValueWithUnit( this.values.border_radius_bottom_right ) : '0px';
borderRadius = this.values.border_radius_top_left + ' ' + this.values.border_radius_top_right + ' ' + this.values.border_radius_bottom_right + ' ' + this.values.border_radius_bottom_left;
if ( '0px 0px 0px 0px' !== borderRadius && '' === this.values.overflow ) {
this.values.overflow = 'hidden';
}
},
/**
* Set extra args.
*
* @since 2.0.0
* @return {void}
*/
setExtraValues: function() {
this.values.alpha_background_color = jQuery.AWB_Color( this.values.background_color ).alpha();
},
contentStyle: function() {
var self = this,
contentStyle = '';
if ( 'yes' === this.values.hundred_percent_height && 'yes' === this.values.hundred_percent_height_center_content ) {
// Get correct container padding.
jQuery.each( [ 'top', 'right', 'bottom', 'left' ], function( index, padding ) {
var paddingName = 'padding_' + padding;
// Add padding to style.
if ( '' !== self.values[ paddingName ] ) {
contentStyle += 'padding-' + padding + ':' + _.fusionGetValueWithUnit( self.values[ paddingName ] ) + ';';
}
} );
}
return contentStyle;
},
/**
* Sets container video data args.
*
* @access public
* @since 3.0
* @return void
*/
setContainerVideoData: function() {
// If no blend mode is defined, check if we should set to overlay.
if ( 'undefined' !== typeof this.values.background_blend_mode &&
1 > this.values.alpha_background_color &&
0 !== this.values.alpha_background_color &&
! this.is_gradient_color &&
( this.background_image || this.values.video_bg ) ) {
this.values.background_blend_mode = 'overlay';
}
this.values.video_bg = false;
if ( this.values.video_mp4 || this.values.video_webm || this.values.video_ogv || this.values.video_url ) {
this.values.video_bg = true;
}
},
parallaxAttr: function() {
var attr = {},
bgColorAlpha = jQuery.AWB_Color( this.values.background_color ).alpha();
attr[ 'class' ] = 'fusion-bg-parallax';
attr[ 'data-bg-align' ] = this.values.background_position;
attr[ 'data-direction' ] = this.values.background_parallax;
attr[ 'data-mute' ] = 'mute' === this.values.video_mute ? 'true' : 'false';
attr[ 'data-opacity' ] = this.values.opacity;
attr[ 'data-velocity' ] = this.values.parallax_speed * -1;
attr[ 'data-mobile-enabled' ] = 'yes' === this.values.enable_mobile ? 'true' : 'false';
attr[ 'data-break_parents' ] = this.values.break_parents;
attr[ 'data-bg-image' ] = this.values.background_image;
attr[ 'data-bg-repeat' ] = this.values.background_repeat && 'no-repeat' !== this.values.background_repeat ? 'true' : 'false';
if ( 0 !== bgColorAlpha ) {
attr[ 'data-bg-color' ] = this.values.background_color;
}
if ( 'none' !== this.values.background_blend_mode ) {
attr[ 'data-blend-mode' ] = this.values.background_blend_mode;
}
if ( this.values.is_gradient_color ) {
attr[ 'data-bg-gradient-type' ] = this.values.gradient_type;
attr[ 'data-bg-gradient-angle' ] = this.values.linear_angle;
attr[ 'data-bg-gradient-start-color' ] = this.values.gradient_start_color;
attr[ 'data-bg-gradient-start-position' ] = this.values.gradient_start_position;
attr[ 'data-bg-gradient-end-color' ] = this.values.gradient_end_color;
attr[ 'data-bg-gradient-end-position' ] = this.values.gradient_end_position;
attr[ 'data-bg-radial-direction' ] = this.values.radial_direction;
}
attr[ 'data-bg-height' ] = this.values.data_bg_height;
attr[ 'data-bg-width' ] = this.values.data_bg_width;
return attr;
},
isFlex: function() {
return this.values && 'flex' === this.values.type;
},
attr: function() {
var attr = {
'class': 'fusion-fullwidth fullwidth-box fusion-builder-row-live-' + this.model.get( 'cid' ),
'style': this.getInlineStyle(),
'id': ''
};
if ( this.isFlex() ) {
attr[ 'class' ] += ' fusion-flex-container';
if ( 'stretch' !== this.values.align_content ) {
attr[ 'class' ] += ' fusion-flex-align-content-' + this.values.align_content;
}
}
if ( this.values.video_bg ) {
attr[ 'class' ] += ' video-background';
}
// Fading Background.
if ( 'yes' === this.values.fade && '' !== this.values.background_image && false === this.values.video_bg ) {
attr[ 'class' ] += ' faded-background';
}
// Parallax.
if ( false === this.values.video_bg && '' !== this.values.background_image ) {
// Parallax css class+
if ( '' !== this.values.background_parallax ) {
attr[ 'class' ] += ' fusion-parallax-' + this.values.background_parallax;
}
if ( 'fixed' === this.values.background_parallax ) {
attr.style += 'background-attachment:' + this.values.background_parallax + ';';
}
}
// Custom CSS class+
if ( '' !== this.values[ 'class' ] ) {
attr[ 'class' ] += ' ' + this.values[ 'class' ];
}
attr[ 'class' ] += ( 'yes' === this.values.hundred_percent ) ? ' hundred-percent-fullwidth' : ' nonhundred-percent-fullwidth';
attr[ 'class' ] += ( 'yes' === this.values.hundred_percent_height_scroll && 'yes' === this.values.hundred_percent_height ) ? ' fusion-scrolling-section-edit' : '';
attr[ 'class' ] += ( 'yes' === this.values.hundred_percent_height ) ? ' non-hundred-percent-height-scrolling' : '';
attr[ 'class' ] += ( 'yes' === this.values.hundred_percent_height && 'yes' !== this.values.hundred_percent_height_center_content ) ? ' hundred-percent-height' : '';
attr[ 'class' ] += ( 'yes' === this.values.hundred_percent_height && 'yes' === this.values.hundred_percent_height_center_content ) ? ' hundred-percent-height-center-content' : '';
// Equal column height.
if ( 'yes' === this.values.equal_height_columns && ! this.isFlex() ) {
attr[ 'class' ] += ' fusion-equal-height-columns';
}
// Hundred percent height and centered content, if added to centerContentClass then the padding makes the container too large.
if ( 'yes' === this.values.hundred_percent_height && 'yes' === this.values.hundred_percent_height_center_content ) {
attr[ 'class' ] += ' hundred-percent-height non-hundred-percent-height-scrolling';
}
// Visibility classes.
let visibilityValue = this.values.hide_on_mobile;
// Get Render logics Array.
const renderLogicsDevices = this.getRenderLogicsDevices();
if ( renderLogicsDevices.length && 'on' === FusionApp.preferencesData.rendering_logic ) {
const rlDevicesEqual = [];
const rlDevicesNotEqual = [];
renderLogicsDevices.forEach( ( r ) => {
switch ( r.value ) {
case 'desktop':
if ( 'equal' === r.comparison ) {
rlDevicesEqual.push( 'large-visibility' );
} else {
rlDevicesNotEqual.push( 'large-visibility' );
}
break;
case 'tablet':
if ( 'equal' === r.comparison ) {
rlDevicesEqual.push( 'medium-visibility' );
} else {
rlDevicesNotEqual.push( 'medium-visibility' );
}
break;
case 'mobile':
if ( 'equal' === r.comparison ) {
rlDevicesEqual.push( 'small-visibility' );
} else {
rlDevicesNotEqual.push( 'small-visibility' );
}
break;
case 'mobile_tablet':
if ( 'equal' === r.comparison ) {
rlDevicesEqual.push( 'medium-visibility' );
rlDevicesEqual.push( 'small-visibility' );
} else {
rlDevicesNotEqual.push( 'medium-visibility' );
rlDevicesNotEqual.push( 'small-visibility' );
}
break;
}
} );
if ( rlDevicesEqual.length ) {
attr[ 'class' ] = _.fusionVisibilityAtts( rlDevicesEqual.join( ',' ), attr[ 'class' ] );
}
if ( rlDevicesNotEqual.length ) {
visibilityValue = visibilityValue.split( ',' ).filter( ( v ) => !rlDevicesNotEqual.includes( v ) );
}
}
attr[ 'class' ] = _.fusionVisibilityAtts( visibilityValue, attr[ 'class' ] );
// Animations.
attr = _.fusionAnimations( this.values, attr );
// Custom CSS ID.
if ( '' !== this.values.id ) {
attr.id = this.values.id;
}
if ( '' !== this.values.menu_anchor ) {
attr.id += ' ' + this.values.menu_anchor;
}
// Sticky container.
if ( 'on' === this.values.sticky ) {
attr[ 'class' ] += ' fusion-sticky-container';
if ( '' !== this.values.sticky_transition_offset && 0 !== this.values.sticky_transition_offset ) {
attr[ 'data-transition-offset' ] = parseFloat( this.values.sticky_transition_offset );
}
if ( '' !== this.values.sticky_offset && 0 !== this.values.sticky_offset ) {
attr[ 'data-sticky-offset' ] = this.values.sticky_offset;
}
if ( '' !== this.values.scroll_offset && 0 !== this.values.scroll_offset ) {
attr[ 'data-scroll-offset' ] = parseFloat( this.values.scroll_offset );
}
if ( '' !== this.values.sticky_devices ) {
if ( 'string' === typeof this.values.sticky_devices ) {
this.values.sticky_devices = this.values.sticky_devices.split( ',' );
}
_.each( this.values.sticky_devices, function( stickyDevice ) {
attr[ 'data-sticky-' + stickyDevice.replace( /\s/g, '' ) ] = true;
} );
}
}
// z-index.
if ( 'undefined' !== typeof this.values.z_index && '' !== this.values.z_index ) {
attr[ 'class' ] += ' fusion-custom-z-index';
}
// Absolute container.
if ( 'undefined' !== typeof this.values.absolute && 'on' === this.values.absolute ) {
attr[ 'class' ] += ' fusion-absolute-container';
if ( 'undefined' !== typeof this.values.absolute_devices && '' !== this.values.absolute_devices ) {
_.each( this.values.absolute_devices.split( ',' ), function( absoluteDevice ) {
attr[ 'class' ] += ' fusion-absolute-position-' + absoluteDevice;
} );
}
}
if ( this.values.pattern_bg ) {
attr[ 'class' ] += ' has-pattern-background';
}
if ( this.values.mask_bg ) {
attr[ 'class' ] += ' has-mask-background';
}
return attr;
},
getInlineStyle: function() {
var customVars = {},
cssVars,
boxShadow;
cssVars = [
'background_position',
'background_position_medium',
'background_position_small',
'background_repeat',
'background_repeat_medium',
'background_repeat_small',
'background_blend_mode',
'background_blend_mode_medium',
'background_blend_mode_small',
'border_sizes_top',
'border_sizes_bottom',
'border_sizes_left',
'border_sizes_right',
'border_color',
'border_style',
'border_radius_top_left',
'border_radius_top_right',
'border_radius_bottom_right',
'border_radius_bottom_left',
'overflow',
'z_index'
];
// Background.
if ( '' !== this.values.background_color && ! ( 'yes' === this.values.fade && '' !== this.values.background_image && false === this.values.video_bg ) ) {
customVars.background_color = this.values.background_color;
}
if ( '' !== this.values.background_color_medium ) {
customVars.background_color_medium = this.values.background_color_medium;
}
if ( '' !== this.values.background_color_small ) {
customVars.background_color_small = this.values.background_color_small;
}
if ( '' !== this.values.background_image && 'yes' !== this.values.fade ) {
customVars.background_image = 'url(\'' + this.values.background_image + '\')';
}
if ( '' !== this.values.background_image_medium ) {
customVars.background_image_medium = 'url(\'' + this.values.background_image_medium + '\')';
}
if ( '' !== this.values.background_image_small ) {
customVars.background_image_small = 'url(\'' + this.values.background_image_small + '\')';
}
if ( '' !== _.getGradientString( this.values, 'main_bg' ) ) {
customVars.background_image = _.getGradientString( this.values, 'main_bg' );
if ( '' !== this.values.background_image_medium ) {
customVars.background_image_medium = _.getGradientString( this.values, 'column', 'medium' );
}
if ( '' !== this.values.background_image_small ) {
customVars.background_image_small = _.getGradientString( this.values, 'column', 'small' );
}
}
if ( 'on' === this.values.sticky ) {
if ( '' !== this.values.sticky_background_color ) {
customVars.sticky_background_color = this.values.sticky_background_color + ' !important';
}
if ( '' !== this.values.sticky_height ) {
customVars.sticky_height = this.values.sticky_height + ' !important';
}
}
if ( undefined !== this.values.flex_wrap && '' !== this.values.flex_wrap ) {
customVars.flex_wrap = this.values.flex_wrap;
}
if ( undefined !== this.values.flex_wrap_medium && '' !== this.values.flex_wrap_medium ) {
customVars.flex_wrap_medium = this.values.flex_wrap_medium;
}
if ( undefined !== this.values.flex_wrap_small && '' !== this.values.flex_wrap_small ) {
customVars.flex_wrap_small = this.values.flex_wrap_small;
}
if ( ! this.isFlex() ) {
cssVars.padding_top = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_right = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_bottom = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_left = { 'callback': _.fusionGetValueWithUnit };
cssVars.margin_top = { 'callback': _.fusionGetValueWithUnit };
cssVars.margin_bottom = { 'callback': _.fusionGetValueWithUnit };
} else {
cssVars.padding_top = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_right = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_bottom = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_left = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_top_medium = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_right_medium = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_bottom_medium = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_left_medium = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_top_small = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_right_small = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_bottom_small = { 'callback': _.fusionGetValueWithUnit };
cssVars.padding_left_small = { 'callback': _.fusionGetValueWithUnit };
cssVars.margin_top = { 'callback': _.fusionGetValueWithUnit };
cssVars.margin_bottom = { 'callback': _.fusionGetValueWithUnit };
cssVars.margin_top_medium = { 'callback': _.fusionGetValueWithUnit };
cssVars.margin_bottom_medium = { 'callback': _.fusionGetValueWithUnit };
cssVars.margin_top_small = { 'callback': _.fusionGetValueWithUnit };
cssVars.margin_bottom_small = { 'callback': _.fusionGetValueWithUnit };
// Minimum height.
if ( 'min' === this.values.hundred_percent_height ) {
cssVars.min_height = { 'callback': this.sanitizeMinHeightArg };
cssVars.min_height_medium = { 'callback': this.sanitizeMinHeightArg };
cssVars.min_height_small = { 'callback': this.sanitizeMinHeightArg };
}
}
boxShadow = _.awbGetBoxShadowCssVar( '--awb-box-shadow', this.values );
if ( boxShadow ) {
boxShadow += 'box-shadow: var(--awb-box-shadow) !important';
}
// background size.
if ( '' !== this.values.background_image && false === this.values.video_bg ) {
if ( 'no-repeat' === this.values.background_repeat ) {
customVars.background_size = 'cover';
}
}
if ( '' !== this.values.background_size ) {
const backgroundSize = 'custom' === this.values.background_size ? this.values.background_custom_size : this.values.background_size;
customVars.background_size = backgroundSize;
}
if ( '' !== this.values.background_size_medium ) {
const backgroundSizeMedium = 'custom' === this.values.background_size_medium ? this.values.background_custom_size_medium : this.values.background_size_medium;
customVars.background_size_medium = backgroundSizeMedium;
}
if ( '' !== this.values.background_size_small ) {
const backgroundSizeSmall = 'custom' === this.values.background_size_small ? this.values.background_custom_size_small : this.values.background_size_small;
customVars.background_size_small = backgroundSizeSmall;
}
return this.getLinkColorStyles( this.values ) + this.getCssVarsForOptions( cssVars ) + this.getCustomCssVars( customVars ) + boxShadow + _.getFilterVars( this.values );
},
getLinkColorStyles: function( values ) {
let styles = '';
if ( '' !== values.link_hover_color ) {
styles += '--link_hover_color: ' + values.link_hover_color + ';';
}
if ( '' !== values.link_color ) {
styles += '--link_color: ' + values.link_color + ';';
}
return styles;
},
getFadingBgVars: function() {
var customVars = {},
cssVars;
// Fading Background.
if ( 'yes' === this.values.fade && '' !== this.values.background_image && false === this.values.video_bg ) {
cssVars = [
'background_color',
'background_position',
'background_position_medium',
'background_position_small',
'background_repeat',
'background_repeat_medium',
'background_repeat_small',
'background_blend_mode',
'background_blend_mode_medium',
'background_blend_mode_small'
];
if ( this.values.background_parallax ) {
cssVars.push( 'background_parallax' );
}
if ( this.values.background_image ) {
customVars.background_image = 'url(' + this.values.background_image + ')';
}
if ( this.values.background_image_medium ) {
customVars.background_image_medium = 'url(' + this.values.background_image_medium + ')';
}
if ( this.values.background_image_small ) {
customVars.background_image_small = 'url(' + this.values.background_image_small + ')';
}
if ( '' !== _.getGradientString( this.values, 'fade' ) ) {
customVars.background_image = _.getGradientString( this.values, 'fade' );
if ( this.values.background_image_medium ) {
customVars.background_image_medium = _.getGradientString( this.values, 'fade', 'medium' );
}
if ( this.values.background_image_small ) {
customVars.background_image_small = _.getGradientString( this.values, 'fade', 'small' );
}
}
if ( 'no-repeat' === this.values.background_repeat ) {
customVars.background_size = 'cover';
}
if ( '' !== this.values.background_size ) {
const backgroundSize = 'custom' === this.values.background_size ? this.values.background_custom_size : this.values.background_size;
customVars.background_size = backgroundSize;
}
if ( '' !== this.values.background_size ) {
const backgroundSizeMedium = 'custom' === this.values.background_size_medium ? this.values.background_custom_size_medium : this.values.background_size_medium;
customVars.background_size_medium = backgroundSizeMedium;
}
if ( '' !== this.values.background_size ) {
const backgroundSizeSmall = 'custom' === this.values.background_size_small ? this.values.background_custom_size_small : this.values.background_size_small;
customVars.background_size_small = backgroundSizeSmall;
}
}
return this.getCssVarsForOptions( cssVars ) + this.getCustomCssVars( customVars );
},
sanitizeMinHeightArg: function( value ) {
if ( '' !== value ) {
if ( -1 !== value.indexOf( '%' ) ) {
value = value.replace( '%', 'vh' );
}
value = _.fusionGetValueWithUnit( value );
}
return value;
},
createVideoBackground: function() {
var videoBackground = '',
overlayStyle = '',
cid = this.model.get( 'cid' ),
videoAttributes,
videoPreviewImageStyle,
videoUrl,
videoSrc,
loop;
// Videos.
if ( 'undefined' !== typeof this.values.video_mp4 && '' !== this.values.video_mp4 ) {
videoSrc += '';
}
if ( 'undefined' !== typeof this.values.video_webm && '' !== this.values.video_webm ) {
videoSrc += '';
}
if ( 'undefined' !== typeof this.values.video_ogv && '' !== this.values.video_ogv ) {
videoSrc += '';
}
if ( '' !== this.values.video_url ) {
videoUrl = _.fusionGetVideoProvider( this.values.video_url ),
loop = ( 'yes' === this.values.video_loop ? 1 : 0 );
if ( 'youtube' === videoUrl.type ) {
videoBackground += '';
} else if ( 'vimeo' === videoUrl.type ) {
videoBackground += '';
}
} else {
videoAttributes = 'preload="auto" autoplay playsinline';
if ( 'yes' === this.values.video_loop ) {
videoAttributes += ' loop';
}
if ( 'yes' === this.values.video_mute ) {
videoAttributes += ' muted';
}
// Video Preview Image.
if ( '' !== this.values.video_preview_image ) {
videoPreviewImageStyle = 'background-image: url(\'' + this.values.video_preview_image + '\');';
videoBackground += '';
}
videoBackground += '';
}
// Video Overlay.
if ( '' !== _.getGradientString( this.values ) ) {
overlayStyle += 'background-image:' + _.getGradientString( this.values ) + ';';
}
if ( '' !== this.values.background_color && 1 > jQuery.AWB_Color( this.values.background_color ).alpha() ) {
overlayStyle += 'background-color:' + this.values.background_color + ';';
}
if ( '' !== overlayStyle ) {
videoBackground += '';
}
return videoBackground;
},
fadingBackgroundAttr: function() {
var attr = {
class: 'fullwidth-faded',
style: this.getFadingBgVars()
};
return attr;
},
/**
* Get template attributes.
*
* @since 2.0.0
* @return {void}
*/
getTemplateAtts: function() {
var templateAttributes = {};
this.setValues();
this.setExtraValues();
this.setContainerVideoData();
// Remove old parallax bg.
if ( this.$el.find( '.fusion-bg-parallax' ).length ) {
if ( 'undefined' !== typeof this.$el.find( '.fusion-bg-parallax' ).data( 'parallax-index' ) ) {
jQuery( '#fb-preview' )[ 0 ].contentWindow._fusionImageParallaxImages.splice( this.$el.find( '.fusion-bg-parallax' ).data( 'parallax-index' ), 1 );
}
this.$el.find( '.fusion-bg-parallax' ).remove();
this.$el.find( '.parallax-inner' ).remove();
}
templateAttributes.values = this.values;
templateAttributes.attr = this.attr();
templateAttributes.parallax = this.parallaxAttr();
templateAttributes.createVideoBackground = _.bind( this.createVideoBackground, this );
templateAttributes.fadingBackground = this.fadingBackgroundAttr();
templateAttributes.admin_label = ( '' !== this.values.admin_label ) ? _.unescape( this.values.admin_label ) : fusionBuilderText.full_width_section;
templateAttributes.topOverlap = ( 20 > parseInt( this.values.padding_top, 10 ) && ( '0%' === this.values.padding_top || -1 === this.values.padding_top.indexOf( '%' ) ) ) ? 'fusion-overlap' : '';
templateAttributes.bottomOverlap = ( 20 > parseInt( this.values.padding_bottom, 10 ) && ( '0%' === this.values.padding_bottom || -1 === this.values.padding_bottom.indexOf( '%' ) ) ) ? 'fusion-overlap' : '';
templateAttributes.isFlex = this.isFlex();
templateAttributes.isGlobal = ( 'undefined' !== typeof this.values.fusion_global ) ? 'yes' : 'no';
templateAttributes.cid = this.model.get( 'cid' );
templateAttributes.status = this.values.status;
templateAttributes.container_tag = this.values.container_tag;
templateAttributes.scrollPosition = ( 'right' === FusionApp.settings.header_position || jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).hasClass( 'rtl' ) ) ? 'scroll-navigation-left' : 'scroll-navigation-right';
templateAttributes.contentStyle = this.contentStyle();
templateAttributes.patternBg = _.fusionGetPatternElement( this.values );
templateAttributes.maskBg = _.fusionGetMaskElement( this.values );
templateAttributes.bgSlider = _.fusionGetBackgroundSliderElement( this );
return templateAttributes;
},
triggerScrollUpdate: function() {
setTimeout( function() {
FusionPageBuilderApp.scrollingContainers();
}, 100 );
},
beforePatch: function() {
if ( this.$el.find( '.fusion-bg-parallax' ).length ) {
if ( 'object' === typeof jQuery( '#fb-preview' )[ 0 ].contentWindow._fusionImageParallaxImages && 'undefined' !== typeof this.$el.find( '.fusion-bg-parallax' ).attr( 'data-parallax-index' ) ) {
jQuery( '#fb-preview' )[ 0 ].contentWindow._fusionImageParallaxImages.splice( this.$el.find( '.fusion-bg-parallax' ).attr( 'data-parallax-index' ), 1 );
}
}
},
/**
* Runs after view DOM is patched.
*
* @since 2.0.0
* @return null
*/
afterPatch: function() {
var self = this;
this.appendChildren();
// Using non debounced version for smoothness.
this.refreshJs();
this._triggerScrollUpdate();
setTimeout( function() {
self.droppableContainer();
}, 100 );
if ( 'yes' === this.model.attributes.params.hundred_percent_height && 'yes' === this.model.attributes.params.hundred_percent_height_scroll ) {
this.$el.addClass( 'scrolling-helper' );
} else {
this.$el.removeClass( 'scrolling-helper' );
}
this.setSettingsControlsOffset( true );
this._reInitSticky();
if ( this.reInitDraggables ) {
this.updateDragHandles();
}
},
/**
* Triggers a refresh.
*
* @since 2.0.0
* @return void
*/
refreshJs: function( cid ) {
cid = 'undefined' === typeof cid ? this.model.attributes.cid : cid;
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).trigger( 'fusion-element-render-fusion_builder_container', cid );
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).trigger( 'fusion-reinit-carousels', cid );
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).trigger( 'fusion-reinit-masonry', cid );
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).trigger( 'fusion-reinit-background-slider', cid );
},
/**
* Adds a container.
*
* @since 2.0.0
* @param {Object} event - The event.
* @return {void}
*/
addContainer: function( event ) {
var elementID,
defaultParams,
params,
value,
newContainer;
if ( event ) {
event.preventDefault();
FusionPageBuilderApp.newContainerAdded = true;
}
elementID = FusionPageBuilderViewManager.generateCid();
defaultParams = fusionAllElements.fusion_builder_container.params;
params = {};
// Process default options for shortcode.
_.each( defaultParams, function( param ) {
value = ( _.isObject( param.value ) ) ? param[ 'default' ] : param.value;
params[ param.param_name ] = value;
if ( 'dimension' === param.type && _.isObject( param.value ) ) {
_.each( param.value, function( val, name ) {
params[ name ] = val;
} );
}
} );
this.collection.add( [
{
type: 'fusion_builder_container',
added: 'manually',
element_type: 'fusion_builder_container',
cid: elementID,
params: params,
view: this,
created: 'auto'
}
] );
// Make sure to add row to new container not current one.
newContainer = FusionPageBuilderViewManager.getView( elementID );
newContainer.addRow();
FusionPageBuilderApp.scrollingContainers();
},
/**
* Adds a row.
*
* @since 2.0.0
* @return {void}
*/
addRow: function() {
this.collection.add( [
{
type: 'fusion_builder_row',
element_type: 'fusion_builder_row',
added: 'manually',
cid: FusionPageBuilderViewManager.generateCid(),
parent: this.model.get( 'cid' ),
view: this,
element_content: ''
}
] );
},
/**
* Removes the container.
*
* @since 2.0.0
* @param {Object} event - The event.
* @param {boolean|undefined} skip - Should we skip this?
* @param {bool} forceManually - Force manually, even if it's not an event, to update history and trigger content changes.
* @return {void}
*/
removeContainer: function( event, skip, forceManually ) {
var rows;
if ( event ) {
event.preventDefault();
}
rows = FusionPageBuilderViewManager.getChildViews( this.model.get( 'cid' ) );
_.each( rows, function( row ) {
if ( 'fusion_builder_row' === row.model.get( 'type' ) ) {
row.removeRow();
}
} );
FusionPageBuilderViewManager.removeView( this.model.get( 'cid' ) );
this.model.destroy();
FusionEvents.trigger( 'fusion-element-removed', this.model.get( 'cid' ) );
this.remove();
// If its the last container add empty page view.
if ( 1 > FusionPageBuilderViewManager.countElementsByType( 'fusion_builder_container' ) && 'undefined' === typeof skip ) {
FusionPageBuilderApp.blankPage = true;
FusionPageBuilderApp.clearBuilderLayout( true );
}
// If the column is deleted manually.
if ( event || forceManually ) {
FusionPageBuilderApp.scrollingContainers();
FusionEvents.trigger( 'fusion-history-save-step', fusionBuilderText.deleted_section );
FusionEvents.trigger( 'fusion-content-changed' );
}
},
/**
* Clones a container.
*
* @since 2.0.0
* @param {Object} event - The event.
* @return {void}
*/
cloneContainer: function( event ) {
var containerAttributes,
$thisContainer;
if ( event ) {
event.preventDefault();
}
containerAttributes = jQuery.extend( true, {}, this.model.attributes );
containerAttributes.cid = FusionPageBuilderViewManager.generateCid();
containerAttributes.created = 'manually';
containerAttributes.view = this;
FusionPageBuilderApp.collection.add( containerAttributes );
$thisContainer = this.$el;
// Parse rows
$thisContainer.find( '.fusion-builder-row-container:not(.fusion_builder_row_inner .fusion-builder-row-container)' ).each( function() {
var thisRow = jQuery( this ),
rowCID = thisRow.data( 'cid' ),
rowView,
// Get model from collection by cid.
row = FusionPageBuilderElements.find( function( model ) {
return model.get( 'cid' ) == rowCID; // jshint ignore: line
} ),
// Clone row.
rowAttributes = jQuery.extend( true, {}, row.attributes );
rowAttributes.created = 'manually';
rowAttributes.cid = FusionPageBuilderViewManager.generateCid();
rowAttributes.parent = containerAttributes.cid;
FusionPageBuilderApp.collection.add( rowAttributes );
// Make sure spacing is calculated.
rowView = FusionPageBuilderViewManager.getView( rowAttributes.cid );
// Parse columns
thisRow.find( '.fusion-builder-column-outer' ).each( function() {
// Parse column elements
var thisColumn = jQuery( this ),
$columnCID = thisColumn.data( 'cid' ),
// Get model from collection by cid
column = FusionPageBuilderElements.find( function( model ) {
return model.get( 'cid' ) == $columnCID; // jshint ignore: line
} ),
// Clone column
columnAttributes = jQuery.extend( true, {}, column.attributes );
columnAttributes.created = 'manually';
columnAttributes.cid = FusionPageBuilderViewManager.generateCid();
columnAttributes.parent = rowAttributes.cid;
columnAttributes.from = 'fusion_builder_container';
columnAttributes.cloned = true;
// Don't need target element, position is defined from order.
delete columnAttributes.targetElementPosition;
FusionPageBuilderApp.collection.add( columnAttributes );
// Find column elements
thisColumn.find( '.fusion-builder-column-content:not( .fusion-nested-column-content )' ).children( '.fusion-builder-live-element, .fusion_builder_row_inner' ).each( function() {
var thisElement,
elementCID,
element,
elementAttributes,
thisInnerRow,
InnerRowCID,
innerRowView;
// Regular element
if ( jQuery( this ).hasClass( 'fusion-builder-live-element' ) ) {
thisElement = jQuery( this );
elementCID = thisElement.data( 'cid' );
// Get model from collection by cid
element = FusionPageBuilderElements.find( function( model ) {
return model.get( 'cid' ) == elementCID; // jshint ignore: line
} );
// Clone model attritubes
elementAttributes = jQuery.extend( true, {}, element.attributes );
elementAttributes.created = 'manually';
elementAttributes.cid = FusionPageBuilderViewManager.generateCid();
elementAttributes.parent = columnAttributes.cid;
elementAttributes.from = 'fusion_builder_container';
// Don't need target element, position is defined from order.
delete elementAttributes.targetElementPosition;
FusionPageBuilderApp.collection.add( elementAttributes );
// Inner row element
} else if ( jQuery( this ).hasClass( 'fusion_builder_row_inner' ) ) {
thisInnerRow = jQuery( this );
InnerRowCID = thisInnerRow.data( 'cid' );
innerRowView = FusionPageBuilderViewManager.getView( InnerRowCID );
// Clone inner row
if ( 'undefined' !== typeof innerRowView ) {
innerRowView.cloneNestedRow( '', columnAttributes.cid );
}
}
} );
} );
// Update spacing for columns.
rowView.setRowData();
} );
FusionPageBuilderApp.scrollingContainers();
FusionEvents.trigger( 'fusion-history-save-step', fusionBuilderText.cloned_section );
FusionEvents.trigger( 'fusion-content-changed' );
this._refreshJs( containerAttributes.cid );
},
/**
* Adds a child view.
*
* @param {Object} element - The element model.
* @return {void}
*/
addChildView: function( element ) {
var view,
viewSettings = {
model: element,
collection: FusionPageBuilderElements
};
view = new FusionPageBuilder.RowView( viewSettings );
FusionPageBuilderViewManager.addView( element.get( 'cid' ), view );
if ( this.$el.find( '.fusion-builder-container-content' ).length ) {
this.$el.find( '.fusion-builder-container-content' ).append( view.render().el );
} else {
this.$el.find( '> .fusion-builder-add-element' ).hide().end().append( view.render().el );
}
// Add parent view to inner rows that have been converted from shortcodes
if ( 'manually' === element.get( 'created' ) && 'row_inner' === element.get( 'element_type' ) ) {
element.set( 'view', FusionPageBuilderViewManager.getView( element.get( 'parent' ) ), { silent: true } );
}
},
/**
* Appends model children.
*
* @since 2.0.0
* @return {void}
*/
appendChildren: function() {
var self = this,
cid,
view;
this.model.children.each( function( child ) {
cid = child.attributes.cid;
view = FusionPageBuilderViewManager.getView( cid );
self.$el.find( '.fusion-builder-container-content' ).append( view.$el );
view.delegateEvents();
view.delegateChildEvents();
view.droppableColumn();
} );
},
/**
* Triggers event to reinit sticky container properties.
*
* @since 3.0
* @return {void}
*/
reInitSticky: function() {
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).trigger( 'fusion-reinit-sticky', this.model.attributes.cid );
},
/**
* Set empty spacing for legacy and re-render.
*
* @since 3.0.0
* @return {void}
*/
setEmptySpacing: function() {
var params = this.model.get( 'params' );
params.flex_column_spacing = '0px';
this.model.set( 'params', params );
},
/**
* Things to do, places to go when options change.
*
* @since 2.0.0
* @param {string} paramName - The name of the parameter that changed.
* @param {mixed} paramValue - The value of the option that changed.
* @param {Object} event - The event triggering the option change.
* @return {void}
*/
onOptionChange: function( paramName, paramValue, event ) {
var reInitDraggables = false,
dimensionType = _.find( [ 'spacing_', 'margin_', 'padding_' ], function( type ) {
return paramName.includes( type );
} );
// Reverted to history step or user entered value manually.
if ( 'undefined' === typeof event || ( 'undefined' !== typeof event && ( 'change' !== event.type || ( 'change' === event.type && 'undefined' !== typeof event.srcElement ) ) ) ) {
reInitDraggables = true;
}
if ( dimensionType ) {
this.model.attributes.params[ paramName ] = paramValue;
if ( true === reInitDraggables ) {
if ( 'padding_' === dimensionType ) {
this.destroyPaddingResizable();
this.paddingDrag();
} else {
this.destroyMarginResizable();
this.marginDrag();
}
}
}
switch ( paramName ) {
case 'admin_label':
this.model.attributes.params[ paramName ] = paramValue.replace( /[[\]]+/g, '' );
break;
// Changing between legacy and flex.
case 'type':
this.model.attributes.params[ paramName ] = paramValue;
this.values.type = paramValue;
this.reRenderRows();
this.updateResponsiveSetup();
break;
// Sticky options.
case 'sticky':
case 'sticky_devices':
case 'sticky_height':
case 'sticky_offset':
case 'sticky_transition_offset':
case 'scroll_offset':
this._reInitSticky();
break;
// Changing options which alter row if in flex mode.
case 'flex_column_spacing':
this._updateInnerStyles();
break;
case 'absolute':
if ( 'on' === paramValue && ! this.$el.hasClass( 'fusion-builder-absolute-container-wrapper' ) ) {
this.$el.addClass( 'fusion-builder-absolute-container-wrapper' );
} else if ( 'off' === paramValue && this.$el.hasClass( 'fusion-builder-absolute-container-wrapper' ) ) {
this.$el.removeClass( 'fusion-builder-absolute-container-wrapper' );
}
break;
case 'render_logics':
this.reRender();
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).trigger( 'fusion-column-resized', this.model.attributes.cid );
FusionEvents.trigger( 'fusion-column-resized' );
break;
}
},
/**
* Re-renders the rows.
*
* @since 3.0
* @return {void}
*/
reRenderRows: function() {
var rows = FusionPageBuilderViewManager.getChildViews( this.model.get( 'cid' ) );
// TODO: check this for performance. Ideally we just update params, not re-render row.
_.each( rows, function( row ) {
row.modeChange();
} );
},
/**
* Updates the styles inside container.
*
* @since 3.0
* @return {void}
*/
updateInnerStyles: function() {
var rows = FusionPageBuilderViewManager.getChildViews( this.model.get( 'cid' ) );
_.each( rows, function( row ) {
row.updateInnerStyles();
} );
},
/**
* Updates responsive setup.
*
* @since 3.0
* @return {void}
*/
updateResponsiveSetup: function() {
var $settings = jQuery( '.fusion_builder_module_settings' );
this.isFlex() ? $settings.addClass( 'has-flex' ) : $settings.removeClass( 'has-flex' );
},
/**
* Gets the contents of the container.
*
* @since 2.0.0
* @return {string}
*/
getContent: function() {
var shortcode = '';
shortcode += FusionPageBuilderApp.generateElementShortcode( this.$el, true );
this.$el.find( '.fusion_builder_row' ).each( function() {
var $thisRow = jQuery( this );
shortcode += '[fusion_builder_row]';
$thisRow.find( '.fusion-builder-column-outer' ).each( function() {
var $thisColumn = jQuery( this ),
columnCID = $thisColumn.data( 'cid' ),
columnView = FusionPageBuilderViewManager.getView( columnCID );
shortcode += columnView.getColumnContent();
} );
shortcode += '[/fusion_builder_row]';
} );
shortcode += '[/fusion_builder_container]';
return shortcode;
},
/**
* Get the save label.
*
* @since 2.0.0
* @return {string}
*/
getSaveLabel: function() {
return fusionBuilderText.save_section;
},
/**
* Returns the 'sections' string.
*
* @since 2.0.0
* @return {string}
*/
getCategory: function() {
return 'sections';
},
/**
* Handle margin adjustments on drag.
*
* @since 2.0.0
* @return {void}
*/
marginDrag: function() {
var $el = this.$el,
self = this,
directions = { top: 's', bottom: 's' },
parentWidth = $el.closest( '.fusion-row, .fusion-builder-live-editor' ).width();
if ( this.$el.hasClass( 'active' ) ) {
return;
}
_.each( directions, function( handle, direction ) {
var optionKey = FusionApp.getResponsiveOptionKey( 'margin_' + direction, self.isFlex() ),
actualDimension = self.values[ optionKey ] || self.values[ 'margin_' + direction ] || 0,
percentSpacing = false;
percentSpacing = actualDimension && actualDimension.includes( '%' );
if ( percentSpacing ) {
// Get actual dimension and set.
actualDimension = ( parentWidth / 100 ) * parseFloat( actualDimension );
$el.find( '.fusion-container-margin-' + direction ).css( 'height', actualDimension );
if ( 'bottom' === direction && 20 > actualDimension ) {
$el.find( '.fusion-container-margin-bottom, .fusion-container-padding-bottom' ).addClass( 'fusion-overlap' );
}
}
$el.find( '.fusion-container-margin-' + direction ).css( 'display', 'block' );
$el.find( '.fusion-container-margin-' + direction ).height( actualDimension );
$el.find( '.fusion-container-margin-' + direction ).resizable( {
handles: handle,
minHeight: 0,
minWidth: 0,
grid: ( percentSpacing ) ? [ parentWidth / 100, 10 ] : '',
create: function() {
if ( 'bottom' === direction ) {
if ( 20 > parseInt( actualDimension, 10 ) && ! percentSpacing ) {
$el.find( '.fusion-container-margin-bottom, .fusion-container-padding-bottom' ).addClass( 'fusion-overlap' );
} else {
$el.find( '.fusion-container-margin-bottom, .fusion-container-padding-bottom' ).removeClass( 'fusion-overlap' );
}
}
},
resize: function( event, ui ) {
var optionKey = FusionApp.getResponsiveOptionKey( 'margin_' + direction, self.isFlex() ),
actualDimension = self.values[ optionKey ] || 0,
percentSpacing = false,
value = 'top' === direction || 'bottom' === direction ? ui.size.height : ui.size.width;
jQuery( ui.element ).addClass( 'active' );
// Recheck in case unit is changed in the modal.
percentSpacing = actualDimension && actualDimension.includes( '%' );
jQuery( ui.element ).closest( '.fusion-builder-container' ).addClass( 'active' );
value = 0 > value ? 0 : value;
value = value + 'px';
if ( percentSpacing ) {
value = 0 === parseFloat( value ) ? '0%' : Math.round( parseFloat( parseFloat( value ) / ( parentWidth / 100 ) ) ) + '%';
}
// Bottom margin overlap
if ( 'bottom' === direction ) {
if ( 20 > ui.size.height ) {
jQuery( ui.element ).addClass( 'fusion-overlap' );
$el.find( '.fusion-container-padding-bottom' ).addClass( 'fusion-overlap' );
} else {
jQuery( ui.element ).removeClass( 'fusion-overlap' );
$el.find( '.fusion-container-padding-bottom' ).removeClass( 'fusion-overlap' );
}
}
// Legacy update.
if ( ! self.isFlex() ) {
$el.find( '.fusion-fullwidth' ).css( 'margin-' + direction, value );
}
jQuery( ui.element ).find( '.fusion-spacing-tooltip, .fusion-column-spacing' ).addClass( 'active' );
jQuery( ui.element ).find( '.fusion-spacing-tooltip' ).text( value );
// Update open modal.
self.updateDragSettings( '#' + optionKey, value );
},
stop: function( event, ui ) {
jQuery( ui.element ).removeClass( 'active' );
jQuery( ui.element ).closest( '.fusion-builder-container' ).removeClass( 'active' );
// Delete all spacing resizable within because parent width has changed.
if ( jQuery( ui.element ).closest( '.fusion-builder-container' ).find( '.fusion-column-spacing .ui-resizable' ).length ) {
jQuery( ui.element ).closest( '.fusion-builder-container' ).find( '.fusion-column-spacing .ui-resizable' ).resizable( 'destroy' );
}
}
} );
} );
},
/**
* Checks if the container needs to run through legacy conversion.
*
* @since 3.0.0
* @return {boolean}
*/
needsLegacyConversion: function() {
var params = this.model.get( 'params' );
return 'undefined' === typeof params.type;
},
/**
* Handle padding adjustments on drag.
*
* @since 2.0.0
* @return {void}
*/
paddingDrag: function() {
var $el = this.$el,
self = this,
directions = { top: 's', right: 'w', bottom: 's', left: 'e' },
parentWidth = $el.closest( '.fusion-row, .fusion-builder-live-editor' ).width(),
defaults;
if ( this.$el.hasClass( 'active' ) ) {
return;
}
defaults = this.defaults;
_.each( directions, function( handle, direction ) {
var actualDimension,
previewSize = FusionApp.getPreviewWindowSize(),
percentSpacing = false;
if ( 'small' === previewSize ) {
actualDimension = self.values[ 'padding_' + direction + '_small' ];
}
if ( ! actualDimension && [ 'small', 'medium' ].includes( previewSize ) ) {
actualDimension = self.values[ 'padding_' + direction + '_medium' ];
}
if ( ! actualDimension ) {
actualDimension = self.values[ 'padding_' + direction ];
}
actualDimension = actualDimension || defaults[ 'padding_' + direction ] || 0;
// Check if using a percentage.
percentSpacing = actualDimension && actualDimension.includes( '%' );
if ( percentSpacing ) {
// Get actual dimension and set.
actualDimension = ( parentWidth / 100 ) * parseFloat( actualDimension );
if ( 'top' === direction || 'bottom' === direction ) {
$el.find( '.fusion-container-padding-' + direction ).css( 'height', actualDimension );
} else {
$el.find( '.fusion-container-padding-' + direction ).css( 'width', actualDimension );
}
if ( 'top' === direction && 20 > actualDimension ) {
$el.find( '.fusion-container-margin-top, .fusion-container-padding-top' ).addClass( 'fusion-overlap' );
}
}
$el.find( '.fusion-container-padding-' + direction ).css( 'display', 'block' );
if ( 'top' === direction || 'bottom' === direction ) {
$el.find( '.fusion-container-padding-' + direction ).height( actualDimension );
} else {
$el.find( '.fusion-container-padding-' + direction ).width( actualDimension );
}
$el.find( '.fusion-container-padding-' + direction ).resizable( {
handles: handle,
minHeight: 0,
minWidth: 0,
create: function() {
if ( 'top' === direction ) {
if ( 20 > parseInt( actualDimension, 10 ) && ! percentSpacing ) {
$el.find( '.fusion-container-margin-top, .fusion-container-padding-top' ).addClass( 'fusion-overlap' );
} else {
$el.find( '.fusion-container-margin-top, .fusion-container-padding-top' ).removeClass( 'fusion-overlap' );
}
}
},
resize: function( event, ui ) {
var optionKey = FusionApp.getResponsiveOptionKey( 'padding_' + direction, self.isFlex() ),
actualDimension = self.values[ optionKey ],
percentSpacing = false,
value = 'top' === direction || 'bottom' === direction ? ui.size.height : ui.size.width;
percentSpacing = actualDimension && actualDimension.includes( '%' );
jQuery( ui.element ).addClass( 'active' );
jQuery( ui.element ).closest( '.fusion-builder-container' ).addClass( 'active' );
value = 0 > value ? 0 : value;
value = value + 'px';
if ( percentSpacing ) {
value = 0 === parseFloat( value ) ? '0%' : Math.round( parseFloat( parseFloat( value ) / ( parentWidth / 100 ) ) ) + '%';
}
// Top padding overlap
if ( 'top' === direction ) {
if ( 20 > ui.size.height ) {
jQuery( ui.element ).addClass( 'fusion-overlap' );
$el.find( '.fusion-container-margin-top' ).addClass( 'fusion-overlap' );
} else {
jQuery( ui.element ).removeClass( 'fusion-overlap' );
$el.find( '.fusion-container-margin-top' ).removeClass( 'fusion-overlap' );
}
}
// Set values and width.
$el.children( '.fusion-fullwidth' ).css( '--awb-' + optionKey.replaceAll( '_', '-' ), value );
jQuery( ui.element ).find( '.fusion-spacing-tooltip, .fusion-column-spacing' ).addClass( 'active' );
jQuery( ui.element ).find( '.fusion-spacing-tooltip' ).text( value );
// Update open modal.
self.updateDragSettings( '#' + optionKey, value );
},
stop: function( event, ui ) {
jQuery( ui.element ).removeClass( 'active' );
jQuery( ui.element ).closest( '.fusion-builder-container' ).removeClass( 'active' );
// Delete all spacing resizable within because parent width has changed.
if ( jQuery( ui.element ).closest( '.fusion-builder-container' ).find( '.fusion-column-spacing .ui-resizable' ).length ) {
jQuery( ui.element ).closest( '.fusion-builder-container' ).find( '.fusion-column-spacing .ui-resizable' ).resizable( 'destroy' );
}
}
} );
} );
},
/**
* Destroy container resizable.
*
* @since 2.0.0
* @return {void}
*/
destroyResizable: function() {
this.destroyMarginResizable();
this.destroyPaddingResizable();
},
/**
* Destroy container margin resizable.
*
* @since 2.0.0
* @return {void}
*/
destroyMarginResizable: function() {
var $containerSpacer = this.$el.find( '.fusion-container-margin-top, .fusion-container-margin-bottom' );
jQuery.each( $containerSpacer, function( index, spacer ) {
if ( jQuery( spacer ).hasClass( 'ui-resizable' ) ) {
jQuery( spacer ).resizable( 'destroy' );
jQuery( spacer ).hide();
}
} );
},
/**
* Destroy container padding resizable.
*
* @since 2.0.0
* @return {void}
*/
destroyPaddingResizable: function() {
var $containerSpacer = this.$el.find( '.fusion-container-padding-top, .fusion-container-padding-right, .fusion-container-padding-bottom, .fusion-container-padding-left' );
jQuery.each( $containerSpacer, function( index, spacer ) {
if ( jQuery( spacer ).hasClass( 'ui-resizable' ) ) {
jQuery( spacer ).resizable( 'destroy' );
jQuery( spacer ).hide();
}
} );
},
/**
* Filter out DOM before patching.
*
* @since 2.0.0
* @return {void}
*/
patcherFilter: function( diff ) {
var filteredDiff = [],
self = this;
self.reInitDraggables = false;
_.each( diff, function( info ) {
if ( 'removeElement' === info.action ) {
if ( 'undefined' !== typeof info.element.attributes && 'undefined' !== typeof info.element.attributes[ 'class' ] && -1 !== info.element.attributes[ 'class' ].indexOf( 'fusion-fullwidth' ) ) {
self.reInitDraggables = true;
filteredDiff.push( info );
} else if ( 'undefined' !== typeof info.element.attributes && 'undefined' !== typeof info.element.attributes[ 'class' ] && -1 !== info.element.attributes[ 'class' ].indexOf( 'fusion-container-spacing' ) ) {
// Ignore.
} else {
filteredDiff.push( info );
}
} else if ( 'addElement' === info.action ) {
if ( 'undefined' !== typeof info.element.attributes && 'undefined' !== typeof info.element.attributes[ 'class' ] && -1 !== info.element.attributes[ 'class' ].indexOf( 'fusion-container-spacing' ) ) {
// Ignore.
} else {
filteredDiff.push( info );
}
} else {
filteredDiff.push( info );
}
} );
return filteredDiff;
},
publish: function( event ) {
var cid = jQuery( event.currentTarget ).data( 'cid' ),
view = FusionPageBuilderViewManager.getView( cid ),
params = view.model.get( 'params' );
FusionApp.confirmationPopup( {
title: fusionBuilderText.container_publish,
content: fusionBuilderText.are_you_sure_you_want_to_publish,
actions: [
{
label: fusionBuilderText.no,
classes: 'no',
callback: function() {
FusionApp.confirmationPopup( {
action: 'hide'
} );
}
},
{
label: fusionBuilderText.yes,
classes: 'yes',
callback: function() {
params.status = 'published';
view.model.set( 'params', params );
view.$el.find( 'a[data-cid="' + cid + '"].fusion-builder-publish-tooltip' ).remove();
FusionEvents.trigger( 'fusion-history-turn-on-tracking' );
FusionEvents.trigger( 'fusion-history-save-step', fusionBuilderText.container_published );
FusionEvents.trigger( 'fusion-content-changed' );
FusionApp.confirmationPopup( {
action: 'hide'
} );
}
}
]
} );
},
unglobalize: function( event ) {
var cid = jQuery( event.currentTarget ).data( 'cid' ),
view = FusionPageBuilderViewManager.getView( cid ),
params = view.model.get( 'params' );
event.preventDefault();
FusionApp.confirmationPopup( {
title: fusionBuilderText.remove_global,
content: fusionBuilderText.are_you_sure_you_want_to_remove_global,
actions: [
{
label: fusionBuilderText.no,
classes: 'no',
callback: function() {
FusionApp.confirmationPopup( {
action: 'hide'
} );
}
},
{
label: fusionBuilderText.yes,
classes: 'yes',
callback: function() {
// Remove global attributes.
delete params.fusion_global;
view.model.set( 'params', params );
view.$el.removeClass( 'fusion-global-container fusion-global-column fusion-global-nested-row fusion-global-element fusion-global-parent-element' );
view.$el.find( 'a[data-cid="' + cid + '"].fusion-builder-unglobal-tooltip' ).remove();
view.$el.removeAttr( 'fusion-global-layout' );
FusionEvents.trigger( 'fusion-history-turn-on-tracking' );
FusionEvents.trigger( 'fusion-history-save-step', fusionBuilderText.removed_global );
FusionEvents.trigger( 'fusion-content-changed' );
FusionApp.confirmationPopup( {
action: 'hide'
} );
}
}
]
} );
},
/**
* Fires when preview are is resized.
*
* @since 3.0
* @return {void}
*/
onPreviewResize: function() {
if ( ! this.isFlex() ) {
return;
}
if ( this.$el.hasClass( 'fusion-builder-element-edited' ) ) {
this.updateDragHandles();
}
},
/**
* Updates column sizes controls.
*
* @since 3.0
* @return {void}
*/
updateDragHandles: function() {
this.destroyResizable();
this.marginDrag();
this.paddingDrag();
},
/**
* Runs just after render on cancel.
*
* @since 3.5
* @return null
*/
beforeGenerateShortcode: function() {
var elementType = this.model.get( 'element_type' ),
options = fusionAllElements[ elementType ].params,
values = jQuery.extend( true, {}, fusionAllElements[ elementType ].defaults, _.fusionCleanParameters( this.model.get( 'params' ) ) );
if ( 'object' !== typeof options ) {
return;
}
// If images needs replaced lets check element to see if we have media being used to add to object.
if ( 'undefined' !== typeof FusionApp.data.replaceAssets && FusionApp.data.replaceAssets && ( 'undefined' !== typeof FusionApp.data.fusion_element_type || 'fusion_template' === FusionApp.getPost( 'post_type' ) ) ) {
this.mapStudioImages( options, values );
if ( '' !== values.video_mp4 ) {
// If its not within object already, add it.
if ( 'undefined' === typeof FusionPageBuilderApp.mediaMap.videos[ values.video_mp4 ] ) {
FusionPageBuilderApp.mediaMap.videos[ values.video_mp4 ] = true;
}
}
}
},
/**
* check if String is JSON string.
*
* @since 3.7
* @return boolean
*/
IsJsonString: function( str ) {
try {
const json = JSON.parse( str );
return ( 'object' === typeof json );
} catch ( e ) {
return false;
}
},
/**
* Get render logics devices.
*
* @since 3.7
* @return boolean
*/
getRenderLogicsDevices: function( value ) {
value = value || this.values.render_logics;
let renderLogics = value && this.IsJsonString( atob( value ) ) ? JSON.parse( atob( value ) ) : [];
// Get device Render logics only.
renderLogics = renderLogics.filter( ( r ) => 'device_type' === r.field );
return renderLogics;
}
} );
} );
}( jQuery ) );
;/* global FusionEvents */
var FusionPageBuilder = FusionPageBuilder || {};
( function() {
jQuery( document ).ready( function() {
// Studio import modal view.
FusionPageBuilder.StudioImportModalView = window.wp.Backbone.View.extend( {
template: FusionPageBuilder.template( jQuery( '#fusion-builder-studio-import-modal' ).html() ),
className: 'fusion-builder-studio-import-modal',
events: {
'click .awb-admin-modal-corner-close': 'closeModal'
},
/**
* Renders the view.
*
* @since 3.5.0
* @return {Object} this
*/
render: function() {
this.$el.html( this.template() );
return this;
},
/**
* Updates modal status.
*
* @since 3.5.0
* @param {String} status - New status text.
* @return {void}
*/
updateStatus: function( status ) {
this.$el.find( '.awb-admin-modal-status-bar .awb-admin-modal-status-bar-label' ).html( status );
},
/**
* Updates modal progress.
*
* @since 3.5.0
* @param {Object} avadaMedia - Avada Media object, all things we need to import.
* @param {String} currentImportKey - Object key which is currently being imported.
* @return {void}
*/
updateProgressBar: function( avadaMedia, currentImportKey ) {
var mediaKeys = Object.keys( avadaMedia ),
progress = ( mediaKeys.indexOf( currentImportKey ) + 1 ) / mediaKeys.length;
this.$el.find( '.awb-admin-modal-status-bar .awb-admin-modal-status-bar-progress-bar' ).css( 'width', ( 100 * progress ) + '%' );
},
/**
* Remove the view.
*
* @since 3.5.0
* @param {Object} event - The event triggering the element removal.
* @return {void}
*/
closeModal: function( event ) {
if ( event ) {
event.preventDefault();
}
FusionEvents.trigger( 'awb-studio-import-modal-closed' );
this.remove();
}
} );
} );
}( jQuery ) );
;/* global FusionPageBuilderApp, FusionPageBuilderViewManager, fusionBuilderText, fusionAllElements, FusionEvents */
var FusionPageBuilder = FusionPageBuilder || {};
( function() {
jQuery( document ).ready( function() {
let isClipboardEnabled;
if ( 'clipboard' in navigator ) {
navigator.clipboard.readText().then( ( clipboardContent ) => {
isClipboardEnabled = true;
} ).catch( error => {
isClipboardEnabled = false;
console.log( error );
} )
} else {
isClipboardEnabled = false;
}
// Builder Container View
FusionPageBuilder.ContextMenuView = window.wp.Backbone.View.extend( {
template: FusionPageBuilder.template( jQuery( '#fusion-builder-context-menu' ).html() ),
className: 'fusion-builder-context-menu',
events: {
'click [data-action="edit"]': 'editTrigger',
'click [data-action="save"]': 'saveTrigger',
'click [data-action="clone"]': 'cloneTrigger',
'click [data-action="remove"]': 'removeTrigger',
'click [data-action="copy"]': 'copy',
'click [data-action="paste-before"]': 'pasteBefore',
'click [data-action="paste-after"]': 'pasteAfter',
'click [data-action="paste-start"]': 'pasteStart',
'click [data-action="paste-end"]': 'pasteEnd',
'click [data-action="invert"]': 'invertTrigger'
},
/**
* Initialize the builder sidebar.
*
* @since 2.0.0
* @return {void}
*/
initialize: function() {
this.copyData = {
data: {
type: false,
content: false
}
};
this.getCopy();
this.elWidth = 130;
this.elHeight = 257;
},
/**
* Renders the view.
*
* @since 2.0.0
* @return {Object} this
*/
render: function() {
if ( isClipboardEnabled ) {
const self = this;
navigator.clipboard.readText().then( ( clipboardContent ) => {
if ( 'string' === typeof clipboardContent && '' !== clipboardContent ) {
const data = JSON.parse( clipboardContent )
if ( 'object' === typeof data && 'undefined' !== typeof data.type && 'undefined' !== typeof data.content ) {
self.copyData.data.type = data.type
self.copyData.data.content = data.content
}
}
self.doRender()
} ).catch( error => {
console.error( 'Error storing content from clipboard: ' + error )
self.doRender()
} )
} else {
this.doRender();
}
return this;
},
/**
* Do the rendering of the view.
*
* @since 3.11.10
* @return {void}
*/
doRender: function() {
var leftOffset = this.model.event.pageX,
topOffset = this.model.event.pageY;
this.$el.html( this.template( jQuery.extend( true, this.copyData, this.model.parent.attributes ) ) );
if ( this.model.event.pageX + this.elWidth > jQuery( '#fb-preview' ).width() ) {
leftOffset = jQuery( '#fb-preview' ).width() - this.elWidth;
}
if ( this.model.event.pageY + this.elHeight > jQuery( jQuery( '#fb-preview' )[ 0 ].contentWindow.document ).height() ) {
topOffset = jQuery( jQuery( '#fb-preview' )[ 0 ].contentWindow.document ).height() - this.elHeight;
}
this.$el.css( { top: ( topOffset ) + 'px', left: ( leftOffset ) + 'px' } );
},
/**
* Trigger edit on relevant element.
*
* @since 2.0.0
*/
editTrigger: function( event ) {
if ( 'fusion_builder_row_inner' === this.model.parent.attributes.element_type ) {
this.model.parentView.editRow( event );
} else {
this.model.parentView.settings( event );
}
},
/**
* Trigger save on relavent element.
*
* @since 2.0.0
*/
saveTrigger: function( event ) {
this.model.parentView.openLibrary( event );
},
/**
* Trigger clone on relavent element.
*
* @since 2.0.0
*/
cloneTrigger: function( event ) {
switch ( this.model.parent.attributes.element_type ) {
case 'fusion_builder_container':
this.model.parentView.cloneContainer( event );
break;
case 'fusion_builder_column_inner':
case 'fusion_builder_column':
this.model.parentView.cloneColumn( event );
break;
case 'fusion_builder_row_inner':
this.model.parentView.cloneNestedRow( event );
break;
case 'fusion_builder_form_step':
this.model.parentView.cloneSpecialElement( event );
break;
default:
this.model.parentView.cloneElement( event );
break;
}
},
/**
* Trigger remove on relavent element.
*
* @since 2.0.0
*/
removeTrigger: function( event ) {
switch ( this.model.parent.attributes.element_type ) {
case 'fusion_builder_form_step':
case 'fusion_builder_container':
this.model.parentView.removeContainer( event );
break;
case 'fusion_builder_column_inner':
case 'fusion_builder_column':
this.model.parentView.removeColumn( event );
break;
case 'fusion_builder_row_inner':
this.model.parentView.removeRow( event );
break;
default:
this.model.parentView.removeElement( event );
break;
}
},
/**
* Copy the element.
*
* @since 2.0.0
*/
copy: function() {
var type = this.model.parent.attributes.element_type,
content = this.model.parentView.getContent(),
$temp = jQuery( '