File: //var/www/html/triad-infosec/wp-content/plugins/fusion-builder/front-end/models/model-navigator.js
/* global FusionPageBuilderViewManager, fusionAllElements, FusionEvents, FusionApp */
var FusionPageBuilder = FusionPageBuilder || {};
( function() {
FusionPageBuilder.Navigator = Backbone.Model.extend( {
defaults: {
// see _getNavItemObject() function for this object format.
navigatorItems: null,
// An object with the views that are collapsed.
collapsedItems: {},
// If is either a page/column/element... etc. library navigator. This will not display some buttons.
navigatorType: ''
},
verifiedNestedRowsForCollapse: {},
initialize: function() {
this.update = _.debounce( this.update.bind( this ), 20 );
// Used for nested columns added.
this.listenTo( FusionEvents, 'fusion-columns-added', this.update );
this.listenTo( FusionEvents, 'fusion-content-changed', this.update );
this.listenTo( FusionEvents, 'fusion-element-removed', this.update );
this.listenTo( FusionEvents, 'fusion-column-resized', this.update );
this.listenTo( FusionEvents, 'fusion-cancel-nested-row-changes', this.restoreNestedRowCollapsible );
},
/**
* Update all the attributes. This will also trigger render if necessary.
*/
update: function() {
var navigatorItems = this.getNavigatorItems();
this.setNavigatorType();
this.setNewNestedRowsToCollapsible( navigatorItems );
// this will render if it's changed.
this.set( 'navigatorItems', navigatorItems );
},
getNavigatorItems: function() {
var elementViews = FusionPageBuilderViewManager.getViews(),
index,
navItems = [],
elType,
isContainerView,
isCheckoutForm,
isNextPageView,
isFormStep;
this._updateModelsToViewsMap( elementViews );
for ( index in elementViews ) {
if ( 'object' !== typeof elementViews[ index ] ) {
continue; // eslint-disable-line no-continue
}
elType = elementViews[ index ].model.get( 'element_type' );
isContainerView = ( 'fusion_builder_container' === elType );
isNextPageView = ( 'fusion_builder_next_page' === elType );
isCheckoutForm = ( 'fusion_woo_checkout_form' === elType );
isFormStep = ( 'fusion_builder_form_step' === elType );
// Construct all the containers, with their children in order.
// Only the children are in order, and not the containers themselves.
if ( isContainerView || ( isNextPageView && ! elementViews[ index ].$el.hasClass( 'fusion-builder-next-page-last' ) ) || isCheckoutForm || isFormStep ) {
navItems.push( this._getNavItemObject( elementViews[ index ] ) );
}
}
navItems = this._orderByDisplayedContainers( navItems );
return navItems;
},
setNavigatorType: function() {
this.set( 'navigatorType', FusionApp.data.fusion_element_type );
},
setNewNestedRowsToCollapsible( navigatorItems ) {
var i, j, k, l,
item,
collapsedItems = this.get( 'collapsedItems' );
if ( ! Array.isArray( navigatorItems ) ) {
return;
}
for ( i = 0; i < navigatorItems.length; i++ ) { // containers
for ( j = 0; j < navigatorItems[ i ].children.length; j++ ) { // rows
for ( k = 0; k < navigatorItems[ i ].children[ j ].children.length; k++ ) { // columns
for ( l = 0; l < navigatorItems[ i ].children[ j ].children[ k ].children.length; l++ ) { // elements or nested rows.
item = navigatorItems[ i ].children[ j ].children[ k ].children[ l ];
// eslint-disable-next-line max-depth
if (
'fusion_builder_row_inner' === item.type &&
'undefined' === typeof this.verifiedNestedRowsForCollapse[ item.view.cid ]
) {
this.verifiedNestedRowsForCollapse[ item.view.cid ] = true;
collapsedItems[ item.view.cid ] = true;
}
}
}
}
}
this.set( 'collapsedItems', collapsedItems );
},
/**
* When a nested row is canceled from editing, the view cid changes,
* so that the collapsible refreshes to default state of collapsed.
* */
restoreNestedRowCollapsible( data ) {
var oldStatus,
collapsedItems = this.get( 'collapsedItems' );
if ( 'object' !== typeof data.oldView || ! data.oldView.cid || 'object' !== typeof data.newView || ! data.newView.cid ) {
return;
}
oldStatus = collapsedItems[ data.oldView.cid ] ? collapsedItems[ data.oldView.cid ] : false;
if ( ! oldStatus ) {
this.verifiedNestedRowsForCollapse[ data.newView.cid ] = true;
} else {
this.verifiedNestedRowsForCollapse[ data.newView.cid ] = true;
collapsedItems[ data.newView.cid ] = true;
}
this.set( 'collapsedItems', collapsedItems );
},
_updateModelsToViewsMap: function( elementViews ) {
var index;
this.modelsToViewsMap = [];
this.viewsCidToViewsMap = [];
for ( index in elementViews ) {
if ( 'object' !== typeof elementViews[ index ] ) {
continue; // eslint-disable-line no-continue
}
this.modelsToViewsMap[ elementViews[ index ].model.cid ] = elementViews[ index ];
this.viewsCidToViewsMap[ elementViews[ index ].cid ] = elementViews[ index ];
}
},
_getNavItemObject: function( view ) {
return {
view: view,
model: view.model,
name: this._getElementDisplayName( view ),
type: view.model.get( 'element_type' ),
// An array with items of the same type as this.
children: this._getNavigationChildrenItems( view )
};
},
_getNavigationChildrenItems: function( view ) {
var model,
children = [],
childView,
i;
if ( ! view.model || ! view.model.children || ! view.model.children.length ) {
return children;
}
for ( i = 0; i < view.model.children.length; i++ ) {
model = view.model.children.models[ i ];
if ( 'object' === typeof this.modelsToViewsMap[ model.cid ] && 'multi_element_child' !== model.get( 'multi' ) ) {
childView = this.modelsToViewsMap[ model.cid ];
children.push( this._getNavItemObject( childView ) );
}
}
return children;
},
_orderByDisplayedContainers: function( navItems ) {
var previewIframe = jQuery( '#fb-preview' ),
containers,
orderedItems = [],
j,
index;
if ( ! previewIframe.length ) {
return navItems;
}
containers = previewIframe[ 0 ].contentWindow.jQuery( '#fusion_builder_container > .fusion-builder-container, #fusion_builder_container > .fusion-builder-next-page, #fusion_builder_container > .fusion-checkout-form, #fusion_builder_container > .fusion-builder-form-step' );
for ( index = 0; index < containers.length; index++ ) {
for ( j = 0; j < navItems.length; j++ ) {
if ( navItems[ j ].view.$el.is( containers.eq( index ) ) ) {
orderedItems.push( navItems[ j ] );
}
}
}
return orderedItems;
},
_getElementDisplayName: function( view ) {
var elType = view.model.get( 'element_type' ),
params;
// If element is container, the use the admin label.
if ( 'fusion_builder_container' === elType ) {
params = view.model.get( 'params' );
if ( params.admin_label ) {
return params.admin_label;
}
}
// Return the element name.
if ( fusionAllElements[ elType ] && fusionAllElements[ elType ].name ) {
return fusionAllElements[ elType ].name;
}
return elType;
}
} );
}( jQuery ) );