ControlWysiwygItemView = ControlBaseItemView.extend( { childEvents: { 'keyup textarea.elementor-wp-editor': 'updateElementModel' }, buttons: { keepInBasic: [ 'bold', 'italic', 'link', 'unlink', 'wp_adv', 'fullscreen' ], moveToBasic: { underline: 'italic' } }, initialize: function() { ControlBaseItemView.prototype.initialize.apply( this, arguments ); var self = this; this.editorID = 'elementorwpeditor' + this.cid; var editorConfig = { id: this.editorID, selector: '#' + this.editorID, setup: function( editor ) { editor.on( 'keyup change', function() { editor.save(); self.setValue( editor.getContent() ); } ); } }; tinyMCEPreInit.mceInit[ this.editorID ] = _.extend( _.clone( tinyMCEPreInit.mceInit.elementorwpeditor ), editorConfig ); this.rearrangeButtons(); // This class allows us to reduce "flicker" by hiding the editor // until we are done loading and modifying it. this.$el.addClass( 'elementor-loading-editor' ); // Wait a cycle before initializing the editors. _.defer( function() { // Initialize QuickTags, and set as the default mode. quicktags( { buttons: 'strong,em,del,link,img,close', id: self.editorID } ); switchEditors.go( self.editorID, 'tmce' ); delete QTags.instances[ 0 ]; } ); }, attachElContent: function() { var editorTemplate = elementor.config.wp_editor.replace( /elementorwpeditor/g, this.editorID ).replace( '%%EDITORCONTENT%%', this.getControlValue() ); this.$el.html( editorTemplate ); return this; }, rearrangeButtons: function() { var editorProps = tinyMCEPreInit.mceInit[ this.editorID ], editorBasicToolbarButtons = editorProps.toolbar1.split( ',' ), editorAdvancedToolbarButtons = editorProps.toolbar2.split( ',' ), buttonsToKeepInBasic = Array.prototype.slice.call( this.buttons.keepInBasic ), buttonsToMoveToAdvanced = _.difference( editorBasicToolbarButtons, buttonsToKeepInBasic ), buttonsToKeepInAdvanced = _.difference( editorAdvancedToolbarButtons, Object.keys( this.buttons.moveToBasic ) ); _.each( this.buttons.moveToBasic, function( afterButton, button ) { var afterButtonIndex = buttonsToKeepInBasic.indexOf( afterButton ); if ( -1 !== afterButtonIndex ) { buttonsToKeepInBasic.splice( afterButtonIndex + 1, 0, button ); } } ); editorProps.toolbar1 = buttonsToKeepInBasic.join( ',' ); editorProps.toolbar2 = buttonsToMoveToAdvanced + ',' + buttonsToKeepInAdvanced; }, onBeforeDestroy: function() { // Remove TinyMCE and QuickTags instances tinymce.EditorManager.execCommand( 'mceRemoveEditor', true, this.editorID ); delete QTags.instances[ this.editorID ]; // Cleanup PreInit data delete tinyMCEPreInit.mceInit[ this.editorID ]; delete tinyMCEPreInit.qtInit[ this.editorID ]; } } );
ControlMediaItemView = ControlBaseItemView.extend( { ui: function() { var ui = ControlBaseItemView.prototype.ui.apply( this, arguments ); ui.controlMedia = '.elementor-control-media'; ui.frameOpeners = '.elementor-control-media-upload-button, .elementor-control-media-image'; ui.deleteButton = '.elementor-control-media-delete'; return ui; }, childEvents: { 'click @ui.frameOpeners': 'openFrame', 'click @ui.deleteButton': 'deleteImage' }, onReady: function() { if ( _.isEmpty( this.getControlValue() ) ) { this.ui.controlMedia.addClass( 'media-empty' ); } }, openFrame: function() { this.initFrame(); this.frame.open(); }, deleteImage: function() { this.setValue( '' ); this.render(); }, /** * Create a media modal select frame, and store it so the instance can be reused when needed. */ initFrame: function() { var options, ids = this.getControlValue(); options = { frame: 'post', multiple: true, button: { text: 'Insert Media' }, state: 'gallery' }; if ( '' !== ids ) { options.selection = this.fetchSelection( ids ); options.state = 'gallery-edit'; } this.frame = wp.media( options ); // When a file is selected, run a callback. this.frame.on( 'update', _.bind( this.select, this ) ); this.frame.on( 'menu:render:default', _.bind( this.menuRender, this ) ); this.frame.on( 'content:render:browse', _.bind( this.gallerySettings, this ) ); }, menuRender: function( view ) { view.unset( 'insert' ); view.unset( 'featured-image' ); }, gallerySettings: function( browser ) { browser.sidebar.on( 'ready', function() { browser.sidebar.unset( 'gallery' ); } ); }, fetchSelection: function( ids ) { var idArray = ids.split( ',' ), args = { orderby: 'post__in', order: 'ASC', type: 'image', perPage: -1, post__in: idArray }, attachments = wp.media.query( args ), selection = new wp.media.model.Selection( attachments.models, { props: attachments.props.toJSON(), multiple: true } ); return selection; }, /** * Callback handler for when an attachment is selected in the media modal. * Gets the selected image information, and sets it within the control. */ select: function( selection ) { var ids = selection.pluck( 'id' ); this.setValue( ids.toString() ); this.render(); }, onBeforeDestroy: function() { if ( this.frame ) { this.frame.off( 'update' ); this.frame.off( 'menu:render:default' ); this.frame.off( 'content:render:browse' ); } this.$el.remove(); } } );
var ControlBaseItemView = require( 'elementor-views/controls/base' ), ControlStructureItemView; ControlStructureItemView = ControlBaseItemView.extend( { templateHelpers: function() { var helpers = ControlBaseItemView.prototype.templateHelpers.apply( this, arguments ); helpers.getMorePresets = _.bind( this.getMorePresets, this ); return helpers; }, getMorePresets: function() { var parsedStructure = elementor.presetsFactory.getParsedStructure( this.getControlValue() ); return elementor.presetsFactory.getPresets( parsedStructure.columnsCount ); }, onInputChange: function() { var editor = elementor.getPanelView().getCurrentPageView(), currentEditedSection = editor.getOption( 'editedElementView' ); currentEditedSection.redefineLayout(); this.render(); } } ); module.exports = ControlStructureItemView;
ControlWysiwygItemView = ControlBaseItemView.extend( { childEvents: { 'keyup textarea.elementor-wp-editor': 'updateElementModel' }, // List of buttons to move {buttonToMove: afterButton} buttons: { moveToAdvanced: { blockquote: 'removeformat', alignleft: 'blockquote', aligncenter: 'alignleft', alignright: 'aligncenter' }, moveToBasic: {}, removeFromBasic: [ 'unlink', 'wp_more' ], removeFromAdvanced: [] }, initialize: function() { ControlBaseItemView.prototype.initialize.apply( this, arguments ); var self = this; self.editorID = 'elementorwpeditor' + self.cid; // Wait a cycle before initializing the editors. _.defer( function() { // Initialize QuickTags, and set as the default mode. quicktags( { buttons: 'strong,em,del,link,img,close', id: self.editorID } ); if ( elementor.config.rich_editing_enabled ) { switchEditors.go( self.editorID, 'tmce' ); } delete QTags.instances[ 0 ]; } ); if ( ! elementor.config.rich_editing_enabled ) { self.$el.addClass( 'elementor-rich-editing-disabled' ); return; } var editorConfig = { id: self.editorID, selector: '#' + self.editorID, setup: function( editor ) { editor.on( 'keyup change undo redo SetContent', function() { editor.save(); self.setValue( editor.getContent() ); } ); } }; tinyMCEPreInit.mceInit[ self.editorID ] = _.extend( _.clone( tinyMCEPreInit.mceInit.elementorwpeditor ), editorConfig ); self.rearrangeButtons(); }, attachElContent: function() { var editorTemplate = elementor.config.wp_editor.replace( /elementorwpeditor/g, this.editorID ).replace( '%%EDITORCONTENT%%', this.getControlValue() ); this.$el.html( editorTemplate ); return this; }, moveButtons: function( buttonsToMove, from, to ) { _.each( buttonsToMove, function( afterButton, button ) { var buttonIndex = from.indexOf( button ), afterButtonIndex = to.indexOf( afterButton ); if ( -1 === buttonIndex ) { throw new ReferenceError( 'Trying to move non-existing button `' + button + '`' ); } if ( -1 === afterButtonIndex ) { throw new ReferenceError( 'Trying to move button after non-existing button `' + afterButton + '`' ); } from.splice( buttonIndex, 1 ); to.splice( afterButtonIndex + 1, 0, button ); } ); }, rearrangeButtons: function() { var editorProps = tinyMCEPreInit.mceInit[ this.editorID ], editorBasicToolbarButtons = editorProps.toolbar1.split( ',' ), editorAdvancedToolbarButtons = editorProps.toolbar2.split( ',' ); editorBasicToolbarButtons = _.difference( editorBasicToolbarButtons, this.buttons.removeFromBasic ); editorAdvancedToolbarButtons = _.difference( editorAdvancedToolbarButtons, this.buttons.removeFromAdvanced ); this.moveButtons( this.buttons.moveToBasic, editorAdvancedToolbarButtons, editorBasicToolbarButtons ); this.moveButtons( this.buttons.moveToAdvanced, editorBasicToolbarButtons, editorAdvancedToolbarButtons ); editorProps.toolbar1 = editorBasicToolbarButtons.join( ',' ); editorProps.toolbar2 = editorAdvancedToolbarButtons.join( ',' ); }, onBeforeDestroy: function() { // Remove TinyMCE and QuickTags instances delete QTags.instances[ this.editorID ]; if ( ! elementor.config.rich_editing_enabled ) { return; } tinymce.EditorManager.execCommand( 'mceRemoveEditor', true, this.editorID ); // Cleanup PreInit data delete tinyMCEPreInit.mceInit[ this.editorID ]; delete tinyMCEPreInit.qtInit[ this.editorID ]; } } );
ControlDateTimePickerItemView = ControlBaseItemView.extend( { ui: function() { var ui = ControlBaseItemView.prototype.ui.apply( this, arguments ); ui.picker = '.elementor-date-time-picker'; return ui; }, onReady: function() { var self = this; var options = _.extend( this.model.get( 'picker_options' ), { onHide: function() { self.saveValue(); } } ); this.ui.picker.appendDtpicker( options ).handleDtpicker( 'setDate', new Date( this.getControlValue() ) ); }, saveValue: function() { this.setValue( this.ui.input.val() ); }, onBeforeDestroy: function() { this.saveValue(); this.ui.picker.dtpicker( 'destroy' ); } } );
ControlBaseMultipleItemView = ControlBaseItemView.extend( { applySavedValue: function() { var values = this.getControlValue(), $inputs = this.$( '[data-setting]' ), self = this; _.each( values, function( value, key ) { var $input = $inputs.filter( function() { return key === this.dataset.setting; } ); self.setInputValue( $input, value ); } ); }, getControlValue: function( key ) { var values = this.elementSettingsModel.get( this.model.get( 'name' ) ); if ( ! Backbone.$.isPlainObject( values ) ) { return {}; } if ( key ) { return values[ key ] || ''; } return elementor.helpers.cloneObject( values ); }, setValue: function( key, value ) { var values = this.getControlValue(); if ( 'object' === typeof key ) { _.each( key, function( internalValue, internalKey ) { values[ internalKey ] = internalValue; } ); } else { values[ key ] = value; } this.setSettingsModel( values ); }, updateElementModel: function( event ) { var inputValue = this.getInputValue( event.currentTarget ), key = event.currentTarget.dataset.setting; this.setValue( key, inputValue ); } }, { // Static methods replaceStyleValues: function( cssProperty, controlValue ) { if ( ! _.isObject( controlValue ) ) { return ''; // invalid } // Trying to retrieve whole the related properties // according to the string matches. // When one of the properties is empty, aborting // the action and returning an empty string. try { return cssProperty.replace( /\{\{([A-Z]+)}}/g, function( fullMatch, pureMatch ) { var value = controlValue[ pureMatch.toLowerCase() ]; if ( '' === value ) { throw ''; } return value; } ); } catch ( exception ) { return ''; } } } );
ControlRepeaterItemView = ControlBaseItemView.extend( { ui: { btnAddRow: '.elementor-repeater-add', fieldContainer: '.elementor-repeater-fields' }, events: { 'click @ui.btnAddRow': 'onButtonAddRowClick', 'sortstart @ui.fieldContainer': 'onSortStart', 'sortupdate @ui.fieldContainer': 'onSortUpdate', 'sortstop @ui.fieldContainer': 'onSortStop' }, childView: RepeaterRowView, childViewContainer: '.elementor-repeater-fields', templateHelpers: function() { return { data: _.extend( {}, this.model.toJSON(), { controlValue: [] } ) }; }, childViewOptions: function() { return { controlFields: this.model.get( 'fields' ), titleField: this.model.get( 'title_field' ), parentModel: this.elementSettingsModel // For parentConditions in repeaterRow }; }, initialize: function( options ) { ControlBaseItemView.prototype.initialize.apply( this, arguments ); this.collection = this.elementSettingsModel.get( this.model.get( 'name' ) ); this.listenTo( this.collection, 'change add remove reset', this.onCollectionChanged, this ); this.collection.each( function( model ) { if ( ! model.get( '_id' ) ) { model.set( '_id', elementor.helpers.getUniqueID() ); } } ); }, addRow: function( data, options ) { var id = elementor.helpers.getUniqueID(); if ( data instanceof Backbone.Model ) { data.set( '_id', id ); } else { data._id = id; } return this.collection.add( data, options ); }, editRow: function( rowView ) { if ( this.currentEditableChild ) { var currentEditable = this.currentEditableChild.getChildViewContainer( this.currentEditableChild ); currentEditable.removeClass( 'editable' ); // If the repeater contains TinyMCE editors, fire the `hide` trigger to hide floated toolbars currentEditable.find( '.elementor-wp-editor' ).each( function() { tinymce.get( this.id ).fire( 'hide' ); } ); } if ( this.currentEditableChild === rowView ) { delete this.currentEditableChild; return; } rowView.getChildViewContainer( rowView ).addClass( 'editable' ); this.currentEditableChild = rowView; this.updateActiveRow(); }, toggleMinRowsClass: function() { if ( ! this.model.get( 'prevent_empty' ) ) { return; } this.$el.toggleClass( 'elementor-repeater-has-minimum-rows', 1 >= this.collection.length ); }, updateActiveRow: function() { var activeItemIndex = 0; if ( this.currentEditableChild ) { activeItemIndex = this.currentEditableChild.itemIndex; } this.setEditSetting( 'activeItemIndex', activeItemIndex ); }, updateChildIndexes: function() { this.children.each( _.bind( function( view ) { view.updateIndex( this.collection.indexOf( view.model ) + 1 ); }, this ) ); }, onRender: function() { this.ui.fieldContainer.sortable( { axis: 'y', handle: '.elementor-repeater-row-tools' } ); this.toggleMinRowsClass(); }, onSortStart: function( event, ui ) { ui.item.data( 'oldIndex', ui.item.index() ); }, onSortStop: function( event, ui ) { // Reload TinyMCE editors (if exist), it's a bug that TinyMCE content is missing after stop dragging ui.item.find( '.elementor-wp-editor' ).each( function() { var editor = tinymce.get( this.id ), settings = editor.settings; settings.height = Backbone.$( editor.getContainer() ).height(); tinymce.execCommand( 'mceRemoveEditor', true, this.id ); tinymce.init( settings ); } ); }, onSortUpdate: function( event, ui ) { var oldIndex = ui.item.data( 'oldIndex' ), model = this.collection.at( oldIndex ), newIndex = ui.item.index(); this.collection.remove( model ); this.addRow( model, { at: newIndex } ); }, onAddChild: function() { this.updateChildIndexes(); this.updateActiveRow(); }, onRemoveChild: function( childView ) { if ( childView === this.currentEditableChild ) { delete this.currentEditableChild; } this.updateChildIndexes(); this.updateActiveRow(); }, onCollectionChanged: function() { this.elementSettingsModel.trigger( 'change' ); this.toggleMinRowsClass(); }, onButtonAddRowClick: function() { var defaults = {}; _.each( this.model.get( 'fields' ), function( field ) { defaults[ field.name ] = field['default']; } ); var newModel = this.addRow( defaults ), newChildView = this.children.findByModel( newModel ); this.editRow( newChildView ); }, onChildviewClickRemove: function( childView ) { childView.model.destroy(); }, onChildviewClickDuplicate: function( childView ) { this.addRow( childView.model.clone(), { at: childView.itemIndex } ); }, onChildviewClickEdit: function( childView ) { this.editRow( childView ); } } );
ControlIconItemView = ControlBaseItemView.extend( { ui: function() { var ui = ControlBaseItemView.prototype.ui.apply( this, arguments ); ui.iconSelect = '.elementor-control-icon'; return ui; }, initialize: function() { ControlBaseItemView.prototype.initialize.apply( this, arguments ); this.filterIcons(); }, filterIcons: function() { var icons = this.model.get( 'icons' ), include = this.model.get( 'include' ), exclude = this.model.get( 'exclude' ); if ( include ) { var filteredIcons = {}; _.each( include, function( iconKey ) { filteredIcons[ iconKey ] = icons[ iconKey ]; } ); this.model.set( 'icons', filteredIcons ); return; } if ( exclude ) { _.each( exclude, function( iconKey ) { delete icons[ iconKey ]; } ); } }, iconsList: function( icon ) { if ( ! icon.id ) { return icon.text; } return Backbone.$( '<span><i class="' + icon.id + '"></i> ' + icon.text + '</span>' ); }, getFieldTitleValue: function() { var controlValue = this.getControlValue(); return controlValue.replace( /^fa fa-/, '' ).replace( '-', ' ' ); }, onReady: function() { this.ui.iconSelect.select2( { allowClear: true, templateResult: _.bind( this.iconsList, this ), templateSelection: _.bind( this.iconsList, this ) } ); }, onBeforeDestroy: function() { if ( this.ui.iconSelect.data( 'select2' ) ) { this.ui.iconSelect.select2( 'destroy' ); } this.$el.remove(); } } );
var ControlBaseItemView = require( 'elementor-views/controls/base' ), ControlAnimationItemView; ControlAnimationItemView = ControlBaseItemView.extend( { onReady: function() { this.ui.select.select2(); } } ); module.exports = ControlAnimationItemView;
ControlIconItemView = ControlBaseItemView.extend( { initialize: function() { ControlBaseItemView.prototype.initialize.apply( this, arguments ); this.filterIcons(); }, filterIcons: function() { var icons = this.model.get( 'icons' ), include = this.model.get( 'include' ), exclude = this.model.get( 'exclude' ); if ( include ) { var filteredIcons = {}; _.each( include, function( iconKey ) { filteredIcons[ iconKey ] = icons[ iconKey ]; } ); this.model.set( 'icons', filteredIcons ); return; } if ( exclude ) { _.each( exclude, function( iconKey ) { delete icons[ iconKey ]; } ); } }, iconsList: function( icon ) { if ( ! icon.id ) { return icon.text; } return Backbone.$( '<span><i class="' + icon.id + '"></i> ' + icon.text + '</span>' ); }, onReady: function() { this.ui.select.select2( { allowClear: true, templateResult: _.bind( this.iconsList, this ), templateSelection: _.bind( this.iconsList, this ) } ); } } );
ControlFontItemView = ControlBaseItemView.extend( { ui: function() { var ui = ControlBaseItemView.prototype.ui.apply( this, arguments ); ui.fontSelect = '.elementor-control-font-family'; return ui; }, onReady: function() { this.ui.fontSelect.select2( { dir: elementor.config.is_rtl ? 'rtl' : 'ltr' } ); }, onBeforeDestroy: function() { if ( this.ui.fontSelect.data( 'select2' ) ) { this.ui.fontSelect.select2( 'destroy' ); } this.$el.remove(); }, templateHelpers: function() { var helpers = ControlBaseItemView.prototype.templateHelpers.apply( this, arguments ); helpers.getFontsByGroups = _.bind( function( groups ) { return _.pick( this.model.get( 'fonts' ), function( fontType, fontName ) { return _.isArray( groups ) ? _.contains( groups, fontType ) : fontType === groups; } ); }, this ); return helpers; } } );
var ControlBaseItemView = require( 'elementor-views/controls/base' ), ControlTabItemView; ControlTabItemView = ControlBaseItemView.extend( { triggers: { 'click': 'control:tab:clicked' } } ); module.exports = ControlTabItemView;