1630 lines
51 KiB
JavaScript
1630 lines
51 KiB
JavaScript
/* 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( '<span class="fusion-builder-loader"></span>' );
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 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( '<div class="fusion-element-helper ' + $classes + '" data-cid="' + cid + '"><span class="' + fusionAllElements[ self.model.get( 'element_type' ) ].icon + '"></span></div>' );
|
|
},
|
|
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 ) );
|