373 lines
12 KiB
JavaScript
373 lines
12 KiB
JavaScript
/* global MediumEditor, FusionPageBuilderApp */
|
|
var FusionPageBuilder = FusionPageBuilder || {};
|
|
|
|
( function() {
|
|
|
|
FusionPageBuilder.InlineEditorHelpers = Backbone.Model.extend( {
|
|
initialize: function() {
|
|
this._reRenderElement = _.debounce( _.bind( this.reRenderElement, this ), 300 );
|
|
this._logChangeEvent = _.debounce( _.bind( this.logChangeEvent, this ), 500 );
|
|
this.initialValue = null;
|
|
},
|
|
|
|
logChangeEvent: function( param, value, tempModel, paramName ) {
|
|
var label = paramName,
|
|
state = {
|
|
type: 'param',
|
|
param: param,
|
|
newValue: value,
|
|
cid: tempModel.parentView.model.get( 'cid' )
|
|
},
|
|
elementMap = window.fusionAllElements[ tempModel.get( 'element_type' ) ],
|
|
paramTitle = 'object' === typeof elementMap.params[ label ] ? elementMap.params[ label ].heading : param;
|
|
|
|
state.oldValue = this.initialValue;
|
|
this.initialValue = null;
|
|
|
|
window.FusionEvents.trigger( 'fusion-history-save-step', window.fusionBuilderText.edited + ' ' + elementMap.name + ' - ' + paramTitle, state );
|
|
},
|
|
|
|
updateInlineShortcode: function( oldShortcode, newShortcode, tempModel, paramName ) {
|
|
var oldContent = tempModel.parentView.model.attributes.params.element_content,
|
|
newContent = oldContent.replace( oldShortcode, newShortcode );
|
|
|
|
tempModel.parentView.model.attributes.params.element_content = newContent;
|
|
tempModel.set( 'inlineElement', newShortcode );
|
|
|
|
if ( null === this.initialValue ) {
|
|
this.initialValue = oldContent;
|
|
}
|
|
this._logChangeEvent( 'element_content', newContent, tempModel, paramName );
|
|
},
|
|
|
|
processInlineElement: function( model, paramName ) {
|
|
var newViewOutput,
|
|
tooltipElements = jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( model.parentView.$el ).find( '[data-id="' + model.get( 'cid' ) + '"]' ).find( '[data-toggle="tooltip"]' );
|
|
|
|
if ( tooltipElements.length ) {
|
|
tooltipElements.tooltip( 'destroy' );
|
|
}
|
|
|
|
// Update shortcode
|
|
this.updateInlineShortcode( model.get( 'inlineElement' ), FusionPageBuilderApp.generateElementShortcode( model, false, true ), model, paramName );
|
|
|
|
// Get markup
|
|
newViewOutput = this.getInlineElementMarkup( model );
|
|
|
|
// Append html
|
|
model.parentView.$el.find( '[data-id="' + model.get( 'cid' ) + '"]:not(.fusion-inline-ajax)' ).html( '' ).append( newViewOutput );
|
|
|
|
// Trigger js
|
|
jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( 'body' ).trigger( 'fusion-element-render-fusion_text', model.parentView.model.attributes.cid );
|
|
},
|
|
|
|
getInlineElementMarkup: function( model ) {
|
|
var viewSettings = {
|
|
model: model
|
|
},
|
|
newView,
|
|
newViewOutput;
|
|
|
|
if ( 'undefined' !== typeof FusionPageBuilder[ model.get( 'element_type' ) ] ) {
|
|
newView = new FusionPageBuilder[ model.get( 'element_type' ) ]( viewSettings );
|
|
} else {
|
|
newView = new FusionPageBuilder.ElementView( viewSettings );
|
|
}
|
|
|
|
// This is before the content is being replaced
|
|
if ( 'function' === typeof newView.beforePatch ) {
|
|
newView.beforePatch();
|
|
}
|
|
newViewOutput = newView.getTemplate();
|
|
|
|
return newViewOutput;
|
|
},
|
|
|
|
getInlineElementSettings: function( model ) {
|
|
var viewSettings = {
|
|
model: model
|
|
},
|
|
modalView = new FusionPageBuilder.ElementSettingsView( viewSettings );
|
|
|
|
// No need to render if it already is.
|
|
if ( ! FusionPageBuilderApp.SettingsHelpers.shouldRenderSettings( modalView ) ) {
|
|
return;
|
|
}
|
|
|
|
// If we want dialog.
|
|
if ( 'dialog' === window.FusionApp.preferencesData.editing_mode ) {
|
|
jQuery( modalView.render().el ).dialog( {
|
|
title: window.fusionAllElements[ model.get( 'element_type' ) ].name,
|
|
width: window.FusionApp.dialog.dialogData.width,
|
|
height: window.FusionApp.dialog.dialogData.height,
|
|
position: window.FusionApp.dialog.dialogData.position,
|
|
dialogClass: 'fusion-builder-dialog fusion-builder-settings-dialog',
|
|
|
|
dragStop: function( event, ui ) {
|
|
window.FusionApp.dialog.saveDialogPosition( ui.offset );
|
|
},
|
|
|
|
resizeStop: function( event, ui ) {
|
|
window.FusionApp.dialog.saveDialogSize( ui.size );
|
|
},
|
|
|
|
open: function( event ) {
|
|
var $dialogContent = jQuery( event.target ),
|
|
$tabMenu = $dialogContent.find( '.fusion-builder-modal-top-container' );
|
|
|
|
$dialogContent.closest( '.ui-dialog' ).find( '.ui-dialog-titlebar' ).append( $tabMenu );
|
|
FusionPageBuilderApp.$el.addClass( 'fusion-builder-no-ui' );
|
|
},
|
|
dragStart: function( event ) {
|
|
|
|
// Used to close any open drop-downs in TinyMce.
|
|
jQuery( event.target ).trigger( 'click' );
|
|
},
|
|
|
|
beforeClose: function() {
|
|
modalView.saveSettings();
|
|
window.FusionEvents.trigger( 'fusion-content-changed' );
|
|
FusionPageBuilderApp.$el.removeClass( 'fusion-builder-no-ui' );
|
|
}
|
|
|
|
} );
|
|
} else {
|
|
|
|
// Adding into sidebar view instead.
|
|
modalView.model.set( 'title', window.fusionAllElements[ model.get( 'element_type' ) ].name );
|
|
modalView.model.set( 'display', 'sidebar' );
|
|
window.FusionApp.sidebarView.renderElementSettings( modalView );
|
|
}
|
|
},
|
|
|
|
removeStyle: function( model ) {
|
|
var $editor,
|
|
content,
|
|
param,
|
|
params = model.parentView.model.get( 'params' ),
|
|
editorInstance;
|
|
|
|
$editor = model.$target.closest( '.fusion-live-editable' );
|
|
|
|
model.$target.replaceWith( model.attributes.params.element_content );
|
|
|
|
editorInstance = FusionPageBuilderApp.inlineEditors.getEditor( $editor.data( 'medium-editor-editor-index' ) );
|
|
|
|
if ( 'undefined' !== typeof editorInstance ) {
|
|
content = editorInstance.getContent();
|
|
} else {
|
|
content = $editor.html();
|
|
}
|
|
|
|
param = $editor.data( 'param' ),
|
|
|
|
// Fix for inline font family style.
|
|
content = content.replace( /"/g, '\'' );
|
|
|
|
// Adds in any inline shortcodes.
|
|
content = FusionPageBuilderApp.htmlToShortcode( content, model.parentView.model.get( 'cid' ) );
|
|
|
|
params[ param ] = content;
|
|
model.parentView.model.set( 'params', params );
|
|
|
|
// Update parent settings tinyMCE.
|
|
FusionPageBuilderApp.setContent( param, content );
|
|
|
|
// Remove the inline element settings view, if open.
|
|
FusionEvents.trigger( 'fusion-element-removed', model.get( 'cid' ) );
|
|
},
|
|
|
|
/**
|
|
* Init the Medium Editor for elements that can be live-edited.
|
|
*
|
|
* @since 2.0.0
|
|
* @return {void}
|
|
*/
|
|
liveEditor: function( view ) {
|
|
var liveElements = view.$el.find( '.fusion-live-editable:not([data-medium-editor-element="true"])' );
|
|
|
|
if ( liveElements.length ) {
|
|
liveElements.each( function() {
|
|
FusionPageBuilderApp.inlineEditors.addEditorInstance( jQuery( this ), view );
|
|
} );
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Destroys each instance of live editor.
|
|
*
|
|
* @since 2.0.0
|
|
* @return {void}
|
|
*/
|
|
removeLiveEditors: function( view ) {
|
|
var liveElements = view.$el.find( '[data-medium-editor-element="true"]' ),
|
|
viewEditors = view.model.get( 'inlineEditors' );
|
|
|
|
// First remove IDs stored on view.
|
|
if ( 'undefined' !== typeof viewEditors && viewEditors.length ) {
|
|
_.each( viewEditors, function( inlineEditor ) {
|
|
FusionPageBuilderApp.inlineEditors.destroyEditor( inlineEditor );
|
|
} );
|
|
}
|
|
|
|
// Check if there are still more IDs in DOM.
|
|
if ( liveElements.length ) {
|
|
liveElements.each( function() {
|
|
FusionPageBuilderApp.inlineEditors.destroyEditor( jQuery( this ).data( 'medium-editor-editor-index' ) );
|
|
} );
|
|
}
|
|
|
|
view.model.set( 'inlineEditors', [] );
|
|
},
|
|
|
|
liveEditorEvent: function( view ) {
|
|
var self = this,
|
|
$editors = view.$el.find( '.fusion-live-editable' );
|
|
|
|
// Remove any we already have, to prevent duplicates.
|
|
self.removeLiveEditors( view );
|
|
|
|
if ( true === view.model.get( 'inline_editor' ) && view.$el ) {
|
|
if ( 1 === $editors.length && view.autoSelectEditor ) {
|
|
FusionPageBuilderApp.inlineEditors.addEditorInstance( $editors, view, true );
|
|
} else {
|
|
$editors.on( 'mouseenter.inline-editor', function() {
|
|
self.liveEditor( view );
|
|
} );
|
|
}
|
|
view.autoSelectEditor = false;
|
|
}
|
|
},
|
|
|
|
getInlineHTML: function( content, id ) {
|
|
var $newContent;
|
|
|
|
if ( '' === content || 'undefined' === typeof content ) {
|
|
return '';
|
|
}
|
|
|
|
try {
|
|
$newContent = jQuery( content );
|
|
} catch ( error ) {
|
|
console.log( error ); // jshint ignore:line
|
|
|
|
return content;
|
|
}
|
|
|
|
// If no length, meaning no wrapping tag in this case then we wrap.
|
|
if ( 0 === $newContent.length ) {
|
|
$newContent = jQuery( '<span />' ).html( content );
|
|
} else if ( 1 < $newContent.length ) {
|
|
$newContent = jQuery( '<div />' ).html( content );
|
|
}
|
|
|
|
$newContent.addClass( 'fusion-disable-editing fusion-inline-ajax' ).attr( 'contenteditable', 'false' ).attr( 'data-id', id );
|
|
|
|
// Span is added for content which is just a string and used as a selector #2609.
|
|
return $newContent[ 0 ].outerHTML;
|
|
},
|
|
|
|
/**
|
|
* Checks whether the inline editor is enabled.
|
|
*
|
|
* @since 2.0.0
|
|
* @param {string} shortcodeTag - Shortcode tag.
|
|
* @return {boolean}
|
|
*/
|
|
inlineEditorAllowed: function( shortcodeTag ) {
|
|
var inlineEditor = 'undefined' !== typeof window.fusionAllElements[ shortcodeTag ] && 'undefined' !== typeof window.fusionAllElements[ shortcodeTag ].inline_editor ? window.fusionAllElements[ shortcodeTag ].inline_editor : false;
|
|
|
|
return inlineEditor;
|
|
},
|
|
|
|
/**
|
|
* Used to update model param if exists as override.
|
|
*
|
|
* @since 2.0.0
|
|
* @param {string} cid - The element cid.
|
|
* @param {string} param - The parameter name.
|
|
* @param {string} value - The new parameter value.
|
|
* @param {boolean} debounced - To debounce update or not.
|
|
* @return {void}
|
|
*/
|
|
updateParentElementParam: function( cid, param, value, debounced ) {
|
|
var view = window.FusionPageBuilderViewManager.getView( cid ),
|
|
params = 'undefined' !== typeof view ? view.model.get( 'params' ) : false;
|
|
|
|
debounced = 'undefined' !== typeof debounced ? debounced : false;
|
|
|
|
if ( 'undefined' === typeof cid || 'undefined' === typeof param || 'undefined' === typeof value || ! params ) {
|
|
return false;
|
|
}
|
|
|
|
if ( ! param ) {
|
|
return false;
|
|
}
|
|
|
|
if ( value === params[ param ] ) {
|
|
return true;
|
|
}
|
|
|
|
view.activeInlineEditing = true;
|
|
|
|
if ( debounced ) {
|
|
this._reRenderElement( view, param, value );
|
|
} else {
|
|
this.reRenderElement( view, param, value );
|
|
}
|
|
return true;
|
|
},
|
|
|
|
reRenderElement: function( view, param, value ) {
|
|
var reRender = true;
|
|
|
|
if ( view ) {
|
|
reRender = view.updateParam( param, value );
|
|
|
|
if ( reRender ) {
|
|
view.reRender();
|
|
}
|
|
}
|
|
},
|
|
|
|
setOverrideParams: function( control, option ) {
|
|
var selectionHtml = MediumEditor.selection.getSelectionHtml( control.document ),
|
|
el = MediumEditor.selection.getSelectionElement( control.document ),
|
|
innerHTML = el ? el.innerHTML.trim() : '',
|
|
overrideObject = {};
|
|
|
|
// Default for not full content or overwritable.
|
|
control.parentCid = false;
|
|
control.override = false;
|
|
|
|
// Element has not override for option.
|
|
if ( ! el || ! el.classList.contains( 'fusion-live-editable' ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( 'string' === typeof option ) {
|
|
|
|
// Selection is not full.
|
|
if ( ! el.getAttribute( 'data-inline-override-' + option ) || ( selectionHtml.trim() !== innerHTML && jQuery( '<div>' + selectionHtml + '</div>' ).text().trim() !== jQuery( '<div>' + innerHTML + '</div>' ).text().trim() ) ) {
|
|
return;
|
|
}
|
|
control.override = el.getAttribute( 'data-inline-override-' + option );
|
|
control.parentCid = el.getAttribute( 'data-inline-parent-cid' );
|
|
|
|
} else if ( 'object' == typeof option ) {
|
|
_.each( option, function( scopedOption ) {
|
|
if ( ! el.getAttribute( 'data-inline-override-' + scopedOption ) || ( selectionHtml.trim() !== innerHTML && jQuery( '<div>' + selectionHtml + '</div>' ).text().trim() !== jQuery( '<div>' + innerHTML + '</div>' ).text().trim() ) ) {
|
|
overrideObject[ scopedOption ] = false;
|
|
} else {
|
|
overrideObject[ scopedOption ] = el.getAttribute( 'data-inline-override-' + scopedOption );
|
|
control.parentCid = el.getAttribute( 'data-inline-parent-cid' );
|
|
}
|
|
control.override = overrideObject;
|
|
} );
|
|
}
|
|
}
|
|
|
|
} );
|
|
|
|
}( jQuery ) );
|