/wp-content/plugins/siteorigin-panels/js/siteorigin-panels-24.js
JavaScript | 1845 lines | 1246 code | 327 blank | 272 comment | 149 complexity | 3d6385e1e6f0502ba112b2d995ad6f43 MD5 | raw file
- (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
- var panels = window.panels;
- module.exports = Backbone.Collection.extend( {
- model: panels.model.cell,
- initialize: function () {
- },
- /**
- * Get the total weight for the cells in this collection.
- * @returns {number}
- */
- totalWeight: function () {
- var totalWeight = 0;
- this.each( function ( cell ) {
- totalWeight += cell.get( 'weight' );
- } );
- return totalWeight;
- },
- visualSortComparator: function ( item ) {
- if ( ! _.isNull( item.indexes ) ) {
- return item.indexes.builder;
- } else {
- return null;
- }
- },
- visualSort: function(){
- var oldComparator = this.comparator;
- this.comparator = this.visualSortComparator;
- this.sort();
- this.comparator = oldComparator;
- }
- } );
- },{}],2:[function(require,module,exports){
- var panels = window.panels;
- module.exports = Backbone.Collection.extend( {
- model: panels.model.historyEntry,
- /**
- * The builder model
- */
- builder: null,
- /**
- * The maximum number of items in the history
- */
- maxSize: 12,
- initialize: function () {
- this.on( 'add', this.onAddEntry, this );
- },
- /**
- * Add an entry to the collection.
- *
- * @param text The text that defines the action taken to get to this
- * @param data
- */
- addEntry: function ( text, data ) {
- if ( _.isEmpty( data ) ) {
- data = this.builder.getPanelsData();
- }
- var entry = new panels.model.historyEntry( {
- text: text,
- data: JSON.stringify( data ),
- time: parseInt( new Date().getTime() / 1000 ),
- collection: this
- } );
- this.add( entry );
- },
- /**
- * Resize the collection so it's not bigger than this.maxSize
- */
- onAddEntry: function ( entry ) {
- if ( this.models.length > 1 ) {
- var lastEntry = this.at( this.models.length - 2 );
- if (
- (
- entry.get( 'text' ) === lastEntry.get( 'text' ) && entry.get( 'time' ) - lastEntry.get( 'time' ) < 15
- ) ||
- (
- entry.get( 'data' ) === lastEntry.get( 'data' )
- )
- ) {
- // If both entries have the same text and are within 20 seconds of each other, or have the same data, then remove most recent
- this.remove( entry );
- lastEntry.set( 'count', lastEntry.get( 'count' ) + 1 );
- }
- }
- // Make sure that there are not to many entries in this collection
- while ( this.models.length > this.maxSize ) {
- this.shift();
- }
- }
- } );
- },{}],3:[function(require,module,exports){
- var panels = window.panels;
- module.exports = Backbone.Collection.extend( {
- model: panels.model.row,
- /**
- * Destroy all the rows in this collection
- */
- empty: function () {
- var model;
- do {
- model = this.collection.first();
- if ( ! model ) {
- break;
- }
- model.destroy();
- } while ( true );
- },
- visualSortComparator: function ( item ) {
- if ( ! _.isNull( item.indexes ) ) {
- return item.indexes.builder;
- } else {
- return null;
- }
- },
- visualSort: function(){
- var oldComparator = this.comparator;
- this.comparator = this.visualSortComparator;
- this.sort();
- this.comparator = oldComparator;
- }
- } );
- },{}],4:[function(require,module,exports){
- var panels = window.panels;
- module.exports = Backbone.Collection.extend( {
- model: panels.model.widget,
- initialize: function () {
- },
- visualSortComparator: function ( item ) {
- if ( ! _.isNull( item.indexes ) ) {
- return item.indexes.builder;
- } else {
- return null;
- }
- },
- visualSort: function(){
- var oldComparator = this.comparator;
- this.comparator = this.visualSortComparator;
- this.sort();
- this.comparator = oldComparator;
- }
- } );
- },{}],5:[function(require,module,exports){
- var panels = window.panels, $ = jQuery;
- module.exports = panels.view.dialog.extend( {
- dialogClass: 'so-panels-dialog-add-builder',
- render: function () {
- // Render the dialog and attach it to the builder interface
- this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-builder' ).html(), {} ) );
- this.$( '.so-content .siteorigin-panels-builder' ).append( this.builder.$el );
- },
- initializeDialog: function () {
- var thisView = this;
- this.once( 'open_dialog_complete', function () {
- thisView.builder.initSortable();
- } );
- this.on( 'open_dialog_complete', function () {
- thisView.builder.trigger( 'builder_resize' );
- } );
- }
- } );
- },{}],6:[function(require,module,exports){
- var panels = window.panels, $ = jQuery;
- module.exports = panels.view.dialog.extend( {
- historyEntryTemplate: _.template( $( '#siteorigin-panels-dialog-history-entry' ).html().panelsProcessTemplate() ),
- entries: {},
- currentEntry: null,
- revertEntry: null,
- selectedEntry: null,
- previewScrollTop: null,
- dialogClass: 'so-panels-dialog-history',
- events: {
- 'click .so-close': 'closeDialog',
- 'click .so-restore': 'restoreSelectedEntry'
- },
- initializeDialog: function () {
- this.entries = new panels.collection.historyEntries();
- this.on( 'open_dialog', this.setCurrentEntry, this );
- this.on( 'open_dialog', this.renderHistoryEntries, this );
- },
- render: function () {
- var thisView = this;
- // Render the dialog and attach it to the builder interface
- this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-history' ).html(), {} ) );
- this.$( 'iframe.siteorigin-panels-history-iframe' ).load( function () {
- var $$ = $( this );
- $$.show();
- $$.contents().scrollTop( thisView.previewScrollTop );
- } );
- },
- /**
- * Set the original entry. This should be set when creating the dialog.
- *
- * @param {panels.model.builder} builder
- */
- setRevertEntry: function ( builder ) {
- this.revertEntry = new panels.model.historyEntry( {
- data: JSON.stringify( builder.getPanelsData() ),
- time: parseInt( new Date().getTime() / 1000 )
- } );
- },
- /**
- * This is triggered when the dialog is opened.
- */
- setCurrentEntry: function () {
- this.currentEntry = new panels.model.historyEntry( {
- data: JSON.stringify( this.builder.model.getPanelsData() ),
- time: parseInt( new Date().getTime() / 1000 )
- } );
- this.selectedEntry = this.currentEntry;
- this.previewEntry( this.currentEntry );
- this.$( '.so-buttons .so-restore' ).addClass( 'disabled' );
- },
- /**
- * Render the history entries in the sidebar
- */
- renderHistoryEntries: function () {
- // Set up an interval that will display the time since every 10 seconds
- var thisView = this;
- var c = this.$( '.history-entries' ).empty();
- if ( this.currentEntry.get( 'data' ) !== this.revertEntry.get( 'data' ) || ! _.isEmpty( this.entries.models ) ) {
- $( this.historyEntryTemplate( {title: panelsOptions.loc.history.revert, count: 1} ) )
- .data( 'historyEntry', this.revertEntry )
- .prependTo( c );
- }
- // Now load all the entries in this.entries
- this.entries.each( function ( entry ) {
- var html = thisView.historyEntryTemplate( {
- title: panelsOptions.loc.history[entry.get( 'text' )],
- count: entry.get( 'count' )
- } );
- $( html )
- .data( 'historyEntry', entry )
- .prependTo( c );
- } );
- $( this.historyEntryTemplate( {title: panelsOptions.loc.history['current'], count: 1} ) )
- .data( 'historyEntry', this.currentEntry )
- .addClass( 'so-selected' )
- .prependTo( c );
- // Handle loading and selecting
- c.find( '.history-entry' ).click( function () {
- var $$ = jQuery( this );
- c.find( '.history-entry' ).not( $$ ).removeClass( 'so-selected' );
- $$.addClass( 'so-selected' );
- var entry = $$.data( 'historyEntry' );
- thisView.selectedEntry = entry;
- if ( thisView.selectedEntry.cid !== thisView.currentEntry.cid ) {
- thisView.$( '.so-buttons .so-restore' ).removeClass( 'disabled' );
- } else {
- thisView.$( '.so-buttons .so-restore' ).addClass( 'disabled' );
- }
- thisView.previewEntry( entry );
- } );
- this.updateEntryTimes();
- },
- /**
- * Preview an entry
- *
- * @param entry
- */
- previewEntry: function ( entry ) {
- var iframe = this.$( 'iframe.siteorigin-panels-history-iframe' );
- iframe.hide();
- this.previewScrollTop = iframe.contents().scrollTop();
- this.$( 'form.history-form input[name="live_editor_panels_data"]' ).val( entry.get( 'data' ) );
- this.$( 'form.history-form' ).submit();
- },
- /**
- * Restore the current entry
- */
- restoreSelectedEntry: function () {
- if ( this.$( '.so-buttons .so-restore' ).hasClass( 'disabled' ) ) {
- return false;
- }
- if ( this.currentEntry.get( 'data' ) === this.selectedEntry.get( 'data' ) ) {
- this.closeDialog();
- return false;
- }
- // Add an entry for this restore event
- if ( this.selectedEntry.get( 'text' ) !== 'restore' ) {
- this.builder.addHistoryEntry( 'restore', this.builder.model.getPanelsData() );
- }
- this.builder.model.loadPanelsData( JSON.parse( this.selectedEntry.get( 'data' ) ) );
- this.closeDialog();
- return false;
- },
- /**
- * Update the entry times for the list of entries down the side
- */
- updateEntryTimes: function () {
- var thisView = this;
- this.$( '.history-entries .history-entry' ).each( function () {
- var $$ = jQuery( this );
- var time = $$.find( '.timesince' );
- var entry = $$.data( 'historyEntry' );
- time.html( thisView.timeSince( entry.get( 'time' ) ) );
- } );
- },
- /**
- * Gets the time since as a nice string.
- *
- * @param date
- */
- timeSince: function ( time ) {
- var diff = parseInt( new Date().getTime() / 1000 ) - time;
- var parts = [];
- var interval;
- // There are 3600 seconds in an hour
- if ( diff > 3600 ) {
- interval = Math.floor( diff / 3600 );
- if ( interval === 1 ) {
- parts.push( panelsOptions.loc.time.hour.replace( '%d', interval ) );
- } else {
- parts.push( panelsOptions.loc.time.hours.replace( '%d', interval ) );
- }
- diff -= interval * 3600;
- }
- // There are 60 seconds in a minute
- if ( diff > 60 ) {
- interval = Math.floor( diff / 60 );
- if ( interval === 1 ) {
- parts.push( panelsOptions.loc.time.minute.replace( '%d', interval ) );
- } else {
- parts.push( panelsOptions.loc.time.minutes.replace( '%d', interval ) );
- }
- diff -= interval * 60;
- }
- if ( diff > 0 ) {
- if ( diff === 1 ) {
- parts.push( panelsOptions.loc.time.second.replace( '%d', diff ) );
- } else {
- parts.push( panelsOptions.loc.time.seconds.replace( '%d', diff ) );
- }
- }
- // Return the amount of time ago
- return _.isEmpty( parts ) ? panelsOptions.loc.time.now : panelsOptions.loc.time.ago.replace( '%s', parts.slice( 0, 2 ).join( ', ' ) );
- }
- } );
- },{}],7:[function(require,module,exports){
- var panels = window.panels, $ = jQuery;
- module.exports = panels.view.dialog.extend( {
- directoryTemplate: _.template( $( '#siteorigin-panels-directory-items' ).html().panelsProcessTemplate() ),
- builder: null,
- dialogClass: 'so-panels-dialog-prebuilt-layouts',
- layoutCache: {},
- currentTab: false,
- directoryPage: 1,
- events: {
- 'click .so-close': 'closeDialog',
- 'click .so-sidebar-tabs li a': 'tabClickHandler',
- 'click .so-content .layout': 'layoutClickHandler',
- 'keyup .so-sidebar-search': 'searchHandler',
- // The directory items
- 'click .so-screenshot, .so-title': 'directoryItemClickHandler'
- },
- /**
- * Initialize the prebuilt dialog.
- */
- initializeDialog: function () {
- var thisView = this;
- this.on( 'open_dialog', function () {
- thisView.$( '.so-sidebar-tabs li a' ).first().click();
- thisView.$( '.so-status' ).removeClass( 'so-panels-loading' );
- } );
- this.on( 'button_click', this.toolbarButtonClick, this );
- },
- /**
- * Render the prebuilt layouts dialog
- */
- render: function () {
- this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-prebuilt' ).html(), {} ) );
- this.initToolbar();
- },
- /**
- *
- * @param e
- * @return {boolean}
- */
- tabClickHandler: function ( e ) {
- e.preventDefault();
- // Reset selected item state when changing tabs
- this.selectedLayoutItem = null;
- this.uploadedLayout = null;
- this.updateButtonState( false );
- this.$( '.so-sidebar-tabs li' ).removeClass( 'tab-active' );
- var $$ = $( e.target );
- var tab = $$.attr( 'href' ).split( '#' )[1];
- $$.parent().addClass( 'tab-active' );
- var thisView = this;
- // Empty everything
- this.$( '.so-content' ).empty();
- thisView.currentTab = tab;
- if ( tab == 'import' ) {
- this.displayImportExport();
- } else {
- this.displayLayoutDirectory( '', 1, tab );
- }
- thisView.$( '.so-sidebar-search' ).val( '' );
- },
- /**
- * Display and setup the import/export form
- */
- displayImportExport: function () {
- var c = this.$( '.so-content' ).empty().removeClass( 'so-panels-loading' );
- c.html( $( '#siteorigin-panels-dialog-prebuilt-importexport' ).html() );
- var thisView = this;
- var uploadUi = thisView.$( '.import-upload-ui' ).hide();
- // Create the uploader
- var uploader = new plupload.Uploader( {
- runtimes: 'html5,silverlight,flash,html4',
- browse_button: uploadUi.find( '.file-browse-button' ).get( 0 ),
- container: uploadUi.get( 0 ),
- drop_element: uploadUi.find( '.drag-upload-area' ).get( 0 ),
- file_data_name: 'panels_import_data',
- multiple_queues: false,
- max_file_size: panelsOptions.plupload.max_file_size,
- url: panelsOptions.plupload.url,
- flash_swf_url: panelsOptions.plupload.flash_swf_url,
- silverlight_xap_url: panelsOptions.plupload.silverlight_xap_url,
- filters: [
- {title: panelsOptions.plupload.filter_title, extensions: 'json'}
- ],
- multipart_params: {
- action: 'so_panels_import_layout'
- },
- init: {
- PostInit: function ( uploader ) {
- if ( uploader.features.dragdrop ) {
- uploadUi.addClass( 'has-drag-drop' );
- }
- uploadUi.show().find( '.progress-precent' ).css( 'width', '0%' );
- },
- FilesAdded: function ( uploader ) {
- uploadUi.find( '.file-browse-button' ).blur();
- uploadUi.find( '.drag-upload-area' ).removeClass( 'file-dragover' );
- uploadUi.find( '.progress-bar' ).fadeIn( 'fast' );
- thisView.$( '.js-so-selected-file' ).text( panelsOptions.loc.prebuilt_loading );
- uploader.start();
- },
- UploadProgress: function ( uploader, file ) {
- uploadUi.find( '.progress-precent' ).css( 'width', file.percent + '%' );
- },
- FileUploaded: function ( uploader, file, response ) {
- var layout = JSON.parse( response.response );
- if ( ! _.isUndefined( layout.widgets ) ) {
- thisView.uploadedLayout = layout;
- uploadUi.find( '.progress-bar' ).hide();
- thisView.$( '.js-so-selected-file' ).text(
- panelsOptions.loc.ready_to_insert.replace( '%s', file.name )
- );
- thisView.updateButtonState( true );
- } else {
- alert( panelsOptions.plupload.error_message );
- }
- },
- Error: function () {
- alert( panelsOptions.plupload.error_message );
- }
- }
- } );
- uploader.init();
- // This is
- uploadUi.find( '.drag-upload-area' )
- .on( 'dragover', function () {
- $( this ).addClass( 'file-dragover' );
- } )
- .on( 'dragleave', function () {
- $( this ).removeClass( 'file-dragover' );
- } );
- // Handle exporting the file
- c.find( '.so-export' ).submit( function ( e ) {
- var $$ = $( this );
- $$.find( 'input[name="panels_export_data"]' ).val( JSON.stringify( thisView.builder.model.getPanelsData() ) );
- } );
- },
- /**
- * Display the layout directory tab.
- *
- * @param query
- */
- displayLayoutDirectory: function ( search, page, type ) {
- var thisView = this;
- var c = this.$( '.so-content' ).empty().addClass( 'so-panels-loading' );
- if ( search === undefined ) {
- search = '';
- }
- if ( page === undefined ) {
- page = 1;
- }
- if ( type === undefined ) {
- type = 'directory';
- }
- if ( type === 'directory' && ! panelsOptions.directory_enabled ) {
- // Display the button to enable the prebuilt layout
- c.removeClass( 'so-panels-loading' ).html( $( '#siteorigin-panels-directory-enable' ).html() );
- c.find( '.so-panels-enable-directory' ).click( function ( e ) {
- e.preventDefault();
- // Sent the query to enable the directory, then enable the directory
- $.get(
- panelsOptions.ajaxurl,
- {action: 'so_panels_directory_enable'},
- function () {
- }
- );
- // Enable the layout directory
- panelsOptions.directory_enabled = true;
- c.addClass( 'so-panels-loading' );
- thisView.displayLayoutDirectory( search, page );
- } );
- return;
- }
- // Get all the items for the current query
- $.get(
- panelsOptions.ajaxurl,
- {
- action: 'so_panels_layouts_query',
- search: search,
- page: page,
- type: type,
- },
- function ( data ) {
- // Skip this if we're no longer viewing the layout directory
- if ( thisView.currentTab !== type ) {
- return;
- }
- // Add the directory items
- c.removeClass( 'so-panels-loading' ).html( thisView.directoryTemplate( data ) );
- // Lets setup the next and previous buttons
- var prev = c.find( '.so-previous' ), next = c.find( '.so-next' );
- if ( page <= 1 ) {
- prev.addClass( 'button-disabled' );
- } else {
- prev.click( function ( e ) {
- e.preventDefault();
- thisView.displayLayoutDirectory( search, page - 1, thisView.currentTab );
- } );
- }
- if ( page === data.max_num_pages || data.max_num_pages === 0 ) {
- next.addClass( 'button-disabled' );
- } else {
- next.click( function ( e ) {
- e.preventDefault();
- thisView.displayLayoutDirectory( search, page + 1, thisView.currentTab );
- } );
- }
- // Handle nice preloading of the screenshots
- c.find( '.so-screenshot' ).each( function () {
- var $$ = $( this ), $a = $$.find( '.so-screenshot-wrapper' );
- $a.css( 'height', (
- $a.width() / 4 * 3
- ) + 'px' ).addClass( 'so-loading' );
- if ( $$.data( 'src' ) !== '' ) {
- // Set the initial height
- var $img = $( '<img/>' ).attr( 'src', $$.data( 'src' ) ).load( function () {
- $a.removeClass( 'so-loading' ).css( 'height', 'auto' );
- $img.appendTo( $a ).hide().fadeIn( 'fast' );
- } );
- } else {
- $( '<img/>' ).attr( 'src', panelsOptions.prebuiltDefaultScreenshot ).appendTo( $a ).hide().fadeIn( 'fast' );
- }
- } );
- // Set the title
- c.find( '.so-directory-browse' ).html( data.title );
- },
- 'json'
- );
- },
- /**
- * Set the selected state for the clicked layout directory item and remove previously selected item.
- * Enable the toolbar buttons.
- */
- directoryItemClickHandler: function ( e ) {
- var $directoryItem = this.$( e.target ).closest( '.so-directory-item' );
- this.$( '.so-directory-items' ).find( '.selected' ).removeClass( 'selected' );
- $directoryItem.addClass( 'selected' );
- this.selectedLayoutItem = {lid: $directoryItem.data( 'layout-id' ), type: $directoryItem.data( 'layout-type' )};
- this.updateButtonState( true );
- },
- /**
- * Load a particular layout into the builder.
- *
- * @param id
- */
- toolbarButtonClick: function ( $button ) {
- if ( ! this.canAddLayout() ) {
- return false;
- }
- var position = $button.data( 'value' );
- if ( _.isUndefined( position ) ) {
- return false;
- }
- this.updateButtonState( false );
- if ( $button.hasClass( 'so-needs-confirm' ) && ! $button.hasClass( 'so-confirmed' ) ) {
- this.updateButtonState( true );
- if ( $button.hasClass( 'so-confirming' ) ) {
- return;
- }
- $button.addClass( 'so-confirming' );
- var originalText = $button.html();
- $button.html( '<span class="dashicons dashicons-yes"></span>' + $button.data( 'confirm' ) );
- setTimeout( function () {
- $button.removeClass( 'so-confirmed' ).html( originalText );
- }, 2500 );
- setTimeout( function () {
- $button.removeClass( 'so-confirming' );
- $button.addClass( 'so-confirmed' );
- }, 200 );
- return false;
- }
- this.addingLayout = true;
- if ( this.currentTab === 'import' ) {
- this.addLayoutToBuilder( this.uploadedLayout, position );
- } else {
- this.loadSelectedLayout().then( function ( layout ) {
- this.addLayoutToBuilder( layout, position );
- }.bind( this ) );
- }
- },
- canAddLayout: function () {
- return (
- this.selectedLayoutItem || this.uploadedLayout
- ) && ! this.addingLayout;
- },
- /**
- * Load the layout according to selectedLayoutItem.
- */
- loadSelectedLayout: function () {
- this.setStatusMessage( panelsOptions.loc.prebuilt_loading, true );
- var args = _.extend( this.selectedLayoutItem, {action: 'so_panels_get_layout'} );
- var deferredLayout = new $.Deferred();
- $.get(
- panelsOptions.ajaxurl,
- args,
- function ( layout ) {
- if ( layout.error !== undefined ) {
- // There was an error
- alert( layout.error );
- deferredLayout.reject( layout );
- } else {
- this.setStatusMessage( '', false );
- deferredLayout.resolve( layout );
- }
- }.bind( this )
- );
- return deferredLayout.promise();
- },
- /**
- * Handle an update to the search
- */
- searchHandler: function ( e ) {
- if ( e.keyCode === 13 ) {
- this.displayLayoutDirectory( $( e.currentTarget ).val(), 1, this.currentTab );
- }
- },
- /**
- * Attempt to set the 'Insert' button's state according to the `enabled` argument, also checking whether the
- * requirements for inserting a layout have valid values.
- */
- updateButtonState: function ( enabled ) {
- enabled = enabled && (
- this.selectedLayoutItem || this.uploadedLayout
- );
- var $button = this.$( '.so-import-layout' );
- $button.prop( "disabled", ! enabled );
- if ( enabled ) {
- $button.removeClass( 'disabled' );
- } else {
- $button.addClass( 'disabled' );
- }
- },
- addLayoutToBuilder: function ( layout, position ) {
- this.builder.addHistoryEntry( 'prebuilt_loaded' );
- this.builder.model.loadPanelsData( layout, position );
- this.addingLayout = false;
- this.closeDialog();
- }
- } );
- },{}],8:[function(require,module,exports){
- var panels = window.panels, $ = jQuery;
- module.exports = panels.view.dialog.extend( {
- cellPreviewTemplate: _.template( $( '#siteorigin-panels-dialog-row-cell-preview' ).html().panelsProcessTemplate() ),
- events: {
- 'click .so-close': 'closeDialog',
- // Toolbar buttons
- 'click .so-toolbar .so-save': 'saveHandler',
- 'click .so-toolbar .so-insert': 'insertHandler',
- 'click .so-toolbar .so-delete': 'deleteHandler',
- 'click .so-toolbar .so-duplicate': 'duplicateHandler',
- // Changing the row
- 'change .row-set-form > *': 'setCellsFromForm',
- 'click .row-set-form button.set-row': 'setCellsFromForm'
- },
- dialogClass: 'so-panels-dialog-row-edit',
- styleType: 'row',
- dialogType: 'edit',
- /**
- * The current settings, not yet saved to the model
- */
- row: {
- // This is just the cell weights, cell content is not edited by this dialog
- cells: [],
- // The style settings of the row
- style: {}
- },
- initializeDialog: function () {
- this.on( 'open_dialog', function () {
- if ( ! _.isUndefined( this.model ) && ! _.isEmpty( this.model.cells ) ) {
- this.setRowModel( this.model );
- } else {
- this.setRowModel( null );
- }
- this.regenerateRowPreview();
- }, this );
- // This is the default row layout
- this.row = {
- cells: [0.5, 0.5],
- style: {}
- };
- // Refresh panels data after both dialog form components are loaded
- this.dialogFormsLoaded = 0;
- var thisView = this;
- this.on( 'form_loaded styles_loaded', function () {
- this.dialogFormsLoaded ++;
- if ( this.dialogFormsLoaded === 2 ) {
- thisView.updateModel( {
- refreshArgs: {
- silent: true
- }
- } );
- }
- } );
- },
- /**
- *
- * @param dialogType Either "edit" or "create"
- */
- setRowDialogType: function ( dialogType ) {
- this.dialogType = dialogType;
- },
- /**
- * Render the new row dialog
- */
- render: function ( dialogType ) {
- this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-row' ).html(), {dialogType: this.dialogType} ) );
- if ( this.dialogType === 'edit' ) {
- // Now we need to attach the style window
- this.styles = new panels.view.styles();
- this.styles.model = this.model;
- this.styles.render( 'row', $( '#post_ID' ).val(), {
- builderType: this.builder.config.builderType,
- dialog: this
- } );
- if( ! this.builder.supports( 'addRow' ) ) {
- this.$( '.so-buttons .so-duplicate' ).remove();
- }
- if( ! this.builder.supports( 'deleteRow' ) ) {
- this.$( '.so-buttons .so-delete' ).remove();
- }
- var $rightSidebar = this.$( '.so-sidebar.so-right-sidebar' );
- this.styles.attach( $rightSidebar );
- // Handle the loading class
- this.styles.on( 'styles_loaded', function ( hasStyles ) {
- // If we have styles remove the loading spinner, else remove the whole empty sidebar.
- if ( hasStyles ) {
- $rightSidebar.removeClass( 'so-panels-loading' );
- } else {
- $rightSidebar.closest( '.so-panels-dialog' ).removeClass( 'so-panels-dialog-has-right-sidebar' );
- $rightSidebar.remove();
- }
- }, this );
- $rightSidebar.addClass( 'so-panels-loading' );
- }
- if ( ! _.isUndefined( this.model ) ) {
- // Set the initial value of the
- this.$( 'input.so-row-field' ).val( this.model.cells.length );
- }
- var thisView = this;
- this.$( 'input.so-row-field' ).keyup( function () {
- $( this ).trigger( 'change' );
- } );
- return this;
- },
- /**
- * Set the row model we'll be using for this dialog.
- *
- * @param model
- */
- setRowModel: function ( model ) {
- this.model = model;
- if ( _.isEmpty( this.model ) ) {
- return this;
- }
- // Set the rows to be a copy of the model
- this.row = {
- cells: this.model.cells.map( function ( cell ) {
- return cell.get( 'weight' );
- } ),
- style: {}
- };
- // Set the initial value of the cell field.
- this.$( 'input.so-row-field' ).val( this.model.cells.length );
- return this;
- },
- /**
- * Regenerate the row preview and resizing interface.
- */
- regenerateRowPreview: function () {
- var thisDialog = this;
- var rowPreview = this.$( '.row-preview' );
- rowPreview.empty();
- var timeout;
- // Represent the cells
- _.each( this.row.cells, function ( cell, i ) {
- var newCell = $( this.cellPreviewTemplate( {weight: cell} ) );
- rowPreview.append( newCell );
- var prevCell = newCell.prev();
- var handle;
- if ( prevCell.length ) {
- handle = $( '<div class="resize-handle"></div>' );
- handle
- .appendTo( newCell )
- .dblclick( function () {
- var t = thisDialog.row.cells[i] + thisDialog.row.cells[i - 1];
- thisDialog.row.cells[i] = thisDialog.row.cells[i - 1] = t / 2;
- thisDialog.scaleRowWidths();
- } );
- handle.draggable( {
- axis: 'x',
- containment: rowPreview,
- start: function ( e, ui ) {
- // Create the clone for the current cell
- var newCellClone = newCell.clone().appendTo( ui.helper ).css( {
- position: 'absolute',
- top: '0',
- width: newCell.outerWidth(),
- left: 6,
- height: newCell.outerHeight()
- } );
- newCellClone.find( '.resize-handle' ).remove();
- // Create the clone for the previous cell
- var prevCellClone = prevCell.clone().appendTo( ui.helper ).css( {
- position: 'absolute',
- top: '0',
- width: prevCell.outerWidth(),
- right: 6,
- height: prevCell.outerHeight()
- } );
- prevCellClone.find( '.resize-handle' ).remove();
- $( this ).data( {
- 'newCellClone': newCellClone,
- 'prevCellClone': prevCellClone
- } );
- // Hide the
- newCell.find( '> .preview-cell-in' ).css( 'visibility', 'hidden' );
- prevCell.find( '> .preview-cell-in' ).css( 'visibility', 'hidden' );
- },
- drag: function ( e, ui ) {
- // Calculate the new cell and previous cell widths as a percent
- var ncw = thisDialog.row.cells[i] - (
- (
- ui.position.left + 6
- ) / rowPreview.width()
- );
- var pcw = thisDialog.row.cells[i - 1] + (
- (
- ui.position.left + 6
- ) / rowPreview.width()
- );
- var helperLeft = ui.helper.offset().left - rowPreview.offset().left - 6;
- $( this ).data( 'newCellClone' ).css( 'width', rowPreview.width() * ncw )
- .find( '.preview-cell-weight' ).html( Math.round( ncw * 1000 ) / 10 );
- $( this ).data( 'prevCellClone' ).css( 'width', rowPreview.width() * pcw )
- .find( '.preview-cell-weight' ).html( Math.round( pcw * 1000 ) / 10 );
- },
- stop: function ( e, ui ) {
- // Remove the clones
- $( this ).data( 'newCellClone' ).remove();
- $( this ).data( 'prevCellClone' ).remove();
- // Reshow the main cells
- newCell.find( '.preview-cell-in' ).css( 'visibility', 'visible' );
- prevCell.find( '.preview-cell-in' ).css( 'visibility', 'visible' );
- // Calculate the new cell weights
- var offset = ui.position.left + 6;
- var percent = offset / rowPreview.width();
- // Ignore this if any of the cells are below 2% in width.
- if ( thisDialog.row.cells[i] - percent > 0.02 && thisDialog.row.cells[i - 1] + percent > 0.02 ) {
- thisDialog.row.cells[i] -= percent;
- thisDialog.row.cells[i - 1] += percent;
- }
- thisDialog.scaleRowWidths();
- ui.helper.css( 'left', - 6 );
- }
- } );
- }
- // Make this row weight click editable
- newCell.find( '.preview-cell-weight' ).click( function ( ci ) {
- // Disable the draggable while entering values
- thisDialog.$( '.resize-handle' ).css( 'pointer-event', 'none' ).draggable( 'disable' );
- rowPreview.find( '.preview-cell-weight' ).each( function () {
- var $$ = jQuery( this ).hide();
- $( '<input type="text" class="preview-cell-weight-input no-user-interacted" />' )
- .val( parseFloat( $$.html() ) ).insertAfter( $$ )
- .focus( function () {
- clearTimeout( timeout );
- } )
- .keyup( function ( e ) {
- if ( e.keyCode !== 9 ) {
- // Only register the interaction if the user didn't press tab
- $( this ).removeClass( 'no-user-interacted' );
- }
- // Enter is clicked
- if ( e.keyCode === 13 ) {
- e.preventDefault();
- $( this ).blur();
- }
- } )
- .keydown( function ( e ) {
- if ( e.keyCode === 9 ) {
- e.preventDefault();
- // Tab will always cycle around the row inputs
- var inputs = rowPreview.find( '.preview-cell-weight-input' );
- var i = inputs.index( $( this ) );
- if ( i === inputs.length - 1 ) {
- inputs.eq( 0 ).focus().select();
- } else {
- inputs.eq( i + 1 ).focus().select();
- }
- }
- } )
- .blur( function () {
- rowPreview.find( '.preview-cell-weight-input' ).each( function ( i, el ) {
- if ( isNaN( parseFloat( $( el ).val() ) ) ) {
- $( el ).val( Math.floor( thisDialog.row.cells[i] * 1000 ) / 10 );
- }
- } );
- timeout = setTimeout( function () {
- // If there are no weight inputs, then skip this
- if ( rowPreview.find( '.preview-cell-weight-input' ).legnth === 0 ) {
- return false;
- }
- // Go through all the inputs
- var rowWeights = [],
- rowChanged = [],
- changedSum = 0,
- unchangedSum = 0;
- rowPreview.find( '.preview-cell-weight-input' ).each( function ( i, el ) {
- var val = parseFloat( $( el ).val() );
- if ( isNaN( val ) ) {
- val = 1 / thisDialog.row.cells.length;
- } else {
- val = Math.round( val * 10 ) / 1000;
- }
- // Check within 3 decimal points
- var changed = ! $( el ).hasClass( 'no-user-interacted' );
- rowWeights.push( val );
- rowChanged.push( changed );
- if ( changed ) {
- changedSum += val;
- } else {
- unchangedSum += val;
- }
- } );
- if ( changedSum > 0 && unchangedSum > 0 && (
- 1 - changedSum
- ) > 0 ) {
- // Balance out the unchanged rows to occupy the weight left over by the changed sum
- for ( var i = 0; i < rowWeights.length; i ++ ) {
- if ( ! rowChanged[i] ) {
- rowWeights[i] = (
- rowWeights[i] / unchangedSum
- ) * (
- 1 - changedSum
- );
- }
- }
- }
- // Last check to ensure total weight is 1
- var sum = _.reduce( rowWeights, function ( memo, num ) {
- return memo + num;
- } );
- rowWeights = rowWeights.map( function ( w ) {
- return w / sum;
- } );
- // Set the new cell weights and regenerate the preview.
- if ( Math.min.apply( Math, rowWeights ) > 0.01 ) {
- thisDialog.row.cells = rowWeights;
- }
- // Now lets animate the cells into their new widths
- rowPreview.find( '.preview-cell' ).each( function ( i, el ) {
- $( el ).animate( {'width': Math.round( thisDialog.row.cells[i] * 1000 ) / 10 + "%"}, 250 );
- $( el ).find( '.preview-cell-weight-input' ).val( Math.round( thisDialog.row.cells[i] * 1000 ) / 10 );
- } );
- // So the draggable handle is not hidden.
- rowPreview.find( '.preview-cell' ).css( 'overflow', 'visible' );
- setTimeout( function () {
- thisDialog.regenerateRowPreview();
- }, 260 );
- }, 100 );
- } )
- .click( function () {
- $( this ).select();
- } );
- } );
- $( this ).siblings( '.preview-cell-weight-input' ).select();
- } );
- }, this );
- this.trigger( 'form_loaded', this );
- },
- /**
- * Visually scale the row widths based on the cell weights
- */
- scaleRowWidths: function () {
- var thisDialog = this;
- this.$( '.row-preview .preview-cell' ).each( function ( i, el ) {
- $( el )
- .css( 'width', thisDialog.row.cells[i] * 100 + "%" )
- .find( '.preview-cell-weight' ).html( Math.round( thisDialog.row.cells[i] * 1000 ) / 10 );
- } );
- },
- /**
- * Get the weights from the
- */
- setCellsFromForm: function () {
- try {
- var f = {
- 'cells': parseInt( this.$( '.row-set-form input[name="cells"]' ).val() ),
- 'ratio': parseFloat( this.$( '.row-set-form select[name="ratio"]' ).val() ),
- 'direction': this.$( '.row-set-form select[name="ratio_direction"]' ).val()
- };
- if ( _.isNaN( f.cells ) ) {
- f.cells = 1;
- }
- if ( isNaN( f.ratio ) ) {
- f.ratio = 1;
- }
- if ( f.cells < 1 ) {
- f.cells = 1;
- this.$( '.row-set-form input[name="cells"]' ).val( f.cells );
- }
- else if ( f.cells > 10 ) {
- f.cells = 10;
- this.$( '.row-set-form input[name="cells"]' ).val( f.cells );
- }
- this.$( '.row-set-form input[name="ratio"]' ).val( f.ratio );
- var cells = [];
- var cellCountChanged = (
- this.row.cells.length !== f.cells
- );
- // Now, lets create some cells
- var currentWeight = 1;
- for ( var i = 0; i < f.cells; i ++ ) {
- cells.push( currentWeight );
- currentWeight *= f.ratio;
- }
- // Now lets make sure that the row weights add up to 1
- var totalRowWeight = _.reduce( cells, function ( memo, weight ) {
- return memo + weight;
- } );
- cells = _.map( cells, function ( cell ) {
- return cell / totalRowWeight;
- } );
- // Don't return cells that are too small
- cells = _.filter( cells, function ( cell ) {
- return cell > 0.01;
- } );
- if ( f.direction === 'left' ) {
- cells = cells.reverse();
- }
- this.row.cells = cells;
- if ( cellCountChanged ) {
- this.regenerateRowPreview();
- } else {
- var thisDialog = this;
- // Now lets animate the cells into their new widths
- this.$( '.preview-cell' ).each( function ( i, el ) {
- $( el ).animate( {'width': Math.round( thisDialog.row.cells[i] * 1000 ) / 10 + "%"}, 250 );
- $( el ).find( '.preview-cell-weight' ).html( Math.round( thisDialog.row.cells[i] * 1000 ) / 10 );
- } );
- // So the draggable handle is not hidden.
- this.$( '.preview-cell' ).css( 'overflow', 'visible' );
- setTimeout( function () {
- thisDialog.regenerateRowPreview();
- }, 260 );
- }
- }
- catch (err) {
- console.log( 'Error setting cells - ' + err.message );
- }
- // Remove the button primary class
- this.$( '.row-set-form .so-button-row-set' ).removeClass( 'button-primary' );
- },
- /**
- * Handle a click on the dialog left bar tab
- */
- tabClickHandler: function ( $t ) {
- if ( $t.attr( 'href' ) === '#row-layout' ) {
- this.$( '.so-panels-dialog' ).addClass( 'so-panels-dialog-has-right-sidebar' );
- } else {
- this.$( '.so-panels-dialog' ).removeClass( 'so-panels-dialog-has-right-sidebar' );
- }
- },
- /**
- * Update the current model with what we have in the dialog
- */
- updateModel: function ( args ) {
- args = _.extend( {
- refresh: true,
- refreshArgs: null
- }, args );
- // Set the cells
- if( ! _.isEmpty( this.model ) ) {
- this.model.setCells( this.row.cells );
- }
- // Update the styles if they've loaded
- if ( ! _.isUndefined( this.styles ) && this.styles.stylesLoaded ) {
- // This is an edit dialog, so there are styles
- var style = {};
- try {
- style = this.getFormValues( '.so-sidebar .so-visual-styles' ).style;
- }
- catch ( err ) {
- console.log( 'Error retrieving styles - ' + err.message );
- }
- this.model.set( 'style', style );
- }
- if ( args.refresh ) {
- this.builder.model.refreshPanelsData( args.refreshArgs );
- }
- },
- /**
- * Insert the new row
- */
- insertHandler: function () {
- this.builder.addHistoryEntry( 'row_added' );
- this.model = new panels.model.row();
- this.updateModel();
- var activeCell = this.builder.getActiveCell( {
- createCell: false,
- defaultPosition: 'last'
- } );
- var options = {};
- if ( activeCell !== null ) {
- options.at = this.builder.model.rows.indexOf( activeCell.row ) + 1;
- }
- // Set up the model and add it to the builder
- this.model.collection = this.builder.model.rows;
- this.builder.model.rows.add( this.model, options );
- this.closeDialog();
- this.builder.model.refreshPanelsData();
- return false;
- },
- /**
- * We'll just save this model and close the dialog
- */
- saveHandler: function () {
- this.builder.addHistoryEntry( 'row_edited' );
- this.updateModel();
- this.closeDialog();
- this.builder.model.refreshPanelsData();
- return false;
- },
- /**
- * The user clicks delete, so trigger deletion on the row model
- */
- deleteHandler: function () {
- // Trigger a destroy on the model that will happen with a visual indication to the user
- this.model.trigger( 'visual_destroy' );
- this.closeDialog( {silent: true} );
- return false;
- },
- /**
- * Duplicate this row
- */
- duplicateHandler: function () {
- this.builder.addHistoryEntry( 'row_duplicated' );
- var duplicateRow = this.model.clone( this.builder.model );
- this.builder.model.rows.add( duplicateRow, {
- at: this.builder.model.rows.indexOf( this.model ) + 1
- } );
- this.closeDialog( {silent: true} );
- return false;
- }
- } );
- },{}],9:[function(require,module,exports){
- var panels = window.panels, $ = jQuery;
- module.exports = panels.view.dialog.extend( {
- builder: null,
- sidebarWidgetTemplate: _.template( $( '#siteorigin-panels-dialog-widget-sidebar-widget' ).html().panelsProcessTemplate() ),
- dialogClass: 'so-panels-dialog-edit-widget',
- widgetView: false,
- savingWidget: false,
- events: {
- 'click .so-close': 'saveHandler',
- 'click .so-nav.so-previous': 'navToPrevious',
- 'click .so-nav.so-next': 'navToNext',
- // Action handlers
- 'click .so-toolbar .so-delete': 'deleteHandler',
- 'click .so-toolbar .so-duplicate': 'duplicateHandler'
- },
- initializeDialog: function () {
- var thisView = this;
- this.model.on( 'change:values', this.handleChangeValues, this );
- this.model.on( 'destroy', this.remove, this );
- // Refresh panels data after both dialog form components are loaded
- this.dialogFormsLoaded = 0;
- this.on( 'form_loaded styles_loaded', function () {
- this.dialogFormsLoaded ++;
- if ( this.dialogFormsLoaded === 2 ) {
- thisView.updateModel( {
- refreshArgs: {
- silent: true
- }
- } );
- }
- } );
- },
- /**
- * Render the widget dialog.
- */
- render: function () {
- // Render the dialog and attach it to the builder interface
- this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-widget' ).html(), {} ) );
- this.loadForm();
- if ( ! _.isUndefined( panelsOptions.widgets[this.model.get( 'class' )] ) ) {
- this.$( '.so-title .widget-name' ).html( panelsOptions.widgets[this.model.get( 'class' )].title );
- } else {
- this.$( '.so-title .widget-name' ).html( panelsOptions.loc.missing_widget.title );
- }
- if( ! this.builder.supports( 'addWidget' ) ) {
- this.$( '.so-buttons .so-duplicate' ).remove();
- }
- if( ! this.builder.supports( 'deleteWidget' ) ) {
- this.$( '.so-buttons .so-delete' ).remove();
- }
- // Now we need to attach the style window
- this.styles = new panels.view.styles();
- this.styles.model = this.model;
- this.styles.render( 'widget', $( '#post_ID' ).val(), {
- builderType: this.builder.config.builderType,
- dialog: this
- } );
- var $rightSidebar = this.$( '.so-sidebar.so-right-sidebar' );
- this.styles.attach( $rightSidebar );
- // Handle the loading class
- this.styles.on( 'styles_loaded', function ( hasStyles ) {
- // If we have styles remove the loading spinner, else remove the whole empty sidebar.
- if ( hasStyles ) {
- $rightSidebar.removeClass( 'so-panels-loading' );
- } else {
- $rightSidebar.closest( '.so-panels-dialog' ).removeClass( 'so-panels-dialog-has-right-sidebar' );
- $rightSidebar.remove();
- }
- }, this );
- $rightSidebar.addClass( 'so-panels-loading' );
- },
- /**
- * Get the previous widget editing dialog by looking at the dom.
- * @returns {*}
- */
- getPrevDialog: function () {
- var widgets = this.builder.$( '.so-cells .cell .so-widget' );
- if ( widgets.length <= 1 ) {
- return false;
- }
- var currentIndex = widgets.index( this.widgetView.$el );
- if ( currentIndex === 0 ) {
- return false;
- } else {
- do {
- widgetView = widgets.eq( --currentIndex ).data( 'view' );
- if ( ! _.isUndefined( widgetView ) && ! widgetView.model.get( 'read_only' ) ) {
- return widgetView.getEditDialog();
- }
- } while( ! _.isUndefined( widgetView ) && currentIndex > 0 );
- }
- return false;
- },
- /**
- * Get the next widget editing dialog by looking at the dom.
- * @returns {*}
- */
- getNextDialog: function () {
- var widgets = this.builder.$( '.so-cells .cell .so-widget' );
- if ( widgets.length <= 1 ) {
- return false;
- }
- var currentIndex = widgets.index( this.widgetView.$el ), widgetView;
- if ( currentIndex === widgets.length - 1 ) {
- return false;
- } else {
- do {
- widgetView = widgets.eq( ++currentIndex ).data( 'view' );
- if ( ! _.isUndefined( widgetView ) && ! widgetView.model.get( 'read_only' ) ) {
- return widgetView.getEditDialog();
- }
- } while( ! _.isUndefined( widgetView ) );
- }
- return false;
- },
- /**
- * Load the widget form from the server.
- * This is called when rendering the dialog for the first time.
- */
- loadForm: function () {
- // don't load the form if this dialog hasn't been rendered yet
- if ( ! this.$( '> *' ).length ) {
- return;
- }
- var thisView = this;
- this.$( '.so-content' ).addClass( 'so-panels-loading' );
- var data = {
- 'action': 'so_panels_widget_form',
- 'widget': this.model.get( 'class' ),
- 'instance': JSON.stringify( this.model.get( 'values' ) ),
- 'raw': this.model.get( 'raw' )
- };
- $.post(
- panelsOptions.ajaxurl,
- data,
- function ( result ) {
- // Add in the CID of the widget model
- var html = result.replace( /{\$id}/g, thisView.model.cid );
- // Load this content into the form
- thisView.$( '.so-content' )
- .removeClass( 'so-panels-loading' )
- .html( html );
- // Trigger all the necessary events
- thisView.trigger( 'form_loaded', thisView );
- // For legacy compatibility, trigger a panelsopen event
- thisView.$( '.panel-dialog' ).trigger( 'panelsopen' );
- // If the main dialog is closed from this point on, save the widget content
- thisView.on( 'close_dialog', thisView.updateModel, thisView );
- },
- 'html'
- );
- },
- /**
- * Save the widget from the form to the model
- */
- updateModel: function ( args ) {
- args = _.extend( {
- refresh: true,
- refreshArgs: null
- }, args );
- // Get the values from the form and assign the new values to the model
- this.savingWidget = true;
- if ( ! this.model.get( 'missing' ) ) {
- // Only get the values for non missing widgets.
- var values = this.getFormValues();
- if ( _.isUndefined( values.widgets ) ) {
- values = {};
- } else {
- values = values.widgets;
- values = values[Object.keys( values )[0]];
- }
- this.model.setValues( values );
- this.model.set( 'raw', true ); // We've saved from the widget form, so this is now raw
- }
- if ( this.styles.stylesLoaded ) {
- // If the styles view has loaded
- var style = {};
- try {
- style = this.getFormValues( '.so-sidebar .so-visual-styles' ).style;
- }
- catch ( e ) {
- }
- this.model.set( 'style', style );
- }
- this.savingWidget = false;
- if ( args.refresh ) {
- this.builder.model.refreshPanelsData( args.refreshArgs );
- }
- },
- /**
- *
- */
- handleChangeValues: function () {
- if ( ! this.savingWidget ) {
- // Reload the form when we've changed the model and we're not currently saving from the form
- this.loadForm();
- }
- },
- /**
- * Save a history entry for this widget. Called when the dialog is closed.
- */
- saveHandler: function () {
- this.builder.addHistoryEntry( 'widget_edited' );
- this.closeDialog();
- },
- /**
- * When the user clicks delete.
- *
- * @returns {boolean}
- */
- deleteHandler: function () {
- this.model.trigger( 'visual_destroy' );
- this.closeDialog( {silent: true} );
- this.builder.model.refreshPanelsData();
- return false;
- },
- duplicateHandler: function () {
- this.model.trigger( 'user_duplicate' );
- this.closeDialog( {silent: true} );
- this.builder.model.refreshPanelsData();
- return false;
- }
- } );
- },{}],10:[function(require,module,exports){
- var panels = window.panels, $ = jQuery;
- module.exports = panels.view.dialog.extend( {
- builder: null,
- widgetTemplate: _.template( $( '#siteorigin-panels-dialog-widgets-widget' ).html().panelsProcessTemplate() ),
- filter: {},
- dialogClass: 'so-panels-dialog-add-widget',
- events: {
- 'click .so-close': 'closeDialog',
- 'click .widget-type': 'widgetClickHandler',
- 'keyup .so-sidebar-search': 'searchHandler'
- },
- /**
- * Initialize the widget adding dialog
- */
- initializeDialog: function () {
- this.on( 'open_dialog', function () {
- this.filter.search = '';
- this.filterWidgets( this.filter );
- }, this );
- this.on( 'open_dialog_complete', function () {
- // Clear the search and re-filter the widgets when we open the dialog
- this.$( '.so-sidebar-search' ).val( '' ).focus();
- this.balanceWidgetHeights();
- } );
- // We'll implement a custom tab click handler
- this.on( 'tab_click', this.tabClickHandler, this );
- },
- render: function () {
- // Render the dialog and attach it to the builder interface
- this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-widgets' ).html(), {} ) );
- // Add all the widgets
- _.each( panelsOptions.widgets, function ( widget ) {
- var $w = $( this.widgetTemplate( {
- title: widget.title,
- description: widget.description
- } ) );
- if ( _.isUndefined( widget.icon ) ) {
- widget.icon = 'dashicons dashicons-admin-generic';
- }
- $( '<span class="widget-icon" />' ).addClass( widget.icon ).prependTo( $w.find( '.widget-type-wrapper' ) );
- $w.data( 'class', widget.class ).appendTo( this.$( '.widget-type-list' ) );
- }, this );
- // Add the sidebar tabs
- var tabs = this.$( '.so-sidebar-tabs' );
- _.each( panelsOptions.widget_dialog_tabs, function ( tab ) {
- $( this.dialogTabTemplate( {'title': tab.title} ) ).data( {
- 'message': tab.message,
- 'filter': tab.filter
- } ).appendTo( tabs );
- }, this );
- // We'll be using tabs, so initialize them
- this.initTabs();
- var thisDialog = this;
- $( window ).resize( function () {
- thisDialog.balanceWidgetHeights();
- } );
- },
- /**
- * Handle a tab being clicked
- */
- tabClickHandler: function ( $t ) {
- // Get the filter from the tab, and filter the widgets
- this.filter = $t.parent().data( 'filter' );
- this.filter.search = this.$( '.so-sidebar-search' ).val();
- var message = $t.parent().data( 'message' );
- if ( _.isEmpty( message ) ) {
- message = '';
- }
- this.$( '.so-toolbar .so-status' ).html( message );
- this.filterWidgets( this.filter );
- return false;
- },
- /**
- * Handle changes to the search value
- */
- searchHandler: function ( e ) {
- this.filter.search = $( e.target ).val();
- this.filterWidgets( this.filter );
- },
- /**
- * Filter the widgets that we're displaying
- * @param filter
- */
- filterWidgets: function ( filter ) {
- if ( _.isUndefined( filter ) ) {
- filter = {};
- }
- if ( _.isUndefined( filter.groups ) ) {
- filter.groups = '';
- }
- this.$( '.widget-type-list .widget-type' ).each( function () {
- var $$ = $( this ), showWidget;
- var widgetClass = $$.data( 'class' );
- var widgetData = (
- ! _.isUndefined( panelsOptions.widgets[widgetClass] )
- ) ? panelsOptions.widgets[widgetClass] : null;
- if ( _.isEmpty( filter.groups ) ) {
- // This filter doesn't specify groups, so show all
- showWidget = true;
- } else if ( widgetData !== null && ! _.isEmpty( _.intersection( filter.groups, panelsOptions.widgets[widgetClass].groups ) ) ) {
- // This widget is in the filter group
- showWidget = true;
- } else {
- // This widget is not in the filter group
- showWidget = false;
- }
- // This can probably be done with a more intelligent operator
- if ( showWidget ) {
- if ( ! _.isUndefined( filter.search ) && filter.search !== '' ) {
- // Check if the widget title contains the search term
- if ( widgetData.title.toLowerCase().indexOf( filter.search.toLowerCase() ) === - 1 ) {
- s