/* 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( '