550 lines
15 KiB
JavaScript
550 lines
15 KiB
JavaScript
/* global CodeMirror, fusionAppConfig, fusionAllElements, fusionBuilderConfig */
|
|
/* eslint no-shadow: 0 */
|
|
/* eslint no-empty: 0 */
|
|
var FusionPageBuilder = FusionPageBuilder || {};
|
|
|
|
( function( $ ) {
|
|
var widgets, widget, widgetData, widgetDataPromise, widgetDataLoading, widgetDataLoaded, fusionConfig;
|
|
|
|
widgets = [];
|
|
|
|
/**
|
|
* Gets all widget HTML forms
|
|
* @param {Function} callback
|
|
*/
|
|
function getWidgetForms( callback ) {
|
|
if ( widgetDataLoaded ) {
|
|
return callback();
|
|
}
|
|
if ( widgetDataLoading ) {
|
|
widgetDataPromise.success( callback );
|
|
} else {
|
|
widgetDataLoading = true;
|
|
widgetDataPromise = jQuery.ajax( {
|
|
url: fusionConfig.ajaxurl,
|
|
type: 'post',
|
|
dataType: 'json',
|
|
data: {
|
|
action: 'fusion_get_widget_form'
|
|
}
|
|
} ).done( function( response ) {
|
|
widgetDataLoaded = true;
|
|
widgetDataLoading = false;
|
|
widgetData = response.data;
|
|
|
|
// Fix for the hashed widget php class names
|
|
_.each( widgetData, function( value, key ) {
|
|
|
|
if ( 'undefined' !== typeof fusionAllElements.fusion_widget && 'undefined' === typeof fusionAllElements.fusion_widget.params.type.value[ key ] ) {
|
|
|
|
// Try to find a corresponding class name by widget name
|
|
jQuery.map( fusionAllElements.fusion_widget.params.type.value, function( val, i ) {
|
|
if ( val === value.name ) {
|
|
|
|
// Add the new class name key
|
|
value.title = i;
|
|
widgetData[ i ] = value;
|
|
|
|
// Delete the old class name key
|
|
widgetData[ key ][ 'delete' ];
|
|
}
|
|
} );
|
|
}
|
|
} );
|
|
|
|
return callback && callback();
|
|
} );
|
|
}
|
|
}
|
|
|
|
$( document ).ready( function() {
|
|
// Get correct fusion config in both front/backend
|
|
fusionConfig = ( 'undefined' !== typeof FusionApp ) ? fusionAppConfig : fusionBuilderConfig;
|
|
|
|
// Check if widget_element is enabled and get corresponding form html
|
|
if ( fusionConfig.widget_element_enabled ) {
|
|
getWidgetForms();
|
|
}
|
|
|
|
FusionPageBuilder.BaseWidgetSettingsView = FusionPageBuilder.ElementSettingsView.extend( {
|
|
|
|
/**
|
|
* Invalid widgets list
|
|
* Different from blacklist, because invalid widgets will force form append rather than use compatibility mode
|
|
*
|
|
* @since 2.0.0
|
|
*/
|
|
invalidWidgets: [ 'Fusion_Widget_Social_Links' ],
|
|
|
|
/**
|
|
* Creates a formatted widget form field name.
|
|
*
|
|
* @since 2.0.0
|
|
* @param {String} className
|
|
* @param {String} name
|
|
*/
|
|
createWidgetFieldName: function ( className, name ) {
|
|
var prefix = className.toLowerCase().replace( /\\/g, '_' ) + '__';
|
|
|
|
name = name.toLowerCase();
|
|
|
|
try {
|
|
prefix += name.match( /\[(.*?)\]/g ).slice( -1 )[ 0 ].replace( /\[|(\])/g, '' );
|
|
} catch ( e ) {}
|
|
|
|
return prefix;
|
|
},
|
|
|
|
/**
|
|
* Parses a widget and registers it to `widgets` variable.
|
|
*
|
|
* @since 2.0.0
|
|
* @param {Object} widget
|
|
* @param {String} className
|
|
*/
|
|
registerWidget: function( widget, className ) {
|
|
var $form,
|
|
selectors,
|
|
fields,
|
|
getElementAttributes,
|
|
incorrectFields,
|
|
self;
|
|
|
|
self = this;
|
|
fields = {};
|
|
// Make a form and insert widget form contents for easy manipulation
|
|
$form = $( '<form></form>' ).html( widget.form );
|
|
// HTML selectors we want to retrieve from `$form`
|
|
selectors = [
|
|
'fieldset',
|
|
'input',
|
|
'select',
|
|
'textarea'
|
|
].join( ',' );
|
|
|
|
getElementAttributes = function ( element, keys ) {
|
|
var result = {};
|
|
_.each( keys, function( key ) {
|
|
result[ key ] = element[ key ];
|
|
} );
|
|
return result;
|
|
};
|
|
|
|
// Start form parsing
|
|
$form.find( selectors ).not( '[type="button"]' ).each( function() {
|
|
var field, name;
|
|
|
|
// The form field attributes
|
|
field = getElementAttributes(
|
|
this,
|
|
[ 'id', 'className', 'name', 'tagName', 'type', 'value', 'placeholder', 'options', 'checked' ]
|
|
);
|
|
// The form field name
|
|
name = self.createWidgetFieldName( className, field.name );
|
|
|
|
// Map options for select elements
|
|
field.options = _.map( field.options, function( option ) {
|
|
return getElementAttributes( option, [ 'value', 'text', 'selected' ] );
|
|
} );
|
|
|
|
// Match field attributes to fusion form fields by tagName
|
|
switch ( field.tagName ) {
|
|
case 'INPUT': {
|
|
if ( [ 'text', 'number' ].includes( field.type ) ) {
|
|
field.type = 'textfield';
|
|
} else if ( 'checkbox' === field.type ) {
|
|
field.type = 'radio_button_set';
|
|
field.value = {
|
|
'on': 'On',
|
|
'off': 'Off'
|
|
};
|
|
// eslint-disable-next-line dot-notation
|
|
field.default = field.checked ? 'on' : 'off';
|
|
}
|
|
break;
|
|
}
|
|
case 'SELECT': {
|
|
field.type = 'select';
|
|
field.value = _.reduce( field.options, function( options, option ) {
|
|
if ( option.selected ) {
|
|
field[ 'default' ] = option.value;
|
|
}
|
|
options[ option.value ] = option.text;
|
|
return options;
|
|
}, {} );
|
|
break;
|
|
}
|
|
|
|
case 'TEXTAREA': {
|
|
field.type = 'textarea';
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// Match field attributes to fusion form fields
|
|
if ( field.id ) {
|
|
// Temporal fix for menu widget typo
|
|
field.id = 'widget-menu-widget--menu_Link_color' === field.id ? field.id.toLowerCase() : field.id;
|
|
field.heading = $form.find( 'label[for="' + field.id + '"]' ).text() || field.placeholder;
|
|
}
|
|
|
|
field.param_name = name;
|
|
// assing same ajax callback
|
|
field.callback = {};
|
|
field.callback[ 'function' ] = 'fusion_get_widget_markup';
|
|
field.callback.ajax = true;
|
|
|
|
if ( 'hidden' === field.type ) {
|
|
delete field.dependency;
|
|
field.hidden = true;
|
|
}
|
|
|
|
fields[ name ] = field;
|
|
} );
|
|
|
|
// Check if there were errors during parsing and add it to incorrect fields array
|
|
incorrectFields = _.find( fields, function ( field ) {
|
|
return ! field.heading || !field.name;
|
|
} );
|
|
|
|
widgets[ className ] = {
|
|
className: className,
|
|
fields: fields,
|
|
data: widget,
|
|
isInvalid: incorrectFields || this.invalidWidgets.includes( className ),
|
|
isCoreWidget: [ 'WP_Widget_Text', 'WP_Widget_Media_Audio', 'WP_Widget_Media_Image', 'WP_Widget_Media_Video', 'WP_Widget_Media_Gallery', 'WP_Widget_Custom_HTML' ].includes( className )
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Register all widgets from `widgetData` to `widgets`
|
|
*
|
|
* @since 2.0.0
|
|
* @returns {void}
|
|
*/
|
|
registerWidgets: function () {
|
|
var self = this;
|
|
|
|
// Attach a callback to getWidgetForms() in case `widgetData` is not fully loaded
|
|
getWidgetForms( function() {
|
|
self.widgetData = widgetData;
|
|
// Just parse `widgetData` once
|
|
if ( ! widgets.length ) {
|
|
_.each( self.widgetData, self.registerWidget.bind( self ) );
|
|
}
|
|
self.setWidgetFields();
|
|
|
|
// HTML and Text widget especial unescape.
|
|
if ( widget ) {
|
|
if ( 'WP_Widget_Custom_HTML' === widget.className ) {
|
|
self.model.attributes.params.wp_widget_custom_html__content = _.unescape( self.model.attributes.params.wp_widget_custom_html__content );
|
|
} else if ( 'WP_Widget_Text' === widget.className ) {
|
|
self.model.attributes.params.wp_widget_text__text = _.unescape( self.model.attributes.params.wp_widget_text__text );
|
|
}
|
|
}
|
|
} );
|
|
},
|
|
|
|
/**
|
|
* Cleans selection of a appended widget form
|
|
*
|
|
* @since 2.0.0
|
|
* @returns {void}
|
|
*/
|
|
clean: function() {
|
|
//NOTE: required for form only
|
|
this.destroyWidgetOptions();
|
|
this.deleteWpModels();
|
|
this.cleanForm();
|
|
},
|
|
|
|
/**
|
|
* Cleans previous appended forms
|
|
*
|
|
* @since 2.0.0
|
|
* @return {void}
|
|
*/
|
|
cleanForm: function() {
|
|
this.$el.find( '.fusion-widget-settings-form' ).remove();
|
|
},
|
|
|
|
/**
|
|
* Appends form into settings view
|
|
*
|
|
* @since 2.2.0
|
|
* @return {void}
|
|
*/
|
|
insertForm: function () {
|
|
var container,
|
|
event,
|
|
formSettings,
|
|
widgetData,
|
|
codeElement,
|
|
$el,
|
|
widgetClassName,
|
|
self = this;
|
|
|
|
// Create form and append it below the widget selector.
|
|
container = this.$el.find( '#general .fusion_widget .fusion-builder-option:first ' );
|
|
widgetData = widget.data;
|
|
widgetClassName = widget.className;
|
|
|
|
|
|
formSettings = {
|
|
coreWidget: widget.isCoreWidget,
|
|
attributes: {
|
|
id: widgetData.id + '-' + this.cid,
|
|
base: widgetData.id,
|
|
form: widgetData.form,
|
|
type: widgetClassName,
|
|
class: widgetData.classname
|
|
},
|
|
widgetData: this.widgetData
|
|
};
|
|
|
|
this.appendedForm = this.formTemplate( formSettings );
|
|
|
|
container.after( this.appendedForm );
|
|
|
|
jQuery( container.next() ).find( 'label' ).each( function() {
|
|
if ( 'INPUT' === jQuery( this ).prev().prop( 'tagName' ) ) {
|
|
jQuery( this ).prev().before( jQuery( this ) );
|
|
}
|
|
|
|
jQuery( this ).children().insertAfter( jQuery( this ) );
|
|
} );
|
|
|
|
// Aditional steps for core widgets.
|
|
if ( formSettings.coreWidget ) {
|
|
$el = this.$el.find( '.widget-inside' ).parent();
|
|
|
|
this.setFormValues( widgetClassName );
|
|
|
|
// Create the core WP view.
|
|
event = new jQuery.Event( 'widget-added' );
|
|
|
|
if ( 'WP_Widget_Text' === widgetClassName ) {
|
|
wp.textWidgets.handleWidgetAdded( event, $el );
|
|
} else if ( 'WP_Widget_Custom_HTML' === widgetClassName ) {
|
|
wp.customHtmlWidgets.handleWidgetAdded( event, $el );
|
|
} else {
|
|
wp.mediaWidgets.handleWidgetAdded( event, $el );
|
|
}
|
|
|
|
this.$el.find( '.widget-inside' ).css( 'display', 'block' );
|
|
if ( this.$el.find( '.wp-editor-area' ).length ) {
|
|
setTimeout( function() {
|
|
wp.textWidgets.widgetControls[ 'text-' + self.cid ].initializeEditor();
|
|
}, 200 );
|
|
}
|
|
|
|
if ( this.$el.find( '.custom-html-widget-fields .code' ).length ) {
|
|
codeElement = this.$el.find( '.custom-html-widget-fields .code' );
|
|
self.codeBlock = codeElement.next( '.CodeMirror' ).get( 0 ).CodeMirror;
|
|
|
|
if ( ! self.codeBlock ) {
|
|
self.codeBlock = CodeMirror.fromTextArea( codeElement[ 0 ], {
|
|
lineNumbers: true,
|
|
lineWrapping: true,
|
|
autofocus: true,
|
|
mode: 'htmlmixed'
|
|
} );
|
|
}
|
|
// Refresh editor after initialization
|
|
setTimeout( function() {
|
|
self.codeBlock.refresh();
|
|
self.codeBlock.focus();
|
|
}, 100 );
|
|
}
|
|
} else {
|
|
$el = this.$el.find( '.fusion-widget-settings-form' );
|
|
|
|
this.setFormValues( widgetClassName );
|
|
setTimeout( function() {
|
|
$el.find( '.widget-inside' ).css( 'display', 'block' );
|
|
}, 100 );
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Goes to each form value and set's default values or previously selected ones.
|
|
*
|
|
* @since 2.2.0
|
|
* @return {void}
|
|
*/
|
|
setFormValues: function( widgetClassName ) {
|
|
var self = this;
|
|
// Set form values
|
|
var paramPrefix = widgetClassName.toLowerCase() + '__';
|
|
|
|
_.each( this.model.attributes.params, function( value, key ) {
|
|
var $input, selector;
|
|
|
|
if ( 'type' !== key && -1 !== key.indexOf( paramPrefix ) ) {
|
|
selector = '[name$="[' + key.replace( paramPrefix, '' ) + ']"]';
|
|
$input = self.$el.find( selector );
|
|
}
|
|
|
|
if ( $input && $input.length ) {
|
|
if ( $input.is( ':checkbox' ) ) {
|
|
if ( 1 === parseInt( value ) || true === value || 'on' === value || 'enabled' === value ) {
|
|
$input.prop( 'checked', true );
|
|
} else {
|
|
$input.prop( 'checked', false );
|
|
}
|
|
} else {
|
|
$input.val( value );
|
|
}
|
|
}
|
|
} );
|
|
},
|
|
|
|
/**
|
|
* Delete the models.
|
|
*
|
|
* @since 2.2.0
|
|
* @returns {void}
|
|
*/
|
|
deleteWpModels: function() {
|
|
if ( 'undefined' !== typeof wp.mediaWidgets.widgetControls && 'undefined' !== typeof wp.mediaWidgets.modelCollection ) {
|
|
wp.mediaWidgets.modelCollection.reset();
|
|
wp.mediaWidgets.widgetControls = {};
|
|
}
|
|
if ( 'undefined' !== typeof wp.textWidgets.widgetControls ) {
|
|
wp.textWidgets.widgetControls = {};
|
|
}
|
|
|
|
if ( 'undefined' !== typeof wp.customHtmlWidgets.widgetControls ) {
|
|
wp.customHtmlWidgets.widgetControls = {};
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handler to destroy specific widget options.
|
|
*
|
|
* @since 2.2.0
|
|
* @returns {void}
|
|
*/
|
|
destroyWidgetOptions: function() {
|
|
|
|
// Remove each instance of tinyMCE editor from this view
|
|
this.$el.find( '.wp-editor-area' ).each( function() {
|
|
var editorID = jQuery( this ).attr( 'id' );
|
|
if ( 'undefined' !== typeof window.tinyMCE ) {
|
|
window.tinyMCE.execCommand( 'mceRemoveEditor', false, editorID );
|
|
if ( 'undefined' !== typeof window.tinyMCE.get( editorID ) ) {
|
|
window.tinyMCE.remove( '#' + editorID );
|
|
}
|
|
}
|
|
} );
|
|
},
|
|
|
|
/**
|
|
* Removes all generated options from selected widget
|
|
*
|
|
* @since 2.2.0
|
|
* @returns {void}
|
|
*/
|
|
cleanWidget: function() {
|
|
var self = this;
|
|
|
|
if ( ! widget ) {
|
|
return;
|
|
}
|
|
// Clean prev fields
|
|
_.each( widget.fields, function( field, key ) {
|
|
delete fusionAllElements.fusion_widget.params[ key ];
|
|
delete self.model.attributes.params[ key ];
|
|
} );
|
|
widget = null;
|
|
},
|
|
|
|
/**
|
|
* Returns current selected widget
|
|
*
|
|
* @since 2.2.0
|
|
* @returns {void}
|
|
*/
|
|
getWidget: function() {
|
|
return widget;
|
|
},
|
|
|
|
/**
|
|
* Sets the widget
|
|
* Action get's called when user selects a widget in <select />.
|
|
*
|
|
* @since 2.2.0
|
|
* @returns {void}
|
|
*/
|
|
setWidget: function() {
|
|
var className = this.model.attributes.params.type;
|
|
if ( ! className || ! widgets[ className ] ) {
|
|
return;
|
|
}
|
|
|
|
widget = widgets[ className ];
|
|
},
|
|
|
|
/**
|
|
* Updates settings fields according to the selected widget
|
|
*
|
|
* @since 2.2.0
|
|
* @returns {Void}
|
|
*/
|
|
updateWidget: function() {
|
|
var self = this;
|
|
|
|
if ( ! widget || widget.isCoreWidget || widget.isInvalid ) {
|
|
return;
|
|
}
|
|
|
|
// Update with widget fields
|
|
fusionAllElements.fusion_widget.params = _.extend(
|
|
{
|
|
type: fusionAllElements.fusion_widget.params.type
|
|
},
|
|
widget.fields,
|
|
fusionAllElements.fusion_widget.params
|
|
);
|
|
|
|
// Set default values
|
|
_.each( widget.fields, function( field, key ) {
|
|
|
|
// Skip if it already have a default param
|
|
if ( 'undefined' !== typeof self.model.attributes.params[ key ] ) {
|
|
return;
|
|
}
|
|
|
|
if ( 'object' === typeof field.value && field.value[ field[ 'default' ] ] ) {
|
|
self.model.attributes.params[ key ] = field[ 'default' ];
|
|
} else if ( 'object' !== typeof field.value && ( field[ 'default' ] || field.value ) ) {
|
|
self.model.attributes.params[ key ] = field[ 'default' ] || field.value;
|
|
}
|
|
} );
|
|
},
|
|
|
|
/**
|
|
* Sets settings fields according to the selected widget
|
|
*
|
|
* @since 2.2.0
|
|
* @returns {Void}
|
|
*/
|
|
setWidgetFields: function () {
|
|
if ( widget && widget.className === this.model.attributes.params.type ) {
|
|
return;
|
|
}
|
|
this.cleanWidget();
|
|
|
|
this.setWidget();
|
|
|
|
this.updateWidget();
|
|
}
|
|
|
|
} );
|
|
} );
|
|
|
|
}( jQuery ) );
|