Page Builder by SiteOrigin - Version 2.6.6

Version Description

  • 25 April 2018 =
  • Only filter WooCommerce content when on the shop page.
  • Fix Background fallback URL notices.
Download this release

Release Info

Developer gpriday
Plugin Icon 128x128 Page Builder by SiteOrigin
Version 2.6.6
Comparing to
See all releases

Code changes from version 2.6.5 to 2.6.6

inc/styles-admin.php CHANGED
@@ -228,7 +228,7 @@ class SiteOrigin_Panels_Styles_Admin {
228
  $image = SiteOrigin_Panels_Styles::get_attachment_image_src( $current, 'thumbnail' );
229
  }
230
 
231
- $fallback_url = $current_styles[ $field_id . '_fallback' ];
232
  $fallback_field_name = 'style[' . $field_id . '_fallback]';
233
 
234
  ?>
@@ -246,7 +246,7 @@ class SiteOrigin_Panels_Styles_Admin {
246
  </div>
247
  <a href="#" class="remove-image<?php if ( empty( $current ) ) echo ' hidden' ?>"><?php _e( 'Remove', 'siteorigin-panels' ) ?></a>
248
 
249
- <input type="text" value="<?php if ( $fallback_url !== 'false' ) echo esc_url( $fallback_url ) ?>"
250
  placeholder="<?php esc_attr_e( 'External URL', 'siteorigin-panels' ) ?>"
251
  name="<?php echo esc_attr( $fallback_field_name ) ?>"
252
  class="image-fallback widefat" />
228
  $image = SiteOrigin_Panels_Styles::get_attachment_image_src( $current, 'thumbnail' );
229
  }
230
 
231
+ $fallback_url = ( ! empty( $current_styles[ $field_id . '_fallback' ] ) && $current_styles[ $field_id . '_fallback' ] !== 'false' ? $current_styles[ $field_id . '_fallback' ] : '' );
232
  $fallback_field_name = 'style[' . $field_id . '_fallback]';
233
 
234
  ?>
246
  </div>
247
  <a href="#" class="remove-image<?php if ( empty( $current ) ) echo ' hidden' ?>"><?php _e( 'Remove', 'siteorigin-panels' ) ?></a>
248
 
249
+ <input type="text" value="<?php echo esc_url( $fallback_url ) ?>"
250
  placeholder="<?php esc_attr_e( 'External URL', 'siteorigin-panels' ) ?>"
251
  name="<?php echo esc_attr( $fallback_field_name ) ?>"
252
  class="image-fallback widefat" />
inc/styles.php CHANGED
@@ -427,7 +427,7 @@ class SiteOrigin_Panels_Styles {
427
  ) {
428
  $url = self::get_attachment_image_src( $style['background_image_attachment'], 'full' );
429
 
430
- if ( empty( $url ) ) {
431
  $url = $style['background_image_attachment_fallback'];
432
  }
433
 
427
  ) {
428
  $url = self::get_attachment_image_src( $style['background_image_attachment'], 'full' );
429
 
430
+ if ( empty( $url ) && ! empty( $style['background_image_attachment_fallback'] ) ) {
431
  $url = $style['background_image_attachment_fallback'];
432
  }
433
 
js/{siteorigin-panels-265.js → siteorigin-panels-266.js} RENAMED
@@ -783,788 +783,788 @@ module.exports = panels.view.dialog.extend( {
783
  } );
784
 
785
  },{}],8:[function(require,module,exports){
786
- var panels = window.panels, $ = jQuery;
787
-
788
- module.exports = panels.view.dialog.extend({
789
-
790
- cellPreviewTemplate: _.template( panels.helpers.utils.processTemplate( $('#siteorigin-panels-dialog-row-cell-preview').html() ) ),
791
-
792
- editableLabel: true,
793
-
794
- events: {
795
- 'click .so-close': 'closeDialog',
796
-
797
- // Toolbar buttons
798
- 'click .so-toolbar .so-save': 'saveHandler',
799
- 'click .so-toolbar .so-insert': 'insertHandler',
800
- 'click .so-toolbar .so-delete': 'deleteHandler',
801
- 'click .so-toolbar .so-duplicate': 'duplicateHandler',
802
-
803
- // Changing the row
804
- 'change .row-set-form > *': 'setCellsFromForm',
805
- 'click .row-set-form button.set-row': 'setCellsFromForm',
806
- },
807
-
808
- dialogIcon: 'add-row',
809
- dialogClass: 'so-panels-dialog-row-edit',
810
- styleType: 'row',
811
-
812
- dialogType: 'edit',
813
-
814
- /**
815
- * The current settings, not yet saved to the model
816
- */
817
- row: {
818
- // This will be a clone of cells collection.
819
- cells: null,
820
- // The style settings of the row
821
- style: {}
822
- },
823
-
824
- cellStylesCache: [],
825
-
826
- initializeDialog: function () {
827
- this.on('open_dialog', function () {
828
- if (!_.isUndefined(this.model) && !_.isEmpty(this.model.get('cells'))) {
829
- this.setRowModel(this.model);
830
- } else {
831
- this.setRowModel(null);
832
- }
833
-
834
- this.regenerateRowPreview();
835
- }, this);
836
-
837
- // This is the default row layout
838
- this.row = {
839
- cells: new panels.collection.cells([{weight: 0.5}, {weight: 0.5}]),
840
- style: {}
841
- };
842
-
843
- // Refresh panels data after both dialog form components are loaded
844
- this.dialogFormsLoaded = 0;
845
- var thisView = this;
846
- this.on('form_loaded styles_loaded', function () {
847
- this.dialogFormsLoaded++;
848
- if (this.dialogFormsLoaded === 2) {
849
- thisView.updateModel({
850
- refreshArgs: {
851
- silent: true
852
- }
853
- });
854
- }
855
- });
856
-
857
- this.on('close_dialog', this.closeHandler);
858
-
859
- this.on( 'edit_label', function ( text ) {
860
- // If text is set to default values, just clear it.
861
- if ( text === panelsOptions.loc.row.add || text === panelsOptions.loc.row.edit ) {
862
- text = '';
863
- }
864
- this.model.set( 'label', text );
865
- if ( _.isEmpty( text ) ) {
866
- var title = this.dialogType === 'create' ? panelsOptions.loc.row.add : panelsOptions.loc.row.edit;
867
- this.$( '.so-title').text( title );
868
- }
869
- }.bind( this ) );
870
- },
871
-
872
- /**
873
- *
874
- * @param dialogType Either "edit" or "create"
875
- */
876
- setRowDialogType: function (dialogType) {
877
- this.dialogType = dialogType;
878
- },
879
-
880
- /**
881
- * Render the new row dialog
882
- */
883
- render: function () {
884
- var title = this.dialogType === 'create' ? panelsOptions.loc.row.add : panelsOptions.loc.row.edit;
885
- this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-row' ).html(), {
886
- title: title,
887
- dialogType: this.dialogType
888
- } ) );
889
-
890
- var titleElt = this.$( '.so-title' );
891
-
892
- if ( this.model.has( 'label' ) && ! _.isEmpty( this.model.get( 'label' ) ) ) {
893
- titleElt.text( this.model.get( 'label' ) );
894
- }
895
- this.$( '.so-edit-title' ).val( titleElt.text() );
896
-
897
- // Now we need to attach the style window
898
- this.styles = new panels.view.styles();
899
- this.styles.model = this.model;
900
- this.styles.render('row', this.builder.config.postId, {
901
- builderType: this.builder.config.builderType,
902
- dialog: this
903
- });
904
-
905
- if (!this.builder.supports('addRow')) {
906
- this.$('.so-buttons .so-duplicate').remove();
907
- }
908
- if (!this.builder.supports('deleteRow')) {
909
- this.$('.so-buttons .so-delete').remove();
910
- }
911
-
912
- var $rightSidebar = this.$('.so-sidebar.so-right-sidebar');
913
- this.styles.attach( $rightSidebar );
914
-
915
- // Handle the loading class
916
- this.styles.on('styles_loaded', function (hasStyles) {
917
- // If we don't have styles remove the empty sidebar.
918
- if ( ! hasStyles ) {
919
- $rightSidebar.closest('.so-panels-dialog').removeClass('so-panels-dialog-has-right-sidebar');
920
- $rightSidebar.remove();
921
- }
922
- }, this);
923
-
924
- if (!_.isUndefined(this.model)) {
925
- // Set the initial value of the
926
- this.$( 'input[name="cells"].so-row-field' ).val( this.model.get( 'cells' ).length );
927
- if ( this.model.has( 'ratio' ) ) {
928
- this.$( 'select[name="ratio"].so-row-field' ).val( this.model.get( 'ratio' ) );
929
- }
930
- if ( this.model.has( 'ratio_direction' ) ) {
931
- this.$( 'select[name="ratio_direction"].so-row-field' ).val( this.model.get( 'ratio_direction' ) );
932
- }
933
- }
934
-
935
- this.$('input.so-row-field').keyup(function () {
936
- $(this).trigger('change');
937
- });
938
-
939
- return this;
940
- },
941
-
942
- /**
943
- * Set the row model we'll be using for this dialog.
944
- *
945
- * @param model
946
- */
947
- setRowModel: function (model) {
948
- this.model = model;
949
-
950
- if (_.isEmpty(this.model)) {
951
- return this;
952
- }
953
-
954
- // Set the rows to be a copy of the model
955
- this.row = {
956
- cells: this.model.get('cells').clone(),
957
- style: {},
958
- ratio: this.model.get('ratio'),
959
- ratio_direction: this.model.get('ratio_direction'),
960
- };
961
-
962
- // Set the initial value of the cell field.
963
- this.$( 'input[name="cells"].so-row-field' ).val( this.model.get( 'cells' ).length );
964
- if ( this.model.has( 'ratio' ) ) {
965
- this.$( 'select[name="ratio"].so-row-field' ).val( this.model.get( 'ratio' ) );
966
- }
967
- if ( this.model.has( 'ratio_direction' ) ) {
968
- this.$( 'select[name="ratio_direction"].so-row-field' ).val( this.model.get( 'ratio_direction' ) );
969
- }
970
-
971
- this.clearCellStylesCache();
972
-
973
- return this;
974
- },
975
-
976
- /**
977
- * Regenerate the row preview and resizing interface.
978
- */
979
- regenerateRowPreview: function () {
980
- var thisDialog = this;
981
- var rowPreview = this.$('.row-preview');
982
-
983
- // If no selected cell, select the first cell.
984
- var selectedIndex = this.getSelectedCellIndex();
985
-
986
- rowPreview.empty();
987
-
988
- var timeout;
989
-
990
- // Represent the cells
991
- this.row.cells.each(function (cellModel, i) {
992
- var newCell = $(this.cellPreviewTemplate({weight: cellModel.get('weight')}));
993
- rowPreview.append(newCell);
994
-
995
- if(i == selectedIndex) {
996
- newCell.find('.preview-cell-in').addClass('cell-selected');
997
- }
998
-
999
- var prevCell = newCell.prev();
1000
- var handle;
1001
-
1002
- if (prevCell.length) {
1003
- handle = $('<div class="resize-handle"></div>');
1004
- handle
1005
- .appendTo(newCell)
1006
- .dblclick(function () {
1007
- var prevCellModel = thisDialog.row.cells.at(i - 1);
1008
- var t = cellModel.get('weight') + prevCellModel.get('weight');
1009
- cellModel.set('weight', t / 2);
1010
- prevCellModel.set('weight', t / 2);
1011
- thisDialog.scaleRowWidths();
1012
- });
1013
-
1014
- handle.draggable({
1015
- axis: 'x',
1016
- containment: rowPreview,
1017
- start: function (e, ui) {
1018
-
1019
- // Create the clone for the current cell
1020
- var newCellClone = newCell.clone().appendTo(ui.helper).css({
1021
- position: 'absolute',
1022
- top: '0',
1023
- width: newCell.outerWidth(),
1024
- left: 6,
1025
- height: newCell.outerHeight()
1026
- });
1027
- newCellClone.find('.resize-handle').remove();
1028
-
1029
- // Create the clone for the previous cell
1030
- var prevCellClone = prevCell.clone().appendTo(ui.helper).css({
1031
- position: 'absolute',
1032
- top: '0',
1033
- width: prevCell.outerWidth(),
1034
- right: 6,
1035
- height: prevCell.outerHeight()
1036
- });
1037
- prevCellClone.find('.resize-handle').remove();
1038
-
1039
- $(this).data({
1040
- 'newCellClone': newCellClone,
1041
- 'prevCellClone': prevCellClone
1042
- });
1043
-
1044
- // Hide the
1045
- newCell.find('> .preview-cell-in').css('visibility', 'hidden');
1046
- prevCell.find('> .preview-cell-in').css('visibility', 'hidden');
1047
- },
1048
- drag: function (e, ui) {
1049
- // Calculate the new cell and previous cell widths as a percent
1050
- var cellWeight = thisDialog.row.cells.at(i).get('weight');
1051
- var prevCellWeight = thisDialog.row.cells.at(i - 1).get('weight');
1052
- var ncw = cellWeight - (
1053
- (
1054
- ui.position.left + 6
1055
- ) / rowPreview.width()
1056
- );
1057
- var pcw = prevCellWeight + (
1058
- (
1059
- ui.position.left + 6
1060
- ) / rowPreview.width()
1061
- );
1062
-
1063
- var helperLeft = ui.helper.offset().left - rowPreview.offset().left - 6;
1064
-
1065
- $(this).data('newCellClone').css('width', rowPreview.width() * ncw)
1066
- .find('.preview-cell-weight').html(Math.round(ncw * 1000) / 10);
1067
-
1068
- $(this).data('prevCellClone').css('width', rowPreview.width() * pcw)
1069
- .find('.preview-cell-weight').html(Math.round(pcw * 1000) / 10);
1070
- },
1071
- stop: function (e, ui) {
1072
- // Remove the clones
1073
- $(this).data('newCellClone').remove();
1074
- $(this).data('prevCellClone').remove();
1075
-
1076
- // Reshow the main cells
1077
- newCell.find('.preview-cell-in').css('visibility', 'visible');
1078
- prevCell.find('.preview-cell-in').css('visibility', 'visible');
1079
-
1080
- // Calculate the new cell weights
1081
- var offset = ui.position.left + 6;
1082
- var percent = offset / rowPreview.width();
1083
-
1084
- // Ignore this if any of the cells are below 2% in width.
1085
- var cellModel = thisDialog.row.cells.at(i);
1086
- var prevCellModel = thisDialog.row.cells.at(i - 1);
1087
- if (cellModel.get('weight') - percent > 0.02 && prevCellModel.get('weight') + percent > 0.02) {
1088
- cellModel.set('weight', cellModel.get('weight') - percent);
1089
- prevCellModel.set('weight', prevCellModel.get('weight') + percent);
1090
- }
1091
-
1092
- thisDialog.scaleRowWidths();
1093
- ui.helper.css('left', -6);
1094
- }
1095
- });
1096
- }
1097
-
1098
- newCell.click(function (event) {
1099
-
1100
- if ( ! ( $(event.target).is('.preview-cell') || $(event.target).is('.preview-cell-in') ) ) {
1101
- return;
1102
- }
1103
-
1104
- var cell = $(event.target);
1105
- cell.closest('.row-preview').find('.preview-cell .preview-cell-in').removeClass('cell-selected');
1106
- cell.addClass('cell-selected');
1107
-
1108
- this.openSelectedCellStyles();
1109
-
1110
- }.bind(this));
1111
-
1112
- // Make this row weight click editable
1113
- newCell.find('.preview-cell-weight').click(function (ci) {
1114
-
1115
- // Disable the draggable while entering values
1116
- thisDialog.$('.resize-handle').css('pointer-event', 'none').draggable('disable');
1117
-
1118
- rowPreview.find('.preview-cell-weight').each(function () {
1119
- var $$ = jQuery(this).hide();
1120
- $('<input type="text" class="preview-cell-weight-input no-user-interacted" />')
1121
- .val(parseFloat($$.html())).insertAfter($$)
1122
- .focus(function () {
1123
- clearTimeout(timeout);
1124
- })
1125
- .keyup(function (e) {
1126
- if (e.keyCode !== 9) {
1127
- // Only register the interaction if the user didn't press tab
1128
- $(this).removeClass('no-user-interacted');
1129
- }
1130
-
1131
- // Enter is clicked
1132
- if (e.keyCode === 13) {
1133
- e.preventDefault();
1134
- $(this).blur();
1135
- }
1136
- })
1137
- .keydown(function (e) {
1138
- if (e.keyCode === 9) {
1139
- e.preventDefault();
1140
-
1141
- // Tab will always cycle around the row inputs
1142
- var inputs = rowPreview.find('.preview-cell-weight-input');
1143
- var i = inputs.index($(this));
1144
- if (i === inputs.length - 1) {
1145
- inputs.eq(0).focus().select();
1146
- } else {
1147
- inputs.eq(i + 1).focus().select();
1148
- }
1149
- }
1150
- })
1151
- .blur(function () {
1152
- rowPreview.find('.preview-cell-weight-input').each(function (i, el) {
1153
- if (isNaN(parseFloat($(el).val()))) {
1154
- $(el).val(Math.floor(thisDialog.row.cells.at(i).get('weight') * 1000) / 10);
1155
- }
1156
- });
1157
-
1158
- timeout = setTimeout(function () {
1159
- // If there are no weight inputs, then skip this
1160
- if (rowPreview.find('.preview-cell-weight-input').length === 0) {
1161
- return false;
1162
- }
1163
-
1164
- // Go through all the inputs
1165
- var rowWeights = [],
1166
- rowChanged = [],
1167
- changedSum = 0,
1168
- unchangedSum = 0;
1169
-
1170
- rowPreview.find('.preview-cell-weight-input').each(function (i, el) {
1171
- var val = parseFloat($(el).val());
1172
- if (isNaN(val)) {
1173
- val = 1 / thisDialog.row.cells.length;
1174
- } else {
1175
- val = Math.round(val * 10) / 1000;
1176
- }
1177
-
1178
- // Check within 3 decimal points
1179
- var changed = !$(el).hasClass('no-user-interacted');
1180
-
1181
- rowWeights.push(val);
1182
- rowChanged.push(changed);
1183
-
1184
- if (changed) {
1185
- changedSum += val;
1186
- } else {
1187
- unchangedSum += val;
1188
- }
1189
- });
1190
-
1191
- if (changedSum > 0 && unchangedSum > 0 && (
1192
- 1 - changedSum
1193
- ) > 0) {
1194
- // Balance out the unchanged rows to occupy the weight left over by the changed sum
1195
- for (var i = 0; i < rowWeights.length; i++) {
1196
- if (!rowChanged[i]) {
1197
- rowWeights[i] = (
1198
- rowWeights[i] / unchangedSum
1199
- ) * (
1200
- 1 - changedSum
1201
- );
1202
- }
1203
- }
1204
- }
1205
-
1206
- // Last check to ensure total weight is 1
1207
- var sum = _.reduce(rowWeights, function (memo, num) {
1208
- return memo + num;
1209
- });
1210
- rowWeights = rowWeights.map(function (w) {
1211
- return w / sum;
1212
- });
1213
-
1214
- // Set the new cell weights and regenerate the preview.
1215
- if (Math.min.apply(Math, rowWeights) > 0.01) {
1216
- thisDialog.row.cells.each(function (cell, i) {
1217
- cell.set('weight', rowWeights[i]);
1218
- });
1219
- }
1220
-
1221
- // Now lets animate the cells into their new widths
1222
- rowPreview.find('.preview-cell').each(function (i, el) {
1223
- var cellWeight = thisDialog.row.cells.at(i).get('weight');
1224
- $(el).animate({'width': Math.round(cellWeight * 1000) / 10 + "%"}, 250);
1225
- $(el).find('.preview-cell-weight-input').val(Math.round(cellWeight * 1000) / 10);
1226
- });
1227
-
1228
- // So the draggable handle is not hidden.
1229
- rowPreview.find('.preview-cell').css('overflow', 'visible');
1230
-
1231
- setTimeout(function () {
1232
- thisDialog.regenerateRowPreview();
1233
- }, 260);
1234
-
1235
- }, 100);
1236
- })
1237
- .click(function () {
1238
- $(this).select();
1239
- });
1240
- });
1241
-
1242
- $(this).siblings('.preview-cell-weight-input').select();
1243
-
1244
- });
1245
-
1246
- }, this);
1247
-
1248
- this.openSelectedCellStyles();
1249
-
1250
- this.trigger('form_loaded', this);
1251
- },
1252
-
1253
- getSelectedCellIndex: function() {
1254
- var selectedIndex = -1;
1255
- this.$('.preview-cell .preview-cell-in').each(function(index, el) {
1256
- if($(el).is('.cell-selected')) {
1257
- selectedIndex = index;
1258
- }
1259
- });
1260
- return selectedIndex;
1261
- },
1262
-
1263
- openSelectedCellStyles: function() {
1264
- if (!_.isUndefined(this.cellStyles)) {
1265
- if (this.cellStyles.stylesLoaded) {
1266
- var style = {};
1267
- try {
1268
- style = this.getFormValues('.so-sidebar .so-visual-styles.so-cell-styles').style;
1269
- }
1270
- catch (err) {
1271
- console.log('Error retrieving cell styles - ' + err.message);
1272
- }
1273
-
1274
- this.cellStyles.model.set('style', style);
1275
- }
1276
- this.cellStyles.detach();
1277
- }
1278
-
1279
- this.cellStyles = this.getSelectedCellStyles();
1280
-
1281
- if ( this.cellStyles ) {
1282
- var $rightSidebar = this.$( '.so-sidebar.so-right-sidebar' );
1283
- this.cellStyles.attach( $rightSidebar );
1284
- }
1285
- },
1286
-
1287
- getSelectedCellStyles: function () {
1288
- var cellIndex = this.getSelectedCellIndex();
1289
- if ( cellIndex > -1 ) {
1290
- var cellStyles = this.cellStylesCache[cellIndex];
1291
- if ( !cellStyles ) {
1292
- cellStyles = new panels.view.styles();
1293
- cellStyles.model = this.row.cells.at( cellIndex );
1294
- cellStyles.render( 'cell', this.builder.config.postId, {
1295
- builderType: this.builder.config.builderType,
1296
- dialog: this,
1297
- index: cellIndex,
1298
- } );
1299
- this.cellStylesCache[cellIndex] = cellStyles;
1300
- }
1301
- }
1302
-
1303
- return cellStyles;
1304
- },
1305
-
1306
- clearCellStylesCache: function () {
1307
- // Call remove() on all cell styles to remove data, event listeners etc.
1308
- this.cellStylesCache.forEach(function (cellStyles) {
1309
- cellStyles.remove();
1310
- });
1311
- this.cellStylesCache = [];
1312
- },
1313
-
1314
- /**
1315
- * Visually scale the row widths based on the cell weights
1316
- */
1317
- scaleRowWidths: function () {
1318
- var thisDialog = this;
1319
- this.$('.row-preview .preview-cell').each(function (i, el) {
1320
- var cell = thisDialog.row.cells.at(i);
1321
- $(el)
1322
- .css('width', cell.get('weight') * 100 + "%")
1323
- .find('.preview-cell-weight').html(Math.round(cell.get('weight') * 1000) / 10);
1324
- });
1325
- },
1326
-
1327
- /**
1328
- * Get the weights from the
1329
- */
1330
- setCellsFromForm: function () {
1331
-
1332
- try {
1333
- var f = {
1334
- 'cells': parseInt(this.$('.row-set-form input[name="cells"]').val()),
1335
- 'ratio': parseFloat(this.$('.row-set-form select[name="ratio"]').val()),
1336
- 'direction': this.$('.row-set-form select[name="ratio_direction"]').val()
1337
- };
1338
-
1339
- if (_.isNaN(f.cells)) {
1340
- f.cells = 1;
1341
- }
1342
- if (isNaN(f.ratio)) {
1343
- f.ratio = 1;
1344
- }
1345
- if (f.cells < 1) {
1346
- f.cells = 1;
1347
- this.$('.row-set-form input[name="cells"]').val(f.cells);
1348
- }
1349
- else if (f.cells > 12) {
1350
- f.cells = 12;
1351
- this.$('.row-set-form input[name="cells"]').val(f.cells);
1352
- }
1353
-
1354
- this.$('.row-set-form select[name="ratio"]').val(f.ratio);
1355
-
1356
- var cells = [];
1357
- var cellCountChanged = (
1358
- this.row.cells.length !== f.cells
1359
- );
1360
-
1361
- // Now, lets create some cells
1362
- var currentWeight = 1;
1363
- for (var i = 0; i < f.cells; i++) {
1364
- cells.push(currentWeight);
1365
- currentWeight *= f.ratio;
1366
- }
1367
-
1368
- // Now lets make sure that the row weights add up to 1
1369
-
1370
- var totalRowWeight = _.reduce(cells, function (memo, weight) {
1371
- return memo + weight;
1372
- });
1373
- cells = _.map(cells, function (cell) {
1374
- return cell / totalRowWeight;
1375
- });
1376
-
1377
- // Don't return cells that are too small
1378
- cells = _.filter(cells, function (cell) {
1379
- return cell > 0.01;
1380
- });
1381
-
1382
- if (f.direction === 'left') {
1383
- cells = cells.reverse();
1384
- }
1385
-
1386
- // Discard deleted cells.
1387
- this.row.cells = new panels.collection.cells(this.row.cells.first(cells.length));
1388
-
1389
- _.each(cells, function (cellWeight, index) {
1390
- var cell = this.row.cells.at(index);
1391
- if (!cell) {
1392
- cell = new panels.model.cell({weight: cellWeight, row: this.model});
1393
- this.row.cells.add(cell);
1394
- } else {
1395
- cell.set('weight', cellWeight);
1396
- }
1397
- }.bind(this));
1398
-
1399
- this.row.ratio = f.ratio;
1400
- this.row.ratio_direction = f.direction;
1401
-
1402
- if (cellCountChanged) {
1403
- this.regenerateRowPreview();
1404
- } else {
1405
- var thisDialog = this;
1406
-
1407
- // Now lets animate the cells into their new widths
1408
- this.$('.preview-cell').each(function (i, el) {
1409
- var cellWeight = thisDialog.row.cells.at(i).get('weight');
1410
- $(el).animate({'width': Math.round(cellWeight * 1000) / 10 + "%"}, 250);
1411
- $(el).find('.preview-cell-weight').html(Math.round(cellWeight * 1000) / 10);
1412
- });
1413
-
1414
- // So the draggable handle is not hidden.
1415
- this.$('.preview-cell').css('overflow', 'visible');
1416
-
1417
- setTimeout(function () {
1418
- thisDialog.regenerateRowPreview();
1419
- }, 260);
1420
- }
1421
- }
1422
- catch (err) {
1423
- console.log('Error setting cells - ' + err.message);
1424
- }
1425
-
1426
-
1427
- // Remove the button primary class
1428
- this.$('.row-set-form .so-button-row-set').removeClass('button-primary');
1429
- },
1430
-
1431
- /**
1432
- * Handle a click on the dialog left bar tab
1433
- */
1434
- tabClickHandler: function ($t) {
1435
- if ($t.attr('href') === '#row-layout') {
1436
- this.$('.so-panels-dialog').addClass('so-panels-dialog-has-right-sidebar');
1437
- } else {
1438
- this.$('.so-panels-dialog').removeClass('so-panels-dialog-has-right-sidebar');
1439
- }
1440
- },
1441
-
1442
- /**
1443
- * Update the current model with what we have in the dialog
1444
- */
1445
- updateModel: function (args) {
1446
- args = _.extend({
1447
- refresh: true,
1448
- refreshArgs: null
1449
- }, args);
1450
-
1451
- // Set the cells
1452
- if (!_.isEmpty(this.model)) {
1453
- this.model.setCells( this.row.cells );
1454
- this.model.set( 'ratio', this.row.ratio );
1455
- this.model.set( 'ratio_direction', this.row.ratio_direction );
1456
- }
1457
-
1458
- // Update the row styles if they've loaded
1459
- if (!_.isUndefined(this.styles) && this.styles.stylesLoaded) {
1460
- // This is an edit dialog, so there are styles
1461
- var style = {};
1462
- try {
1463
- style = this.getFormValues('.so-sidebar .so-visual-styles.so-row-styles').style;
1464
- }
1465
- catch (err) {
1466
- console.log('Error retrieving row styles - ' + err.message);
1467
- }
1468
-
1469
- this.model.set('style', style);
1470
- }
1471
-
1472
- // Update the cell styles if any are showing.
1473
- if (!_.isUndefined(this.cellStyles) && this.cellStyles.stylesLoaded) {
1474
-
1475
- var style = {};
1476
- try {
1477
- style = this.getFormValues('.so-sidebar .so-visual-styles.so-cell-styles').style;
1478
- }
1479
- catch (err) {
1480
- console.log('Error retrieving cell styles - ' + err.message);
1481
- }
1482
-
1483
- this.cellStyles.model.set('style', style);
1484
- }
1485
-
1486
- if (args.refresh) {
1487
- this.builder.model.refreshPanelsData(args.refreshArgs);
1488
- }
1489
- },
1490
-
1491
- /**
1492
- * Insert the new row
1493
- */
1494
- insertHandler: function () {
1495
- this.builder.addHistoryEntry('row_added');
1496
-
1497
- this.updateModel();
1498
-
1499
- var activeCell = this.builder.getActiveCell({
1500
- createCell: false,
1501
- });
1502
-
1503
- var options = {};
1504
- if (activeCell !== null) {
1505
- options.at = this.builder.model.get('rows').indexOf(activeCell.row) + 1;
1506
- }
1507
-
1508
- // Set up the model and add it to the builder
1509
- this.model.collection = this.builder.model.get('rows');
1510
- this.builder.model.get('rows').add(this.model, options);
1511
-
1512
- this.closeDialog();
1513
-
1514
- this.builder.model.refreshPanelsData();
1515
-
1516
- return false;
1517
- },
1518
-
1519
- /**
1520
- * We'll just save this model and close the dialog
1521
- */
1522
- saveHandler: function () {
1523
- this.builder.addHistoryEntry('row_edited');
1524
- this.updateModel();
1525
- this.closeDialog();
1526
-
1527
- this.builder.model.refreshPanelsData();
1528
-
1529
- return false;
1530
- },
1531
-
1532
- /**
1533
- * The user clicks delete, so trigger deletion on the row model
1534
- */
1535
- deleteHandler: function () {
1536
- // Trigger a destroy on the model that will happen with a visual indication to the user
1537
- this.model.trigger('visual_destroy');
1538
- this.closeDialog({silent: true});
1539
-
1540
- return false;
1541
- },
1542
-
1543
- /**
1544
- * Duplicate this row
1545
- */
1546
- duplicateHandler: function () {
1547
- this.builder.addHistoryEntry('row_duplicated');
1548
-
1549
- var duplicateRow = this.model.clone(this.builder.model);
1550
-
1551
- this.builder.model.get('rows').add( duplicateRow, {
1552
- at: this.builder.model.get('rows').indexOf(this.model) + 1
1553
- } );
1554
-
1555
- this.closeDialog({silent: true});
1556
-
1557
- return false;
1558
- },
1559
-
1560
- closeHandler: function() {
1561
- this.clearCellStylesCache();
1562
- if( ! _.isUndefined(this.cellStyles) ) {
1563
- this.cellStyles = undefined;
1564
- }
1565
- },
1566
-
1567
- });
1568
 
1569
  },{}],9:[function(require,module,exports){
1570
  var panels = window.panels, $ = jQuery;
783
  } );
784
 
785
  },{}],8:[function(require,module,exports){
786
+ var panels = window.panels, $ = jQuery;
787
+
788
+ module.exports = panels.view.dialog.extend({
789
+
790
+ cellPreviewTemplate: _.template( panels.helpers.utils.processTemplate( $('#siteorigin-panels-dialog-row-cell-preview').html() ) ),
791
+
792
+ editableLabel: true,
793
+
794
+ events: {
795
+ 'click .so-close': 'closeDialog',
796
+
797
+ // Toolbar buttons
798
+ 'click .so-toolbar .so-save': 'saveHandler',
799
+ 'click .so-toolbar .so-insert': 'insertHandler',
800
+ 'click .so-toolbar .so-delete': 'deleteHandler',
801
+ 'click .so-toolbar .so-duplicate': 'duplicateHandler',
802
+
803
+ // Changing the row
804
+ 'change .row-set-form > *': 'setCellsFromForm',
805
+ 'click .row-set-form button.set-row': 'setCellsFromForm',
806
+ },
807
+
808
+ dialogIcon: 'add-row',
809
+ dialogClass: 'so-panels-dialog-row-edit',
810
+ styleType: 'row',
811
+
812
+ dialogType: 'edit',
813
+
814
+ /**
815
+ * The current settings, not yet saved to the model
816
+ */
817
+ row: {
818
+ // This will be a clone of cells collection.
819
+ cells: null,
820
+ // The style settings of the row
821
+ style: {}
822
+ },
823
+
824
+ cellStylesCache: [],
825
+
826
+ initializeDialog: function () {
827
+ this.on('open_dialog', function () {
828
+ if (!_.isUndefined(this.model) && !_.isEmpty(this.model.get('cells'))) {
829
+ this.setRowModel(this.model);
830
+ } else {
831
+ this.setRowModel(null);
832
+ }
833
+
834
+ this.regenerateRowPreview();
835
+ }, this);
836
+
837
+ // This is the default row layout
838
+ this.row = {
839
+ cells: new panels.collection.cells([{weight: 0.5}, {weight: 0.5}]),
840
+ style: {}
841
+ };
842
+
843
+ // Refresh panels data after both dialog form components are loaded
844
+ this.dialogFormsLoaded = 0;
845
+ var thisView = this;
846
+ this.on('form_loaded styles_loaded', function () {
847
+ this.dialogFormsLoaded++;
848
+ if (this.dialogFormsLoaded === 2) {
849
+ thisView.updateModel({
850
+ refreshArgs: {
851
+ silent: true
852
+ }
853
+ });
854
+ }
855
+ });
856
+
857
+ this.on('close_dialog', this.closeHandler);
858
+
859
+ this.on( 'edit_label', function ( text ) {
860
+ // If text is set to default values, just clear it.
861
+ if ( text === panelsOptions.loc.row.add || text === panelsOptions.loc.row.edit ) {
862
+ text = '';
863
+ }
864
+ this.model.set( 'label', text );
865
+ if ( _.isEmpty( text ) ) {
866
+ var title = this.dialogType === 'create' ? panelsOptions.loc.row.add : panelsOptions.loc.row.edit;
867
+ this.$( '.so-title').text( title );
868
+ }
869
+ }.bind( this ) );
870
+ },
871
+
872
+ /**
873
+ *
874
+ * @param dialogType Either "edit" or "create"
875
+ */
876
+ setRowDialogType: function (dialogType) {
877
+ this.dialogType = dialogType;
878
+ },
879
+
880
+ /**
881
+ * Render the new row dialog
882
+ */
883
+ render: function () {
884
+ var title = this.dialogType === 'create' ? panelsOptions.loc.row.add : panelsOptions.loc.row.edit;
885
+ this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-row' ).html(), {
886
+ title: title,
887
+ dialogType: this.dialogType
888
+ } ) );
889
+
890
+ var titleElt = this.$( '.so-title' );
891
+
892
+ if ( this.model.has( 'label' ) && ! _.isEmpty( this.model.get( 'label' ) ) ) {
893
+ titleElt.text( this.model.get( 'label' ) );
894
+ }
895
+ this.$( '.so-edit-title' ).val( titleElt.text() );
896
+
897
+ // Now we need to attach the style window
898
+ this.styles = new panels.view.styles();
899
+ this.styles.model = this.model;
900
+ this.styles.render('row', this.builder.config.postId, {
901
+ builderType: this.builder.config.builderType,
902
+ dialog: this
903
+ });
904
+
905
+ if (!this.builder.supports('addRow')) {
906
+ this.$('.so-buttons .so-duplicate').remove();
907
+ }
908
+ if (!this.builder.supports('deleteRow')) {
909
+ this.$('.so-buttons .so-delete').remove();
910
+ }
911
+
912
+ var $rightSidebar = this.$('.so-sidebar.so-right-sidebar');
913
+ this.styles.attach( $rightSidebar );
914
+
915
+ // Handle the loading class
916
+ this.styles.on('styles_loaded', function (hasStyles) {
917
+ // If we don't have styles remove the empty sidebar.
918
+ if ( ! hasStyles ) {
919
+ $rightSidebar.closest('.so-panels-dialog').removeClass('so-panels-dialog-has-right-sidebar');
920
+ $rightSidebar.remove();
921
+ }
922
+ }, this);
923
+
924
+ if (!_.isUndefined(this.model)) {
925
+ // Set the initial value of the
926
+ this.$( 'input[name="cells"].so-row-field' ).val( this.model.get( 'cells' ).length );
927
+ if ( this.model.has( 'ratio' ) ) {
928
+ this.$( 'select[name="ratio"].so-row-field' ).val( this.model.get( 'ratio' ) );
929
+ }
930
+ if ( this.model.has( 'ratio_direction' ) ) {
931
+ this.$( 'select[name="ratio_direction"].so-row-field' ).val( this.model.get( 'ratio_direction' ) );
932
+ }
933
+ }
934
+
935
+ this.$('input.so-row-field').keyup(function () {
936
+ $(this).trigger('change');
937
+ });
938
+
939
+ return this;
940
+ },
941
+
942
+ /**
943
+ * Set the row model we'll be using for this dialog.
944
+ *
945
+ * @param model
946
+ */
947
+ setRowModel: function (model) {
948
+ this.model = model;
949
+
950
+ if (_.isEmpty(this.model)) {
951
+ return this;
952
+ }
953
+
954
+ // Set the rows to be a copy of the model
955
+ this.row = {
956
+ cells: this.model.get('cells').clone(),
957
+ style: {},
958
+ ratio: this.model.get('ratio'),
959
+ ratio_direction: this.model.get('ratio_direction'),
960
+ };
961
+
962
+ // Set the initial value of the cell field.
963
+ this.$( 'input[name="cells"].so-row-field' ).val( this.model.get( 'cells' ).length );
964
+ if ( this.model.has( 'ratio' ) ) {
965
+ this.$( 'select[name="ratio"].so-row-field' ).val( this.model.get( 'ratio' ) );
966
+ }
967
+ if ( this.model.has( 'ratio_direction' ) ) {
968
+ this.$( 'select[name="ratio_direction"].so-row-field' ).val( this.model.get( 'ratio_direction' ) );
969
+ }
970
+
971
+ this.clearCellStylesCache();
972
+
973
+ return this;
974
+ },
975
+
976
+ /**
977
+ * Regenerate the row preview and resizing interface.
978
+ */
979
+ regenerateRowPreview: function () {
980
+ var thisDialog = this;
981
+ var rowPreview = this.$('.row-preview');
982
+
983
+ // If no selected cell, select the first cell.
984
+ var selectedIndex = this.getSelectedCellIndex();
985
+
986
+ rowPreview.empty();
987
+
988
+ var timeout;
989
+
990
+ // Represent the cells
991
+ this.row.cells.each(function (cellModel, i) {
992
+ var newCell = $(this.cellPreviewTemplate({weight: cellModel.get('weight')}));
993
+ rowPreview.append(newCell);
994
+
995
+ if(i == selectedIndex) {
996
+ newCell.find('.preview-cell-in').addClass('cell-selected');
997
+ }
998
+
999
+ var prevCell = newCell.prev();
1000
+ var handle;
1001
+
1002
+ if (prevCell.length) {
1003
+ handle = $('<div class="resize-handle"></div>');
1004
+ handle
1005
+ .appendTo(newCell)
1006
+ .dblclick(function () {
1007
+ var prevCellModel = thisDialog.row.cells.at(i - 1);
1008
+ var t = cellModel.get('weight') + prevCellModel.get('weight');
1009
+ cellModel.set('weight', t / 2);
1010
+ prevCellModel.set('weight', t / 2);
1011
+ thisDialog.scaleRowWidths();
1012
+ });
1013
+
1014
+ handle.draggable({
1015
+ axis: 'x',
1016
+ containment: rowPreview,
1017
+ start: function (e, ui) {
1018
+
1019
+ // Create the clone for the current cell
1020
+ var newCellClone = newCell.clone().appendTo(ui.helper).css({
1021
+ position: 'absolute',
1022
+ top: '0',
1023
+ width: newCell.outerWidth(),
1024
+ left: 6,
1025
+ height: newCell.outerHeight()
1026
+ });
1027
+ newCellClone.find('.resize-handle').remove();
1028
+
1029
+ // Create the clone for the previous cell
1030
+ var prevCellClone = prevCell.clone().appendTo(ui.helper).css({
1031
+ position: 'absolute',
1032
+ top: '0',
1033
+ width: prevCell.outerWidth(),
1034
+ right: 6,
1035
+ height: prevCell.outerHeight()
1036
+ });
1037
+ prevCellClone.find('.resize-handle').remove();
1038
+
1039
+ $(this).data({
1040
+ 'newCellClone': newCellClone,
1041
+ 'prevCellClone': prevCellClone
1042
+ });
1043
+
1044
+ // Hide the
1045
+ newCell.find('> .preview-cell-in').css('visibility', 'hidden');
1046
+ prevCell.find('> .preview-cell-in').css('visibility', 'hidden');
1047
+ },
1048
+ drag: function (e, ui) {
1049
+ // Calculate the new cell and previous cell widths as a percent
1050
+ var cellWeight = thisDialog.row.cells.at(i).get('weight');
1051
+ var prevCellWeight = thisDialog.row.cells.at(i - 1).get('weight');
1052
+ var ncw = cellWeight - (
1053
+ (
1054
+ ui.position.left + 6
1055
+ ) / rowPreview.width()
1056
+ );
1057
+ var pcw = prevCellWeight + (
1058
+ (
1059
+ ui.position.left + 6
1060
+ ) / rowPreview.width()
1061
+ );
1062
+
1063
+ var helperLeft = ui.helper.offset().left - rowPreview.offset().left - 6;
1064
+
1065
+ $(this).data('newCellClone').css('width', rowPreview.width() * ncw)
1066
+ .find('.preview-cell-weight').html(Math.round(ncw * 1000) / 10);
1067
+
1068
+ $(this).data('prevCellClone').css('width', rowPreview.width() * pcw)
1069
+ .find('.preview-cell-weight').html(Math.round(pcw * 1000) / 10);
1070
+ },
1071
+ stop: function (e, ui) {
1072
+ // Remove the clones
1073
+ $(this).data('newCellClone').remove();
1074
+ $(this).data('prevCellClone').remove();
1075
+
1076
+ // Reshow the main cells
1077
+ newCell.find('.preview-cell-in').css('visibility', 'visible');
1078
+ prevCell.find('.preview-cell-in').css('visibility', 'visible');
1079
+
1080
+ // Calculate the new cell weights
1081
+ var offset = ui.position.left + 6;
1082
+ var percent = offset / rowPreview.width();
1083
+
1084
+ // Ignore this if any of the cells are below 2% in width.
1085
+ var cellModel = thisDialog.row.cells.at(i);
1086
+ var prevCellModel = thisDialog.row.cells.at(i - 1);
1087
+ if (cellModel.get('weight') - percent > 0.02 && prevCellModel.get('weight') + percent > 0.02) {
1088
+ cellModel.set('weight', cellModel.get('weight') - percent);
1089
+ prevCellModel.set('weight', prevCellModel.get('weight') + percent);
1090
+ }
1091
+
1092
+ thisDialog.scaleRowWidths();
1093
+ ui.helper.css('left', -6);
1094
+ }
1095
+ });
1096
+ }
1097
+
1098
+ newCell.click(function (event) {
1099
+
1100
+ if ( ! ( $(event.target).is('.preview-cell') || $(event.target).is('.preview-cell-in') ) ) {
1101
+ return;
1102
+ }
1103
+
1104
+ var cell = $(event.target);
1105
+ cell.closest('.row-preview').find('.preview-cell .preview-cell-in').removeClass('cell-selected');
1106
+ cell.addClass('cell-selected');
1107
+
1108
+ this.openSelectedCellStyles();
1109
+
1110
+ }.bind(this));
1111
+
1112
+ // Make this row weight click editable
1113
+ newCell.find('.preview-cell-weight').click(function (ci) {
1114
+
1115
+ // Disable the draggable while entering values
1116
+ thisDialog.$('.resize-handle').css('pointer-event', 'none').draggable('disable');
1117
+
1118
+ rowPreview.find('.preview-cell-weight').each(function () {
1119
+ var $$ = jQuery(this).hide();
1120
+ $('<input type="text" class="preview-cell-weight-input no-user-interacted" />')
1121
+ .val(parseFloat($$.html())).insertAfter($$)
1122
+ .focus(function () {
1123
+ clearTimeout(timeout);
1124
+ })
1125
+ .keyup(function (e) {
1126
+ if (e.keyCode !== 9) {
1127
+ // Only register the interaction if the user didn't press tab
1128
+ $(this).removeClass('no-user-interacted');
1129
+ }
1130
+
1131
+ // Enter is clicked
1132
+ if (e.keyCode === 13) {
1133
+ e.preventDefault();
1134
+ $(this).blur();
1135
+ }
1136
+ })
1137
+ .keydown(function (e) {
1138
+ if (e.keyCode === 9) {
1139
+ e.preventDefault();
1140
+
1141
+ // Tab will always cycle around the row inputs
1142
+ var inputs = rowPreview.find('.preview-cell-weight-input');
1143
+ var i = inputs.index($(this));
1144
+ if (i === inputs.length - 1) {
1145
+ inputs.eq(0).focus().select();
1146
+ } else {
1147
+ inputs.eq(i + 1).focus().select();
1148
+ }
1149
+ }
1150
+ })
1151
+ .blur(function () {
1152
+ rowPreview.find('.preview-cell-weight-input').each(function (i, el) {
1153
+ if (isNaN(parseFloat($(el).val()))) {
1154
+ $(el).val(Math.floor(thisDialog.row.cells.at(i).get('weight') * 1000) / 10);
1155
+ }
1156
+ });
1157
+
1158
+ timeout = setTimeout(function () {
1159
+ // If there are no weight inputs, then skip this
1160
+ if (rowPreview.find('.preview-cell-weight-input').length === 0) {
1161
+ return false;
1162
+ }
1163
+
1164
+ // Go through all the inputs
1165
+ var rowWeights = [],
1166
+ rowChanged = [],
1167
+ changedSum = 0,
1168
+ unchangedSum = 0;
1169
+
1170
+ rowPreview.find('.preview-cell-weight-input').each(function (i, el) {
1171
+ var val = parseFloat($(el).val());
1172
+ if (isNaN(val)) {
1173
+ val = 1 / thisDialog.row.cells.length;
1174
+ } else {
1175
+ val = Math.round(val * 10) / 1000;
1176
+ }
1177
+
1178
+ // Check within 3 decimal points
1179
+ var changed = !$(el).hasClass('no-user-interacted');
1180
+
1181
+ rowWeights.push(val);
1182
+ rowChanged.push(changed);
1183
+
1184
+ if (changed) {
1185
+ changedSum += val;
1186
+ } else {
1187
+ unchangedSum += val;
1188
+ }
1189
+ });
1190
+
1191
+ if (changedSum > 0 && unchangedSum > 0 && (
1192
+ 1 - changedSum
1193
+ ) > 0) {
1194
+ // Balance out the unchanged rows to occupy the weight left over by the changed sum
1195
+ for (var i = 0; i < rowWeights.length; i++) {
1196
+ if (!rowChanged[i]) {
1197
+ rowWeights[i] = (
1198
+ rowWeights[i] / unchangedSum
1199
+ ) * (
1200
+ 1 - changedSum
1201
+ );
1202
+ }
1203
+ }
1204
+ }
1205
+
1206
+ // Last check to ensure total weight is 1
1207
+ var sum = _.reduce(rowWeights, function (memo, num) {
1208
+ return memo + num;
1209
+ });
1210
+ rowWeights = rowWeights.map(function (w) {
1211
+ return w / sum;
1212
+ });
1213
+
1214
+ // Set the new cell weights and regenerate the preview.
1215
+ if (Math.min.apply(Math, rowWeights) > 0.01) {
1216
+ thisDialog.row.cells.each(function (cell, i) {
1217
+ cell.set('weight', rowWeights[i]);
1218
+ });
1219
+ }
1220
+
1221
+ // Now lets animate the cells into their new widths
1222
+ rowPreview.find('.preview-cell').each(function (i, el) {
1223
+ var cellWeight = thisDialog.row.cells.at(i).get('weight');
1224
+ $(el).animate({'width': Math.round(cellWeight * 1000) / 10 + "%"}, 250);
1225
+ $(el).find('.preview-cell-weight-input').val(Math.round(cellWeight * 1000) / 10);
1226
+ });
1227
+
1228
+ // So the draggable handle is not hidden.
1229
+ rowPreview.find('.preview-cell').css('overflow', 'visible');
1230
+
1231
+ setTimeout(function () {
1232
+ thisDialog.regenerateRowPreview();
1233
+ }, 260);
1234
+
1235
+ }, 100);
1236
+ })
1237
+ .click(function () {
1238
+ $(this).select();
1239
+ });
1240
+ });
1241
+
1242
+ $(this).siblings('.preview-cell-weight-input').select();
1243
+
1244
+ });
1245
+
1246
+ }, this);
1247
+
1248
+ this.openSelectedCellStyles();
1249
+
1250
+ this.trigger('form_loaded', this);
1251
+ },
1252
+
1253
+ getSelectedCellIndex: function() {
1254
+ var selectedIndex = -1;
1255
+ this.$('.preview-cell .preview-cell-in').each(function(index, el) {
1256
+ if($(el).is('.cell-selected')) {
1257
+ selectedIndex = index;
1258
+ }
1259
+ });
1260
+ return selectedIndex;
1261
+ },
1262
+
1263
+ openSelectedCellStyles: function() {
1264
+ if (!_.isUndefined(this.cellStyles)) {
1265
+ if (this.cellStyles.stylesLoaded) {
1266
+ var style = {};
1267
+ try {
1268
+ style = this.getFormValues('.so-sidebar .so-visual-styles.so-cell-styles').style;
1269
+ }
1270
+ catch (err) {
1271
+ console.log('Error retrieving cell styles - ' + err.message);
1272
+ }
1273
+
1274
+ this.cellStyles.model.set('style', style);
1275
+ }
1276
+ this.cellStyles.detach();
1277
+ }
1278
+
1279
+ this.cellStyles = this.getSelectedCellStyles();
1280
+
1281
+ if ( this.cellStyles ) {
1282
+ var $rightSidebar = this.$( '.so-sidebar.so-right-sidebar' );
1283
+ this.cellStyles.attach( $rightSidebar );
1284
+ }
1285
+ },
1286
+
1287
+ getSelectedCellStyles: function () {
1288
+ var cellIndex = this.getSelectedCellIndex();
1289
+ if ( cellIndex > -1 ) {
1290
+ var cellStyles = this.cellStylesCache[cellIndex];
1291
+ if ( !cellStyles ) {
1292
+ cellStyles = new panels.view.styles();
1293
+ cellStyles.model = this.row.cells.at( cellIndex );
1294
+ cellStyles.render( 'cell', this.builder.config.postId, {
1295
+ builderType: this.builder.config.builderType,
1296
+ dialog: this,
1297
+ index: cellIndex,
1298
+ } );
1299
+ this.cellStylesCache[cellIndex] = cellStyles;
1300
+ }
1301
+ }
1302
+
1303
+ return cellStyles;
1304
+ },
1305
+
1306
+ clearCellStylesCache: function () {
1307
+ // Call remove() on all cell styles to remove data, event listeners etc.
1308
+ this.cellStylesCache.forEach(function (cellStyles) {
1309
+ cellStyles.remove();
1310
+ });
1311
+ this.cellStylesCache = [];
1312
+ },
1313
+
1314
+ /**
1315
+ * Visually scale the row widths based on the cell weights
1316
+ */
1317
+ scaleRowWidths: function () {
1318
+ var thisDialog = this;
1319
+ this.$('.row-preview .preview-cell').each(function (i, el) {
1320
+ var cell = thisDialog.row.cells.at(i);
1321
+ $(el)
1322
+ .css('width', cell.get('weight') * 100 + "%")
1323
+ .find('.preview-cell-weight').html(Math.round(cell.get('weight') * 1000) / 10);
1324
+ });
1325
+ },
1326
+
1327
+ /**
1328
+ * Get the weights from the
1329
+ */
1330
+ setCellsFromForm: function () {
1331
+
1332
+ try {
1333
+ var f = {
1334
+ 'cells': parseInt(this.$('.row-set-form input[name="cells"]').val()),
1335
+ 'ratio': parseFloat(this.$('.row-set-form select[name="ratio"]').val()),
1336
+ 'direction': this.$('.row-set-form select[name="ratio_direction"]').val()
1337
+ };
1338
+
1339
+ if (_.isNaN(f.cells)) {
1340
+ f.cells = 1;
1341
+ }
1342
+ if (isNaN(f.ratio)) {
1343
+ f.ratio = 1;
1344
+ }
1345
+ if (f.cells < 1) {
1346
+ f.cells = 1;
1347
+ this.$('.row-set-form input[name="cells"]').val(f.cells);
1348
+ }
1349
+ else if (f.cells > 12) {
1350
+ f.cells = 12;
1351
+ this.$('.row-set-form input[name="cells"]').val(f.cells);
1352
+ }
1353
+
1354
+ this.$('.row-set-form select[name="ratio"]').val(f.ratio);
1355
+
1356
+ var cells = [];
1357
+ var cellCountChanged = (
1358
+ this.row.cells.length !== f.cells
1359
+ );
1360
+
1361
+ // Now, lets create some cells
1362
+ var currentWeight = 1;
1363
+ for (var i = 0; i < f.cells; i++) {
1364
+ cells.push(currentWeight);
1365
+ currentWeight *= f.ratio;
1366
+ }
1367
+
1368
+ // Now lets make sure that the row weights add up to 1
1369
+
1370
+ var totalRowWeight = _.reduce(cells, function (memo, weight) {
1371
+ return memo + weight;
1372
+ });
1373
+ cells = _.map(cells, function (cell) {
1374
+ return cell / totalRowWeight;
1375
+ });
1376
+
1377
+ // Don't return cells that are too small
1378
+ cells = _.filter(cells, function (cell) {
1379
+ return cell > 0.01;
1380
+ });
1381
+
1382
+ if (f.direction === 'left') {
1383
+ cells = cells.reverse();
1384
+ }
1385
+
1386
+ // Discard deleted cells.
1387
+ this.row.cells = new panels.collection.cells(this.row.cells.first(cells.length));
1388
+
1389
+ _.each(cells, function (cellWeight, index) {
1390
+ var cell = this.row.cells.at(index);
1391
+ if (!cell) {
1392
+ cell = new panels.model.cell({weight: cellWeight, row: this.model});
1393
+ this.row.cells.add(cell);
1394
+ } else {
1395
+ cell.set('weight', cellWeight);
1396
+ }
1397
+ }.bind(this));
1398
+
1399
+ this.row.ratio = f.ratio;
1400
+ this.row.ratio_direction = f.direction;
1401
+
1402
+ if (cellCountChanged) {
1403
+ this.regenerateRowPreview();
1404
+ } else {
1405
+ var thisDialog = this;
1406
+
1407
+ // Now lets animate the cells into their new widths
1408
+ this.$('.preview-cell').each(function (i, el) {
1409
+ var cellWeight = thisDialog.row.cells.at(i).get('weight');
1410
+ $(el).animate({'width': Math.round(cellWeight * 1000) / 10 + "%"}, 250);
1411
+ $(el).find('.preview-cell-weight').html(Math.round(cellWeight * 1000) / 10);
1412
+ });
1413
+
1414
+ // So the draggable handle is not hidden.
1415
+ this.$('.preview-cell').css('overflow', 'visible');
1416
+
1417
+ setTimeout(function () {
1418
+ thisDialog.regenerateRowPreview();
1419
+ }, 260);
1420
+ }
1421
+ }
1422
+ catch (err) {
1423
+ console.log('Error setting cells - ' + err.message);
1424
+ }
1425
+
1426
+
1427
+ // Remove the button primary class
1428
+ this.$('.row-set-form .so-button-row-set').removeClass('button-primary');
1429
+ },
1430
+
1431
+ /**
1432
+ * Handle a click on the dialog left bar tab
1433
+ */
1434
+ tabClickHandler: function ($t) {
1435
+ if ($t.attr('href') === '#row-layout') {
1436
+ this.$('.so-panels-dialog').addClass('so-panels-dialog-has-right-sidebar');
1437
+ } else {
1438
+ this.$('.so-panels-dialog').removeClass('so-panels-dialog-has-right-sidebar');
1439
+ }
1440
+ },
1441
+
1442
+ /**
1443
+ * Update the current model with what we have in the dialog
1444
+ */
1445
+ updateModel: function (args) {
1446
+ args = _.extend({
1447
+ refresh: true,
1448
+ refreshArgs: null
1449
+ }, args);
1450
+
1451
+ // Set the cells
1452
+ if (!_.isEmpty(this.model)) {
1453
+ this.model.setCells( this.row.cells );
1454
+ this.model.set( 'ratio', this.row.ratio );
1455
+ this.model.set( 'ratio_direction', this.row.ratio_direction );
1456
+ }
1457
+
1458
+ // Update the row styles if they've loaded
1459
+ if (!_.isUndefined(this.styles) && this.styles.stylesLoaded) {
1460
+ // This is an edit dialog, so there are styles
1461
+ var style = {};
1462
+ try {
1463
+ style = this.getFormValues('.so-sidebar .so-visual-styles.so-row-styles').style;
1464
+ }
1465
+ catch (err) {
1466
+ console.log('Error retrieving row styles - ' + err.message);
1467
+ }
1468
+
1469
+ this.model.set('style', style);
1470
+ }
1471
+
1472
+ // Update the cell styles if any are showing.
1473
+ if (!_.isUndefined(this.cellStyles) && this.cellStyles.stylesLoaded) {
1474
+
1475
+ var style = {};
1476
+ try {
1477
+ style = this.getFormValues('.so-sidebar .so-visual-styles.so-cell-styles').style;
1478
+ }
1479
+ catch (err) {
1480
+ console.log('Error retrieving cell styles - ' + err.message);
1481
+ }
1482
+
1483
+ this.cellStyles.model.set('style', style);
1484
+ }
1485
+
1486
+ if (args.refresh) {
1487
+ this.builder.model.refreshPanelsData(args.refreshArgs);
1488
+ }
1489
+ },
1490
+
1491
+ /**
1492
+ * Insert the new row
1493
+ */
1494
+ insertHandler: function () {
1495
+ this.builder.addHistoryEntry('row_added');
1496
+
1497
+ this.updateModel();
1498
+
1499
+ var activeCell = this.builder.getActiveCell({
1500
+ createCell: false,
1501
+ });
1502
+
1503
+ var options = {};
1504
+ if (activeCell !== null) {
1505
+ options.at = this.builder.model.get('rows').indexOf(activeCell.row) + 1;
1506
+ }
1507
+
1508
+ // Set up the model and add it to the builder
1509
+ this.model.collection = this.builder.model.get('rows');
1510
+ this.builder.model.get('rows').add(this.model, options);
1511
+
1512
+ this.closeDialog();
1513
+
1514
+ this.builder.model.refreshPanelsData();
1515
+
1516
+ return false;
1517
+ },
1518
+
1519
+ /**
1520
+ * We'll just save this model and close the dialog
1521
+ */
1522
+ saveHandler: function () {
1523
+ this.builder.addHistoryEntry('row_edited');
1524
+ this.updateModel();
1525
+ this.closeDialog();
1526
+
1527
+ this.builder.model.refreshPanelsData();
1528
+
1529
+ return false;
1530
+ },
1531
+
1532
+ /**
1533
+ * The user clicks delete, so trigger deletion on the row model
1534
+ */
1535
+ deleteHandler: function () {
1536
+ // Trigger a destroy on the model that will happen with a visual indication to the user
1537
+ this.model.trigger('visual_destroy');
1538
+ this.closeDialog({silent: true});
1539
+
1540
+ return false;
1541
+ },
1542
+
1543
+ /**
1544
+ * Duplicate this row
1545
+ */
1546
+ duplicateHandler: function () {
1547
+ this.builder.addHistoryEntry('row_duplicated');
1548
+
1549
+ var duplicateRow = this.model.clone(this.builder.model);
1550
+
1551
+ this.builder.model.get('rows').add( duplicateRow, {
1552
+ at: this.builder.model.get('rows').indexOf(this.model) + 1
1553
+ } );
1554
+
1555
+ this.closeDialog({silent: true});
1556
+
1557
+ return false;
1558
+ },
1559
+
1560
+ closeHandler: function() {
1561
+ this.clearCellStylesCache();
1562
+ if( ! _.isUndefined(this.cellStyles) ) {
1563
+ this.cellStyles = undefined;
1564
+ }
1565
+ },
1566
+
1567
+ });
1568
 
1569
  },{}],9:[function(require,module,exports){
1570
  var panels = window.panels, $ = jQuery;
js/{siteorigin-panels-265.min.js → siteorigin-panels-266.min.js} RENAMED
File without changes
js/{styling-265.js → styling-266.js} RENAMED
File without changes
js/{styling-265.min.js → styling-266.min.js} RENAMED
File without changes
lang/siteorigin-panels.pot CHANGED
@@ -1213,15 +1213,15 @@ msgstr ""
1213
  msgid "Save Settings"
1214
  msgstr ""
1215
 
1216
- #: tmp/siteorigin-panels.php:623
1217
  msgid "Read More"
1218
  msgstr ""
1219
 
1220
- #: tmp/siteorigin-panels.php:755
1221
  msgid "Edit Home Page"
1222
  msgstr ""
1223
 
1224
- #: tmp/siteorigin-panels.php:795, tmp/tpl/js-templates.php:67, tmp/tpl/js-templates.php:71
1225
  msgid "Live Editor"
1226
  msgstr ""
1227
 
1213
  msgid "Save Settings"
1214
  msgstr ""
1215
 
1216
+ #: tmp/siteorigin-panels.php:657
1217
  msgid "Read More"
1218
  msgstr ""
1219
 
1220
+ #: tmp/siteorigin-panels.php:789
1221
  msgid "Edit Home Page"
1222
  msgstr ""
1223
 
1224
+ #: tmp/siteorigin-panels.php:829, tmp/tpl/js-templates.php:67, tmp/tpl/js-templates.php:71
1225
  msgid "Live Editor"
1226
  msgstr ""
1227
 
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Tags: page builder, responsive, widget, widgets, builder, page, admin, gallery, content, cms, pages, post, css, layout, grid
3
  Requires at least: 4.4
4
  Tested up to: 4.9
5
- Stable tag: 2.6.5
6
- Build time: 2018-04-23T10:13:48+02:00
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl.html
9
  Donate link: https://siteorigin.com/downloads/contribution/
@@ -96,6 +96,10 @@ We've tried to ensure that Page Builder is compatible with most plugin widgets.
96
 
97
  == Changelog ==
98
 
 
 
 
 
99
  = 2.6.5 - 23 April 2018 =
100
  * Don't use `mime_content_type` for external layouts if it's not available. Just check file extensions.
101
  * Get correct ID for WooCommerce shop page to allow PB to render correctly.
2
  Tags: page builder, responsive, widget, widgets, builder, page, admin, gallery, content, cms, pages, post, css, layout, grid
3
  Requires at least: 4.4
4
  Tested up to: 4.9
5
+ Stable tag: 2.6.6
6
+ Build time: 2018-04-25T14:59:51+02:00
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl.html
9
  Donate link: https://siteorigin.com/downloads/contribution/
96
 
97
  == Changelog ==
98
 
99
+ = 2.6.6 - 25 April 2018 =
100
+ * Only filter WooCommerce content when on the shop page.
101
+ * Fix Background fallback URL notices.
102
+
103
  = 2.6.5 - 23 April 2018 =
104
  * Don't use `mime_content_type` for external layouts if it's not available. Just check file extensions.
105
  * Get correct ID for WooCommerce shop page to allow PB to render correctly.
siteorigin-panels.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Page Builder by SiteOrigin
4
  Plugin URI: https://siteorigin.com/page-builder/
5
  Description: A drag and drop, responsive page builder that simplifies building your website.
6
- Version: 2.6.5
7
  Author: SiteOrigin
8
  Author URI: https://siteorigin.com
9
  License: GPL3
@@ -11,12 +11,12 @@ License URI: http://www.gnu.org/licenses/gpl.html
11
  Donate link: http://siteorigin.com/page-builder/#donate
12
  */
13
 
14
- define( 'SITEORIGIN_PANELS_VERSION', '2.6.5' );
15
  if ( ! defined( 'SITEORIGIN_PANELS_JS_SUFFIX' ) ) {
16
  define( 'SITEORIGIN_PANELS_JS_SUFFIX', '.min' );
17
  }
18
  define( 'SITEORIGIN_PANELS_CSS_SUFFIX', '.min' );
19
- define( 'SITEORIGIN_PANELS_VERSION_SUFFIX', '-265' );
20
 
21
  require_once plugin_dir_path( __FILE__ ) . 'inc/functions.php';
22
 
@@ -65,7 +65,7 @@ class SiteOrigin_Panels {
65
 
66
  // We need to generate fresh post content
67
  add_filter( 'the_content', array( $this, 'generate_post_content' ) );
68
- add_filter( 'woocommerce_format_content', array( $this, 'generate_post_content' ) );
69
  add_filter( 'wp_enqueue_scripts', array( $this, 'generate_post_css' ) );
70
 
71
  // Content cache has been removed. SiteOrigin_Panels_Cache_Renderer just deletes any existing caches.
@@ -255,6 +255,23 @@ class SiteOrigin_Panels {
255
 
256
  return $panels_data;
257
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
 
259
  /**
260
  * Generate post content for the current post.
3
  Plugin Name: Page Builder by SiteOrigin
4
  Plugin URI: https://siteorigin.com/page-builder/
5
  Description: A drag and drop, responsive page builder that simplifies building your website.
6
+ Version: 2.6.6
7
  Author: SiteOrigin
8
  Author URI: https://siteorigin.com
9
  License: GPL3
11
  Donate link: http://siteorigin.com/page-builder/#donate
12
  */
13
 
14
+ define( 'SITEORIGIN_PANELS_VERSION', '2.6.6' );
15
  if ( ! defined( 'SITEORIGIN_PANELS_JS_SUFFIX' ) ) {
16
  define( 'SITEORIGIN_PANELS_JS_SUFFIX', '.min' );
17
  }
18
  define( 'SITEORIGIN_PANELS_CSS_SUFFIX', '.min' );
19
+ define( 'SITEORIGIN_PANELS_VERSION_SUFFIX', '-266' );
20
 
21
  require_once plugin_dir_path( __FILE__ ) . 'inc/functions.php';
22
 
65
 
66
  // We need to generate fresh post content
67
  add_filter( 'the_content', array( $this, 'generate_post_content' ) );
68
+ add_filter( 'woocommerce_format_content', array( $this, 'generate_woocommerce_content' ) );
69
  add_filter( 'wp_enqueue_scripts', array( $this, 'generate_post_css' ) );
70
 
71
  // Content cache has been removed. SiteOrigin_Panels_Cache_Renderer just deletes any existing caches.
255
 
256
  return $panels_data;
257
  }
258
+
259
+ /**
260
+ * Generate post content for WooCommerce shop page if it's using a PB layout.
261
+ *
262
+ * @param $content
263
+ *
264
+ * @return string
265
+ *
266
+ * @filter woocommerce_format_content
267
+ */
268
+ public function generate_woocommerce_content( $content ) {
269
+ if ( class_exists( 'WooCommerce' ) && is_shop() ) {
270
+ return $this->generate_post_content( $content );
271
+ }
272
+
273
+ return $content;
274
+ }
275
 
276
  /**
277
  * Generate post content for the current post.