Customify – A Theme Customizer Booster - Version 1.6.0

Version Description

  • Added Style Manager Customizer section with theme supports logic
  • Added connected fields logic for easy chaining of Customizer controls
  • Fixed a couple of styling inconsistencies regarding the Customizer
Download this release

Release Info

Developer pixelgrade
Plugin Icon Customify – A Theme Customizer Booster
Version 1.6.0
Comparing to
See all releases

Code changes from version 1.5.7 to 1.6.0

class-pixcustomify.php CHANGED
@@ -215,6 +215,9 @@ class PixCustomifyPlugin {
215
  add_action( 'customize_preview_init', array( $this, 'customizer_live_preview_register_scripts' ), 10 );
216
  add_action( 'customize_preview_init', array( $this, 'customizer_live_preview_enqueue_scripts' ), 99999 );
217
 
 
 
 
218
  // The frontend effects of the Customizer controls
219
  $load_location = $this->get_plugin_setting( 'style_resources_location', 'wp_head' );
220
 
@@ -228,14 +231,6 @@ class PixCustomifyPlugin {
228
  add_action( 'admin_head', array( $this, 'add_customizer_settings_into_wp_editor' ) );
229
  }
230
 
231
- /*
232
- * Jetpack Related
233
- */
234
- add_action( 'init', array( $this, 'set_jetpack_sharing_config') );
235
- add_filter( 'default_option_jetpack_active_modules', array( $this, 'default_jetpack_active_modules' ), 10, 1 );
236
- add_filter( 'jetpack_get_available_modules', array( $this, 'jetpack_hide_blocked_modules' ), 10, 1 );
237
- add_filter( 'default_option_sharing-options', array( $this, 'default_jetpack_sharing_options' ), 10, 1 );
238
-
239
  add_action( 'rest_api_init', array( $this, 'add_rest_routes_api' ) );
240
 
241
  /*
@@ -289,68 +284,6 @@ class PixCustomifyPlugin {
289
  $this->localized['theme_fonts'] = $this->theme_fonts = Customify_Font_Selector::instance()->get_theme_fonts();
290
  }
291
 
292
- function set_jetpack_sharing_config() {
293
- // Allow others to change the sharing config here
294
- $this->jetpack_sharing_default_options = apply_filters ( 'customify_filter_jetpack_sharing_default_options', array() );
295
- }
296
-
297
- /**
298
- * Control the default modules that are activated in Jetpack.
299
- * Use the `customify_filter_jetpack_default_modules` to set your's.
300
- *
301
- * @param array $default The default value to return if the option does not exist
302
- * in the database.
303
- *
304
- * @return array
305
- */
306
- function default_jetpack_active_modules( $default ) {
307
- if ( ! is_array( $default ) ) {
308
- $default = array();
309
- }
310
- $jetpack_default_modules = array();
311
-
312
- $theme_default_modules = get_theme_mod( 'pixelgrade_jetpack_default_active_modules', array() );
313
-
314
- if ( ! is_array( $theme_default_modules ) ) {
315
- return array_merge( $default, $jetpack_default_modules );
316
- }
317
-
318
- foreach ( $theme_default_modules as $module ) {
319
- array_push( $jetpack_default_modules, $module );
320
- }
321
-
322
- return array_merge( $default, $jetpack_default_modules );
323
- }
324
-
325
- /**
326
- * Control the default Jetpack Sharing options.
327
- * Use the `customify_filter_jetpack_sharing_default_options` to set your's.
328
- *
329
- * @param array $default The default value to return if the option does not exist
330
- * in the database.
331
- *
332
- * @return array
333
- */
334
- function default_jetpack_sharing_options( $default ) {
335
- if ( ! is_array( $default ) ) {
336
- $default = array();
337
- }
338
-
339
- return array_merge( $default, $this->jetpack_sharing_default_options );
340
- }
341
-
342
- /**
343
- * Control the modules that are available in Jetpack (hide some of them).
344
- * Use the `customify_filter_jetpack_blocked_modules` filter to set your's.
345
- *
346
- * @param array $modules
347
- *
348
- * @return array
349
- */
350
- function jetpack_hide_blocked_modules( $modules ) {
351
- return array_diff_key( $modules, array_flip( $this->jetpack_blocked_modules ) );
352
- }
353
-
354
  /**
355
  * Fired when the plugin is activated.
356
  * @since 1.0.0
@@ -546,7 +479,7 @@ class PixCustomifyPlugin {
546
  $custom_css .= $this->convert_setting_to_css( $option_id, $option['css'] );
547
  }
548
 
549
- if ( $option['type'] === 'custom_background' ) {
550
  $option['value'] = $this->get_option( $option_id );
551
  $custom_css .= $this->process_custom_background_field_output( $option_id, $option );
552
  }
@@ -589,7 +522,7 @@ class PixCustomifyPlugin {
589
 
590
  foreach ( $this->options_list as $option_id => $options ) {
591
 
592
- if ( $options['type'] === 'custom_background' ) {
593
  $options['value'] = $this->get_option( $option_id );
594
  $custom_background_output = $this->process_custom_background_field_output( $option_id, $options ); ?>
595
 
@@ -606,9 +539,10 @@ class PixCustomifyPlugin {
606
  }
607
 
608
  $this_value = $this->get_option( $option_id );
609
- foreach ( $options['css'] as $key => $properties_set ) { ?>
610
- <style id="dynamic_setting_<?php echo $option_id . '_property_' . str_replace( '-', '_', $properties_set['property'] ); ?>"
611
- type="text/css"><?php
 
612
 
613
  if ( isset( $properties_set['media'] ) && ! empty( $properties_set['media'] ) ) {
614
  echo '@media '. $properties_set['media'] . " {\n";
@@ -621,8 +555,9 @@ class PixCustomifyPlugin {
621
  if ( isset( $properties_set['media'] ) && ! empty( $properties_set['media'] ) ) {
622
  echo "}\n";
623
  } ?>
624
- </style>
625
- <?php }
 
626
  }
627
 
628
  if ( ! empty( $this->media_queries ) ) {
@@ -691,26 +626,35 @@ class PixCustomifyPlugin {
691
  }
692
 
693
  // shim the time when this was an array
 
694
  if ( is_array( $font['value'] ) ) {
695
  $font['value'] = stripslashes_deep( $font['value'] );
696
  $font['value'] = json_encode( $font['value'] );
697
  }
698
 
699
- $value = json_decode( wp_unslash( PixCustomifyPlugin::decodeURIComponent( $font['value'] ) ), true );
 
 
 
700
 
701
- // in case the value is still null, try default value(mostly for google fonts)
702
- if ( ! is_array( $value ) || $value === null ) {
703
  $value = $this->get_font_defaults_value( str_replace( '"', '', $font['value'] ) );
704
  }
705
 
706
- //bail if by this time we don't have a value of some sort
707
  if ( empty( $value ) ) {
708
  continue;
709
  }
710
 
711
- //Handle special logic for when the $value array is not an associative array
712
  if ( ! $this->is_assoc( $value ) ) {
713
- $value = $this->process_a_not_associative_font_default( $value );
 
 
 
 
 
714
  }
715
 
716
  if ( isset( $value['font_family'] ) && isset( $value['type'] ) && $value['type'] == 'google' ) {
@@ -787,21 +731,31 @@ class PixCustomifyPlugin {
787
  }
788
 
789
  if ( isset( $font['selector'] ) && isset( $font['value'] ) && ! empty( $font['value'] ) ) {
 
 
 
 
 
790
 
791
- $value = json_decode( PixCustomifyPlugin::decodeURIComponent( $font['value'] ), true );
792
- // in case the value is still null, try default value(mostly for google fonts)
793
  if ( $value === null ) {
794
  $value = $this->get_font_defaults_value( $font['value'] );
795
  }
796
 
797
- // shim the old case when the default was only the font name
798
- if ( is_string( $value ) && ! empty( $value ) ) {
799
  $value = array( 'font_family' => $value );
800
  }
801
 
802
- //Handle special logic for when the $value array is not an associative array
803
  if ( ! $this->is_assoc( $value ) ) {
804
- $value = $this->process_a_not_associative_font_default( $value );
 
 
 
 
 
805
  }
806
 
807
  $selected_variant = '';
@@ -815,23 +769,23 @@ class PixCustomifyPlugin {
815
 
816
  // First handle the case where we have the font-family in the selected variant (usually this means a custom font from our Fonto plugin)
817
  if ( ! empty( $selected_variant ) && is_array( $selected_variant ) && ! empty( $selected_variant['font-family'] ) ) {
818
- //the variant's font-family
819
  echo $font['selector'] . " {\nfont-family: " . $selected_variant['font-family'] . ";\n";
820
 
821
  if ( ! $load_all_weights ) {
822
- // if this is a custom font (like from our plugin Fonto) with individual styles & weights - i.e. the font-family says it all
823
  // we need to "force" the font-weight and font-style
824
  if ( ! empty( $value['type'] ) && 'custom_individual' == $value['type'] ) {
825
  $selected_variant['font-weight'] = '400 !important';
826
  $selected_variant['font-style'] = 'normal !important';
827
  }
828
 
829
- // output the font weight, if available
830
  if ( ! empty( $selected_variant['font-weight'] ) ) {
831
  echo "font-weight: " . $selected_variant['font-weight'] . ";\n";
832
  }
833
 
834
- // output the font style, if available
835
  if ( ! empty( $selected_variant['font-style'] ) ) {
836
  echo "font-style: " . $selected_variant['font-style'] . ";\n";
837
  }
@@ -839,7 +793,7 @@ class PixCustomifyPlugin {
839
 
840
  echo "}\n";
841
  } elseif ( isset( $value['font_family'] ) ) {
842
- // the selected font family
843
  echo $font['selector'] . " {\n font-family: " . $value['font_family'] . ";\n";
844
 
845
  if ( ! empty( $selected_variant ) && ! $load_all_weights ) {
@@ -877,12 +831,16 @@ class PixCustomifyPlugin {
877
  * Handle special logic for when the $value array is not an associative array
878
  * Return a new associative array with proper keys
879
  */
880
- public function process_a_not_associative_font_default( $value ) {
 
 
 
 
881
 
882
  $new_value = array();
883
 
884
- //Let's determine some type of font
885
- if ( ! isset( $value[2] ) || ( isset( $value[2] ) && 'google' == $value[2] ) ) {
886
  $new_value = $this->get_font_defaults_value( $value[0] );
887
  } else {
888
  $new_value['type'] = $value[2];
@@ -892,13 +850,13 @@ class PixCustomifyPlugin {
892
  $new_value = array();
893
  }
894
 
895
- //The first entry is the font-family
896
  if ( isset( $value[0] ) ) {
897
  $new_value['font_family'] = $value[0];
898
  }
899
 
900
- //In case we don't have an associative array
901
- //The second entry is the variants
902
  if ( isset( $value[1] ) ) {
903
  $new_value['selected_variants'] = $value[1];
904
  }
@@ -1150,7 +1108,7 @@ class PixCustomifyPlugin {
1150
  if ( ! empty ( $customizer_settings ) ) {
1151
 
1152
  // first check the very needed options name
1153
- if ( ! isset ( $customizer_settings['opt-name'] ) || empty( $customizer_settings['opt-name'] ) ) {
1154
  return;
1155
  }
1156
  $options_name = $customizer_settings['opt-name'];
@@ -1159,11 +1117,17 @@ class PixCustomifyPlugin {
1159
  // let's check if we have sections or panels
1160
  if ( isset( $customizer_settings['panels'] ) && ! empty( $customizer_settings['panels'] ) ) {
1161
 
1162
- foreach ( $customizer_settings['panels'] as $panel_id => $panel_settings ) {
1163
 
1164
- if ( ! empty( $panel_id ) && isset( $panel_settings['sections'] ) && ! empty( $panel_settings['sections'] ) ) {
 
 
 
 
 
 
 
1165
 
1166
- $panel_id = $options_name . '[' . $panel_id . ']';
1167
  $panel_args = array(
1168
  'priority' => 10,
1169
  'capability' => 'edit_theme_options',
@@ -1171,23 +1135,23 @@ class PixCustomifyPlugin {
1171
  'description' => __( 'Description of what this panel does.', 'pixcustomify' ),
1172
  );
1173
 
1174
- if ( isset( $panel_settings['priority'] ) && ! empty( $panel_settings['priority'] ) ) {
1175
- $panel_args['priority'] = $panel_settings['priority'];
1176
  }
1177
 
1178
- if ( isset( $panel_settings['title'] ) && ! empty( $panel_settings['title'] ) ) {
1179
- $panel_args['title'] = $panel_settings['title'];
1180
  }
1181
 
1182
- if ( isset( $panel_settings['description'] ) && ! empty( $panel_settings['description'] ) ) {
1183
- $panel_args[10] = $panel_settings['description'];
1184
  }
1185
 
1186
  $wp_customize->add_panel( $panel_id, $panel_args );
1187
 
1188
- foreach ( $panel_settings['sections'] as $section_id => $section_settings ) {
1189
- if ( ! empty( $section_id ) && isset( $section_settings['options'] ) && ! empty( $section_settings['options'] ) ) {
1190
- $this->register_section( $panel_id, $section_id, $options_name, $section_settings, $wp_customize );
1191
  }
1192
  }
1193
  }
@@ -1196,9 +1160,9 @@ class PixCustomifyPlugin {
1196
 
1197
  if ( isset( $customizer_settings['sections'] ) && ! empty( $customizer_settings['sections'] ) ) {
1198
 
1199
- foreach ( $customizer_settings['sections'] as $section_id => $section_settings ) {
1200
- if ( ! empty( $section_id ) && isset( $section_settings['options'] ) && ! empty( $section_settings['options'] ) ) {
1201
- $this->register_section( $panel_id = false, $section_id, $options_name, $section_settings, $wp_customize );
1202
  }
1203
  }
1204
  }
@@ -1268,57 +1232,68 @@ class PixCustomifyPlugin {
1268
  * @param string $panel_id
1269
  * @param string $section_key
1270
  * @param string $options_name
1271
- * @param array $section_settings
1272
  * @param WP_Customize_Manager $wp_customize
1273
  */
1274
- protected function register_section( $panel_id, $section_key, $options_name, $section_settings, $wp_customize ) {
1275
 
1276
  if ( isset( $this->plugin_settings['disable_customify_sections'] ) && isset( $this->plugin_settings['disable_customify_sections'][ $section_key ] ) ) {
1277
  return;
1278
  }
1279
 
1280
  // Merge the section settings with the defaults
1281
- $section_args = wp_parse_args( $section_settings, array(
1282
  'priority' => 10,
1283
  'panel' => $panel_id,
1284
  'capability' => 'edit_theme_options',
1285
  'theme_supports' => '',
1286
- 'title' => __( 'Title Section is required', 'customify' ),
1287
  'description' => '',
1288
  'type' => 'default',
1289
  'description_hidden' => false,
1290
  ) );
1291
- $section_id = $options_name . '[' . $section_key . ']';
 
 
 
 
 
 
1292
 
1293
  // Add the new section to the Customizer
1294
  $wp_customize->add_section( $section_id, $section_args );
1295
 
1296
  // Now go through each section option and add the fields
1297
- foreach ( $section_settings['options'] as $option_id => $option_config ) {
1298
 
1299
  if ( empty( $option_id ) || ! isset( $option_config['type'] ) ) {
1300
  continue;
1301
  }
1302
 
1303
- $option_id = $options_name . '[' . $option_id . ']';
 
 
 
 
 
1304
 
1305
- $this->register_field( $section_id, $option_id, $option_config, $wp_customize );
1306
  }
1307
 
1308
  }
1309
 
1310
  /**
1311
- * Register a Customizer field
1312
  *
1313
  * @see WP_Customize_Setting
1314
  * @see WP_Customize_Control
1315
  *
1316
  * @param string $section_id
1317
  * @param string $setting_id
1318
- * @param array $setting_config
1319
  * @param WP_Customize_Manager $wp_customize
1320
  */
1321
- protected function register_field( $section_id, $setting_id, $setting_config, $wp_customize ) {
1322
 
1323
  $add_control = true;
1324
  // defaults
@@ -1328,32 +1303,38 @@ class PixCustomifyPlugin {
1328
  'transport' => 'refresh',
1329
  );
1330
  $control_args = array(
 
1331
  'label' => '',
1332
  'section' => $section_id,
1333
  'settings' => $setting_id,
1334
  );
1335
 
1336
- $this->localized['settings'][ $setting_id ] = $setting_config;
1337
 
1338
  // sanitize settings
1339
- if ( ( isset( $setting_config['live'] ) && $setting_config['live'] ) || $setting_config['type'] === 'font' ) {
1340
  $setting_args['transport'] = 'postMessage';
1341
  }
1342
 
1343
- if ( isset( $setting_config['default'] ) ) {
1344
- $setting_args['default'] = $setting_config['default'];
1345
  }
1346
 
1347
- if ( isset( $setting_config['capability'] ) && ! empty( $setting_config['capability'] ) ) {
1348
- $setting_args['capability'] = $setting_config['capability'];
1349
  }
1350
 
1351
- if ( $this->plugin_settings['values_store_mod'] == 'option' ) {
 
 
 
 
 
1352
  $setting_args['type'] = 'option';
1353
  }
1354
 
1355
  // if we arrive here this means we have a custom field control
1356
- switch ( $setting_config['type'] ) {
1357
 
1358
  case 'checkbox':
1359
 
@@ -1364,39 +1345,39 @@ class PixCustomifyPlugin {
1364
  break;
1365
  }
1366
 
1367
- if ( isset( $setting_config['sanitize_callback'] ) && ! empty( $setting_config['sanitize_callback'] ) && function_exists( $setting_config['sanitize_callback'] ) ) {
1368
- $setting_args['sanitize_callback'] = $setting_config['sanitize_callback'];
1369
  }
1370
 
1371
- // and add it
1372
  $wp_customize->add_setting( $setting_id, $setting_args );
1373
 
1374
  // now sanitize the control
1375
- if ( isset( $setting_config['label'] ) && ! empty( $setting_config['label'] ) ) {
1376
- $control_args['label'] = $setting_config['label'];
1377
  }
1378
 
1379
- if ( isset( $setting_config['priority'] ) && ! empty( $setting_config['priority'] ) ) {
1380
- $control_args['priority'] = $setting_config['priority'];
1381
  }
1382
 
1383
- if ( isset( $setting_config['desc'] ) && ! empty( $setting_config['desc'] ) ) {
1384
- $control_args['description'] = $setting_config['desc'];
1385
  }
1386
 
1387
- if ( isset( $setting_config['active_callback'] ) && ! empty( $setting_config['active_callback'] ) ) {
1388
- $control_args['active_callback'] = $setting_config['active_callback'];
1389
  }
1390
 
1391
 
1392
- $control_args['type'] = $setting_config['type'];
1393
 
1394
  // select the control type
1395
  // but first init a default
1396
  $control_class_name = 'Pix_Customize_Text_Control';
1397
 
1398
- // if is a standard wp field type call it here and skip the rest
1399
- if ( in_array( $setting_config['type'], array(
1400
  'checkbox',
1401
  'dropdown-pages',
1402
  'url',
@@ -1409,36 +1390,36 @@ class PixCustomifyPlugin {
1409
  $wp_customize->add_control( $setting_id . '_control', $control_args );
1410
 
1411
  return;
1412
- } elseif ( in_array( $setting_config['type'], array(
1413
  'radio',
1414
  'select'
1415
- ) ) && isset( $setting_config['choices'] ) && ! empty( $setting_config['choices'] )
1416
  ) {
1417
- $control_args['choices'] = $setting_config['choices'];
1418
  $wp_customize->add_control( $setting_id . '_control', $control_args );
1419
 
1420
  return;
1421
- } elseif ( in_array( $setting_config['type'], array( 'range' ) ) && isset( $setting_config['input_attrs'] ) && ! empty( $setting_config['input_attrs'] ) ) {
1422
 
1423
- $control_args['input_attrs'] = $setting_config['input_attrs'];
1424
 
1425
  $wp_customize->add_control( $setting_id . '_control', $control_args );
1426
  }
1427
 
1428
- // if we arrive here this means we have a custom field control
1429
- switch ( $setting_config['type'] ) {
1430
 
1431
  case 'text':
1432
- if ( isset( $setting_config['live'] ) ) {
1433
- $control_args['live'] = $setting_config['live'];
1434
  }
1435
 
1436
  $control_class_name = 'Pix_Customize_Text_Control';
1437
  break;
1438
 
1439
  case 'textarea':
1440
- if ( isset( $setting_config['live'] ) ) {
1441
- $control_args['live'] = $setting_config['live'];
1442
  }
1443
 
1444
  $control_class_name = 'Pix_Customize_Textarea_Control';
@@ -1453,12 +1434,12 @@ class PixCustomifyPlugin {
1453
  break;
1454
 
1455
  case 'ace_editor':
1456
- if ( isset( $setting_config['live'] ) ) {
1457
- $control_args['live'] = $setting_config['live'];
1458
  }
1459
 
1460
- if ( isset( $setting_config['editor_type'] ) ) {
1461
- $control_args['editor_type'] = $setting_config['editor_type'];
1462
  }
1463
 
1464
  $control_class_name = 'Pix_Customize_Ace_Editor_Control';
@@ -1477,28 +1458,28 @@ class PixCustomifyPlugin {
1477
  break;
1478
 
1479
  case 'custom_background':
1480
- if ( isset( $setting_config['field'] ) ) {
1481
- $control_args['field'] = $setting_config['field'];
1482
  }
1483
 
1484
  $control_class_name = 'Pix_Customize_Background_Control';
1485
  break;
1486
 
1487
  case 'cropped_media':
1488
- if ( isset( $setting_config['width'] ) ) {
1489
- $control_args['width'] = $setting_config['width'];
1490
  }
1491
 
1492
- if ( isset( $setting_config['height'] ) ) {
1493
- $control_args['height'] = $setting_config['height'];
1494
  }
1495
 
1496
- if ( isset( $setting_config['flex_width'] ) ) {
1497
- $control_args['flex_width'] = $setting_config['flex_width'];
1498
  }
1499
 
1500
- if ( isset( $setting_config['flex_height'] ) ) {
1501
- $control_args['flex_height'] = $setting_config['flex_height'];
1502
  }
1503
 
1504
  $control_class_name = 'WP_Customize_Cropped_Image_Control';
@@ -1515,33 +1496,32 @@ class PixCustomifyPlugin {
1515
 
1516
  $control_class_name = 'Pix_Customize_Typography_Control';
1517
 
1518
- if ( isset( $setting_config['backup'] ) ) {
1519
- $control_args['backup'] = $setting_config['backup'];
1520
  }
1521
 
1522
- if ( isset( $setting_config['font_weight'] ) ) {
1523
- $control_args['font_weight'] = $setting_config['font_weight'];
1524
  }
1525
 
1526
- if ( isset( $setting_config['subsets'] ) ) {
1527
- $control_args['subsets'] = $setting_config['subsets'];
1528
  }
1529
 
1530
- if ( isset( $setting_config['recommended'] ) ) {
1531
- $control_args['recommended'] = array_flip( $setting_config['recommended'] );
1532
  }
1533
 
1534
- if ( isset( $setting_config['load_all_weights'] ) ) {
1535
- $control_args['load_all_weights'] = $setting_config['load_all_weights'];
1536
  }
1537
 
1538
- if ( isset( $setting_config['default'] ) ) {
1539
- $control_args['default'] = $setting_config['default'];
1540
  }
1541
 
1542
  break;
1543
 
1544
- // Custom types
1545
  case 'font' :
1546
  $use_typography = $this->get_plugin_setting( 'typography', '1' );
1547
 
@@ -1552,60 +1532,60 @@ class PixCustomifyPlugin {
1552
 
1553
  $control_class_name = 'Pix_Customize_Font_Control';
1554
 
1555
- if ( isset( $setting_config['backup'] ) ) {
1556
- $control_args['backup'] = $setting_config['backup'];
1557
  }
1558
 
1559
- if ( isset( $setting_config['font_weight'] ) ) {
1560
- $control_args['font_weight'] = $setting_config['font_weight'];
1561
  }
1562
 
1563
- if ( isset( $setting_config['subsets'] ) ) {
1564
- $control_args['subsets'] = $setting_config['subsets'];
1565
  }
1566
 
1567
- if ( isset( $setting_config['recommended'] ) ) {
1568
- $control_args['recommended'] = array_flip( $setting_config['recommended'] );
1569
  }
1570
 
1571
- if ( isset( $setting_config['load_all_weights'] ) ) {
1572
- $control_args['load_all_weights'] = $setting_config['load_all_weights'];
1573
  }
1574
 
1575
- if ( isset( $setting_config['default'] ) ) {
1576
- $control_args['default'] = $setting_config['default'];
1577
  }
1578
 
1579
- if ( isset( $setting_config['fields'] ) ) {
1580
- $control_args['fields'] = $setting_config['fields'];
1581
  }
1582
  $control_args['live'] = true;
1583
 
1584
  break;
1585
 
1586
  case 'select2' :
1587
- if ( ! isset( $setting_config['choices'] ) || empty( $setting_config['choices'] ) ) {
1588
  return;
1589
  }
1590
 
1591
- $control_args['choices'] = $setting_config['choices'];
1592
 
1593
  $control_class_name = 'Pix_Customize_Select2_Control';
1594
  break;
1595
 
1596
  case 'preset' :
1597
- if ( ! isset( $setting_config['choices'] ) || empty( $setting_config['choices'] ) ) {
1598
  return;
1599
  }
1600
 
1601
- $control_args['choices'] = $setting_config['choices'];
1602
 
1603
- if ( isset( $setting_config['choices_type'] ) || ! empty( $setting_config['choices_type'] ) ) {
1604
- $control_args['choices_type'] = $setting_config['choices_type'];
1605
  }
1606
 
1607
- if ( isset( $setting_config['desc'] ) || ! empty( $setting_config['desc'] ) ) {
1608
- $control_args['description'] = $setting_config['desc'];
1609
  }
1610
 
1611
 
@@ -1613,18 +1593,18 @@ class PixCustomifyPlugin {
1613
  break;
1614
 
1615
  case 'radio_image' :
1616
- if ( ! isset( $setting_config['choices'] ) || empty( $setting_config['choices'] ) ) {
1617
  return;
1618
  }
1619
 
1620
- $control_args['choices'] = $setting_config['choices'];
1621
 
1622
- if ( isset( $setting_config['choices_type'] ) || ! empty( $setting_config['choices_type'] ) ) {
1623
- $control_args['choices_type'] = $setting_config['choices_type'];
1624
  }
1625
 
1626
- if ( isset( $setting_config['desc'] ) || ! empty( $setting_config['desc'] ) ) {
1627
- $control_args['description'] = $setting_config['desc'];
1628
  }
1629
 
1630
 
@@ -1632,37 +1612,37 @@ class PixCustomifyPlugin {
1632
  break;
1633
 
1634
  case 'button' :
1635
- if ( ! isset( $setting_config['action'] ) || empty( $setting_config['action'] ) ) {
1636
  return;
1637
  }
1638
 
1639
- $control_args['action'] = $setting_config['action'];
1640
 
1641
  $control_class_name = 'Pix_Customize_Button_Control';
1642
 
1643
  break;
1644
 
1645
  case 'html' :
1646
- if ( isset( $setting_config['html'] ) || ! empty( $setting_config['html'] ) ) {
1647
- $control_args['html'] = $setting_config['html'];
1648
  }
1649
 
1650
  $control_class_name = 'Pix_Customize_HTML_Control';
1651
  break;
1652
 
1653
  case 'import_demo_data' :
1654
- if ( isset( $setting_config['html'] ) || ! empty( $setting_config['html'] ) ) {
1655
- $control_args['html'] = $setting_config['html'];
1656
  }
1657
 
1658
- if ( ! isset( $setting_config['label'] ) || empty( $setting_config['label'] ) ) {
1659
  $control_args['label'] = esc_html__( 'Import', 'customify' );
1660
  } else {
1661
- $control_args['label'] = $setting_config['label'];
1662
  }
1663
 
1664
- if ( isset( $setting_config['notices'] ) && ! empty( $setting_config['notices'] ) ) {
1665
- $control_args['notices'] = $setting_config['notices'];
1666
  }
1667
 
1668
  $control_class_name = 'Pix_Customize_Import_Demo_Data_Control';
@@ -1710,6 +1690,89 @@ class PixCustomifyPlugin {
1710
  }
1711
  }
1712
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1713
  public function get_base_path() {
1714
  return plugin_dir_path( $this->file );
1715
  }
@@ -1903,6 +1966,50 @@ class PixCustomifyPlugin {
1903
  return false;
1904
  }
1905
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1906
  protected function get_config() {
1907
  if ( file_exists( $this->get_base_path() . 'plugin-config.php' ) ) {
1908
  return include( $this->get_base_path() . 'plugin-config.php' );
@@ -2021,7 +2128,7 @@ class PixCustomifyPlugin {
2021
  * @return string
2022
  */
2023
  public static function decodeURIComponent( $str ) {
2024
- //if we get an array we just let it be
2025
  if ( is_string( $str ) ) {
2026
  $revert = array( '!' => '%21', '*' => '%2A', "'" => '%27', '(' => '%28', ')' => '%29' );
2027
  $str = rawurldecode( strtr( $str, $revert ) );
215
  add_action( 'customize_preview_init', array( $this, 'customizer_live_preview_register_scripts' ), 10 );
216
  add_action( 'customize_preview_init', array( $this, 'customizer_live_preview_enqueue_scripts' ), 99999 );
217
 
218
+ // Add extra settings data to _wpCustomizeSettings.settings of the parent window.
219
+ add_action( 'customize_controls_print_footer_scripts', array( $this, 'customize_pane_settings_additional_data' ), 10000 );
220
+
221
  // The frontend effects of the Customizer controls
222
  $load_location = $this->get_plugin_setting( 'style_resources_location', 'wp_head' );
223
 
231
  add_action( 'admin_head', array( $this, 'add_customizer_settings_into_wp_editor' ) );
232
  }
233
 
 
 
 
 
 
 
 
 
234
  add_action( 'rest_api_init', array( $this, 'add_rest_routes_api' ) );
235
 
236
  /*
284
  $this->localized['theme_fonts'] = $this->theme_fonts = Customify_Font_Selector::instance()->get_theme_fonts();
285
  }
286
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
287
  /**
288
  * Fired when the plugin is activated.
289
  * @since 1.0.0
479
  $custom_css .= $this->convert_setting_to_css( $option_id, $option['css'] );
480
  }
481
 
482
+ if ( isset( $option['type'] ) && $option['type'] === 'custom_background' ) {
483
  $option['value'] = $this->get_option( $option_id );
484
  $custom_css .= $this->process_custom_background_field_output( $option_id, $option );
485
  }
522
 
523
  foreach ( $this->options_list as $option_id => $options ) {
524
 
525
+ if ( isset( $options['type'] ) && $options['type'] === 'custom_background' ) {
526
  $options['value'] = $this->get_option( $option_id );
527
  $custom_background_output = $this->process_custom_background_field_output( $option_id, $options ); ?>
528
 
539
  }
540
 
541
  $this_value = $this->get_option( $option_id );
542
+ if ( ! empty( $options['css'] ) ) {
543
+ foreach ( $options['css'] as $key => $properties_set ) { ?>
544
+ <style id="dynamic_setting_<?php echo $option_id . '_property_' . str_replace( '-', '_', $properties_set['property'] ); ?>"
545
+ type="text/css"><?php
546
 
547
  if ( isset( $properties_set['media'] ) && ! empty( $properties_set['media'] ) ) {
548
  echo '@media '. $properties_set['media'] . " {\n";
555
  if ( isset( $properties_set['media'] ) && ! empty( $properties_set['media'] ) ) {
556
  echo "}\n";
557
  } ?>
558
+ </style>
559
+ <?php }
560
+ }
561
  }
562
 
563
  if ( ! empty( $this->media_queries ) ) {
626
  }
627
 
628
  // shim the time when this was an array
629
+ // @todo Is this really needed? Or does it make sense?
630
  if ( is_array( $font['value'] ) ) {
631
  $font['value'] = stripslashes_deep( $font['value'] );
632
  $font['value'] = json_encode( $font['value'] );
633
  }
634
 
635
+ $value = wp_unslash( PixCustomifyPlugin::decodeURIComponent( $font['value'] ) );
636
+ if ( is_string( $value ) ) {
637
+ $value = json_decode( $value, true );
638
+ }
639
 
640
+ // In case the value is still null, try default value (mostly for google fonts)
641
+ if ( $value === null || ! is_array( $value ) ) {
642
  $value = $this->get_font_defaults_value( str_replace( '"', '', $font['value'] ) );
643
  }
644
 
645
+ // Bail if by this time we don't have a value of some sort
646
  if ( empty( $value ) ) {
647
  continue;
648
  }
649
 
650
+ // Handle special logic for when the $value array is not an associative array
651
  if ( ! $this->is_assoc( $value ) ) {
652
+ $value = $this->standardize_non_associative_font_default( $value );
653
+ }
654
+
655
+ // Bail if empty or we don't have an array
656
+ if ( empty( $value ) || ! is_array( $value ) ) {
657
+ continue;
658
  }
659
 
660
  if ( isset( $value['font_family'] ) && isset( $value['type'] ) && $value['type'] == 'google' ) {
731
  }
732
 
733
  if ( isset( $font['selector'] ) && isset( $font['value'] ) && ! empty( $font['value'] ) ) {
734
+ // Make sure that the value is in the proper format
735
+ $value = PixCustomifyPlugin::decodeURIComponent( $font['value'] );
736
+ if ( is_string( $value ) ) {
737
+ $value = json_decode( $value, true );
738
+ }
739
 
740
+ // In case the value is null (most probably because the json_decode failed),
741
+ // try the default value (mostly for google fonts)
742
  if ( $value === null ) {
743
  $value = $this->get_font_defaults_value( $font['value'] );
744
  }
745
 
746
+ // Shim the old case when the default was only the font name
747
+ if ( ! empty( $value ) && is_string( $value ) ) {
748
  $value = array( 'font_family' => $value );
749
  }
750
 
751
+ // Handle special logic for when the $value array is not an associative array
752
  if ( ! $this->is_assoc( $value ) ) {
753
+ $value = $this->standardize_non_associative_font_default( $value );
754
+ }
755
+
756
+ // Bail if empty or we don't have an array
757
+ if ( empty( $value ) || ! is_array( $value ) ) {
758
+ continue;
759
  }
760
 
761
  $selected_variant = '';
769
 
770
  // First handle the case where we have the font-family in the selected variant (usually this means a custom font from our Fonto plugin)
771
  if ( ! empty( $selected_variant ) && is_array( $selected_variant ) && ! empty( $selected_variant['font-family'] ) ) {
772
+ // The variant's font-family
773
  echo $font['selector'] . " {\nfont-family: " . $selected_variant['font-family'] . ";\n";
774
 
775
  if ( ! $load_all_weights ) {
776
+ // If this is a custom font (like from our plugin Fonto) with individual styles & weights - i.e. the font-family says it all
777
  // we need to "force" the font-weight and font-style
778
  if ( ! empty( $value['type'] ) && 'custom_individual' == $value['type'] ) {
779
  $selected_variant['font-weight'] = '400 !important';
780
  $selected_variant['font-style'] = 'normal !important';
781
  }
782
 
783
+ // Output the font weight, if available
784
  if ( ! empty( $selected_variant['font-weight'] ) ) {
785
  echo "font-weight: " . $selected_variant['font-weight'] . ";\n";
786
  }
787
 
788
+ // Output the font style, if available
789
  if ( ! empty( $selected_variant['font-style'] ) ) {
790
  echo "font-style: " . $selected_variant['font-style'] . ";\n";
791
  }
793
 
794
  echo "}\n";
795
  } elseif ( isset( $value['font_family'] ) ) {
796
+ // The selected font family
797
  echo $font['selector'] . " {\n font-family: " . $value['font_family'] . ";\n";
798
 
799
  if ( ! empty( $selected_variant ) && ! $load_all_weights ) {
831
  * Handle special logic for when the $value array is not an associative array
832
  * Return a new associative array with proper keys
833
  */
834
+ public function standardize_non_associative_font_default( $value ) {
835
+ // If the value provided is not array, simply return it
836
+ if ( ! is_array( $value ) ) {
837
+ return $value;
838
+ }
839
 
840
  $new_value = array();
841
 
842
+ // Let's determine some type of font
843
+ if ( ! isset( $value[2] ) || 'google' == $value[2] ) {
844
  $new_value = $this->get_font_defaults_value( $value[0] );
845
  } else {
846
  $new_value['type'] = $value[2];
850
  $new_value = array();
851
  }
852
 
853
+ // The first entry is the font-family
854
  if ( isset( $value[0] ) ) {
855
  $new_value['font_family'] = $value[0];
856
  }
857
 
858
+ // In case we don't have an associative array
859
+ // The second entry is the variants
860
  if ( isset( $value[1] ) ) {
861
  $new_value['selected_variants'] = $value[1];
862
  }
1108
  if ( ! empty ( $customizer_settings ) ) {
1109
 
1110
  // first check the very needed options name
1111
+ if ( empty( $customizer_settings['opt-name'] ) ) {
1112
  return;
1113
  }
1114
  $options_name = $customizer_settings['opt-name'];
1117
  // let's check if we have sections or panels
1118
  if ( isset( $customizer_settings['panels'] ) && ! empty( $customizer_settings['panels'] ) ) {
1119
 
1120
+ foreach ( $customizer_settings['panels'] as $panel_id => $panel_config ) {
1121
 
1122
+ if ( ! empty( $panel_id ) && isset( $panel_config['sections'] ) && ! empty( $panel_config['sections'] ) ) {
1123
+
1124
+ // If we have been explicitly given a panel ID we will use that
1125
+ if ( ! empty( $panel_config['panel_id'] ) ) {
1126
+ $panel_id = $panel_config['panel_id'];
1127
+ } else {
1128
+ $panel_id = $options_name . '[' . $panel_id . ']';
1129
+ }
1130
 
 
1131
  $panel_args = array(
1132
  'priority' => 10,
1133
  'capability' => 'edit_theme_options',
1135
  'description' => __( 'Description of what this panel does.', 'pixcustomify' ),
1136
  );
1137
 
1138
+ if ( isset( $panel_config['priority'] ) && ! empty( $panel_config['priority'] ) ) {
1139
+ $panel_args['priority'] = $panel_config['priority'];
1140
  }
1141
 
1142
+ if ( isset( $panel_config['title'] ) && ! empty( $panel_config['title'] ) ) {
1143
+ $panel_args['title'] = $panel_config['title'];
1144
  }
1145
 
1146
+ if ( isset( $panel_config['description'] ) && ! empty( $panel_config['description'] ) ) {
1147
+ $panel_args['description'] = $panel_config['description'];
1148
  }
1149
 
1150
  $wp_customize->add_panel( $panel_id, $panel_args );
1151
 
1152
+ foreach ( $panel_config['sections'] as $section_id => $section_config ) {
1153
+ if ( ! empty( $section_id ) && isset( $section_config['options'] ) && ! empty( $section_config['options'] ) ) {
1154
+ $this->register_section( $panel_id, $section_id, $options_name, $section_config, $wp_customize );
1155
  }
1156
  }
1157
  }
1160
 
1161
  if ( isset( $customizer_settings['sections'] ) && ! empty( $customizer_settings['sections'] ) ) {
1162
 
1163
+ foreach ( $customizer_settings['sections'] as $section_id => $section_config ) {
1164
+ if ( ! empty( $section_id ) && isset( $section_config['options'] ) && ! empty( $section_config['options'] ) ) {
1165
+ $this->register_section( $panel_id = false, $section_id, $options_name, $section_config, $wp_customize );
1166
  }
1167
  }
1168
  }
1232
  * @param string $panel_id
1233
  * @param string $section_key
1234
  * @param string $options_name
1235
+ * @param array $section_config
1236
  * @param WP_Customize_Manager $wp_customize
1237
  */
1238
+ protected function register_section( $panel_id, $section_key, $options_name, $section_config, $wp_customize ) {
1239
 
1240
  if ( isset( $this->plugin_settings['disable_customify_sections'] ) && isset( $this->plugin_settings['disable_customify_sections'][ $section_key ] ) ) {
1241
  return;
1242
  }
1243
 
1244
  // Merge the section settings with the defaults
1245
+ $section_args = wp_parse_args( $section_config, array(
1246
  'priority' => 10,
1247
  'panel' => $panel_id,
1248
  'capability' => 'edit_theme_options',
1249
  'theme_supports' => '',
1250
+ 'title' => esc_html__( 'Title Section is required', 'customify' ),
1251
  'description' => '',
1252
  'type' => 'default',
1253
  'description_hidden' => false,
1254
  ) );
1255
+
1256
+ // If we have been explicitly given a section ID we will use that
1257
+ if ( ! empty( $section_config['section_id'] ) ) {
1258
+ $section_id = $section_config['section_id'];
1259
+ } else {
1260
+ $section_id = $options_name . '[' . $section_key . ']';
1261
+ }
1262
 
1263
  // Add the new section to the Customizer
1264
  $wp_customize->add_section( $section_id, $section_args );
1265
 
1266
  // Now go through each section option and add the fields
1267
+ foreach ( $section_config['options'] as $option_id => $option_config ) {
1268
 
1269
  if ( empty( $option_id ) || ! isset( $option_config['type'] ) ) {
1270
  continue;
1271
  }
1272
 
1273
+ // If we have been explicitly given a setting ID we will use that
1274
+ if ( ! empty( $option_config['setting_id'] ) ) {
1275
+ $setting_id = $option_config['setting_id'];
1276
+ } else {
1277
+ $setting_id = $options_name . '[' . $option_id . ']';
1278
+ }
1279
 
1280
+ $this->register_field( $section_id, $setting_id, $option_config, $wp_customize );
1281
  }
1282
 
1283
  }
1284
 
1285
  /**
1286
+ * Register a Customizer field (setting and control).
1287
  *
1288
  * @see WP_Customize_Setting
1289
  * @see WP_Customize_Control
1290
  *
1291
  * @param string $section_id
1292
  * @param string $setting_id
1293
+ * @param array $field_config
1294
  * @param WP_Customize_Manager $wp_customize
1295
  */
1296
+ protected function register_field( $section_id, $setting_id, $field_config, $wp_customize ) {
1297
 
1298
  $add_control = true;
1299
  // defaults
1303
  'transport' => 'refresh',
1304
  );
1305
  $control_args = array(
1306
+ 'priority' => 10,
1307
  'label' => '',
1308
  'section' => $section_id,
1309
  'settings' => $setting_id,
1310
  );
1311
 
1312
+ $this->localized['settings'][ $setting_id ] = $field_config;
1313
 
1314
  // sanitize settings
1315
+ if ( ! empty( $field_config['live'] ) || $field_config['type'] === 'font' ) {
1316
  $setting_args['transport'] = 'postMessage';
1317
  }
1318
 
1319
+ if ( isset( $field_config['default'] ) ) {
1320
+ $setting_args['default'] = $field_config['default'];
1321
  }
1322
 
1323
+ if ( ! empty( $field_config['capability'] ) ) {
1324
+ $setting_args['capability'] = $field_config['capability'];
1325
  }
1326
 
1327
+ // If the setting defines it's own type we will respect that, otherwise we will follow the global plugin setting.
1328
+ if ( ! empty( $field_config['setting_type'] ) ) {
1329
+ if ( 'option' === $field_config['setting_type'] ) {
1330
+ $setting_args['type'] = 'option';
1331
+ }
1332
+ } elseif ( $this->plugin_settings['values_store_mod'] === 'option' ) {
1333
  $setting_args['type'] = 'option';
1334
  }
1335
 
1336
  // if we arrive here this means we have a custom field control
1337
+ switch ( $field_config['type'] ) {
1338
 
1339
  case 'checkbox':
1340
 
1345
  break;
1346
  }
1347
 
1348
+ if ( ! empty( $field_config['sanitize_callback'] ) && is_callable( $field_config['sanitize_callback'] ) ) {
1349
+ $setting_args['sanitize_callback'] = $field_config['sanitize_callback'];
1350
  }
1351
 
1352
+ // Add the setting
1353
  $wp_customize->add_setting( $setting_id, $setting_args );
1354
 
1355
  // now sanitize the control
1356
+ if ( ! empty( $field_config['label'] ) ) {
1357
+ $control_args['label'] = $field_config['label'];
1358
  }
1359
 
1360
+ if ( ! empty( $field_config['priority'] ) ) {
1361
+ $control_args['priority'] = $field_config['priority'];
1362
  }
1363
 
1364
+ if ( ! empty( $field_config['desc'] ) ) {
1365
+ $control_args['description'] = $field_config['desc'];
1366
  }
1367
 
1368
+ if ( ! empty( $field_config['active_callback'] ) ) {
1369
+ $control_args['active_callback'] = $field_config['active_callback'];
1370
  }
1371
 
1372
 
1373
+ $control_args['type'] = $field_config['type'];
1374
 
1375
  // select the control type
1376
  // but first init a default
1377
  $control_class_name = 'Pix_Customize_Text_Control';
1378
 
1379
+ // If is a standard wp field type call it here and skip the rest.
1380
+ if ( in_array( $field_config['type'], array(
1381
  'checkbox',
1382
  'dropdown-pages',
1383
  'url',
1390
  $wp_customize->add_control( $setting_id . '_control', $control_args );
1391
 
1392
  return;
1393
+ } elseif ( in_array( $field_config['type'], array(
1394
  'radio',
1395
  'select'
1396
+ ) ) && ! empty( $field_config['choices'] )
1397
  ) {
1398
+ $control_args['choices'] = $field_config['choices'];
1399
  $wp_customize->add_control( $setting_id . '_control', $control_args );
1400
 
1401
  return;
1402
+ } elseif ( in_array( $field_config['type'], array( 'range' ) ) && ! empty( $field_config['input_attrs'] ) ) {
1403
 
1404
+ $control_args['input_attrs'] = $field_config['input_attrs'];
1405
 
1406
  $wp_customize->add_control( $setting_id . '_control', $control_args );
1407
  }
1408
 
1409
+ // If we arrive here this means we have a custom field control.
1410
+ switch ( $field_config['type'] ) {
1411
 
1412
  case 'text':
1413
+ if ( isset( $field_config['live'] ) ) {
1414
+ $control_args['live'] = $field_config['live'];
1415
  }
1416
 
1417
  $control_class_name = 'Pix_Customize_Text_Control';
1418
  break;
1419
 
1420
  case 'textarea':
1421
+ if ( isset( $field_config['live'] ) ) {
1422
+ $control_args['live'] = $field_config['live'];
1423
  }
1424
 
1425
  $control_class_name = 'Pix_Customize_Textarea_Control';
1434
  break;
1435
 
1436
  case 'ace_editor':
1437
+ if ( isset( $field_config['live'] ) ) {
1438
+ $control_args['live'] = $field_config['live'];
1439
  }
1440
 
1441
+ if ( isset( $field_config['editor_type'] ) ) {
1442
+ $control_args['editor_type'] = $field_config['editor_type'];
1443
  }
1444
 
1445
  $control_class_name = 'Pix_Customize_Ace_Editor_Control';
1458
  break;
1459
 
1460
  case 'custom_background':
1461
+ if ( isset( $field_config['field'] ) ) {
1462
+ $control_args['field'] = $field_config['field'];
1463
  }
1464
 
1465
  $control_class_name = 'Pix_Customize_Background_Control';
1466
  break;
1467
 
1468
  case 'cropped_media':
1469
+ if ( isset( $field_config['width'] ) ) {
1470
+ $control_args['width'] = $field_config['width'];
1471
  }
1472
 
1473
+ if ( isset( $field_config['height'] ) ) {
1474
+ $control_args['height'] = $field_config['height'];
1475
  }
1476
 
1477
+ if ( isset( $field_config['flex_width'] ) ) {
1478
+ $control_args['flex_width'] = $field_config['flex_width'];
1479
  }
1480
 
1481
+ if ( isset( $field_config['flex_height'] ) ) {
1482
+ $control_args['flex_height'] = $field_config['flex_height'];
1483
  }
1484
 
1485
  $control_class_name = 'WP_Customize_Cropped_Image_Control';
1496
 
1497
  $control_class_name = 'Pix_Customize_Typography_Control';
1498
 
1499
+ if ( isset( $field_config['backup'] ) ) {
1500
+ $control_args['backup'] = $field_config['backup'];
1501
  }
1502
 
1503
+ if ( isset( $field_config['font_weight'] ) ) {
1504
+ $control_args['font_weight'] = $field_config['font_weight'];
1505
  }
1506
 
1507
+ if ( isset( $field_config['subsets'] ) ) {
1508
+ $control_args['subsets'] = $field_config['subsets'];
1509
  }
1510
 
1511
+ if ( isset( $field_config['recommended'] ) ) {
1512
+ $control_args['recommended'] = array_flip( $field_config['recommended'] );
1513
  }
1514
 
1515
+ if ( isset( $field_config['load_all_weights'] ) ) {
1516
+ $control_args['load_all_weights'] = $field_config['load_all_weights'];
1517
  }
1518
 
1519
+ if ( isset( $field_config['default'] ) ) {
1520
+ $control_args['default'] = $field_config['default'];
1521
  }
1522
 
1523
  break;
1524
 
 
1525
  case 'font' :
1526
  $use_typography = $this->get_plugin_setting( 'typography', '1' );
1527
 
1532
 
1533
  $control_class_name = 'Pix_Customize_Font_Control';
1534
 
1535
+ if ( isset( $field_config['backup'] ) ) {
1536
+ $control_args['backup'] = $field_config['backup'];
1537
  }
1538
 
1539
+ if ( isset( $field_config['font_weight'] ) ) {
1540
+ $control_args['font_weight'] = $field_config['font_weight'];
1541
  }
1542
 
1543
+ if ( isset( $field_config['subsets'] ) ) {
1544
+ $control_args['subsets'] = $field_config['subsets'];
1545
  }
1546
 
1547
+ if ( isset( $field_config['recommended'] ) ) {
1548
+ $control_args['recommended'] = array_flip( $field_config['recommended'] );
1549
  }
1550
 
1551
+ if ( isset( $field_config['load_all_weights'] ) ) {
1552
+ $control_args['load_all_weights'] = $field_config['load_all_weights'];
1553
  }
1554
 
1555
+ if ( isset( $field_config['default'] ) ) {
1556
+ $control_args['default'] = $field_config['default'];
1557
  }
1558
 
1559
+ if ( isset( $field_config['fields'] ) ) {
1560
+ $control_args['fields'] = $field_config['fields'];
1561
  }
1562
  $control_args['live'] = true;
1563
 
1564
  break;
1565
 
1566
  case 'select2' :
1567
+ if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1568
  return;
1569
  }
1570
 
1571
+ $control_args['choices'] = $field_config['choices'];
1572
 
1573
  $control_class_name = 'Pix_Customize_Select2_Control';
1574
  break;
1575
 
1576
  case 'preset' :
1577
+ if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1578
  return;
1579
  }
1580
 
1581
+ $control_args['choices'] = $field_config['choices'];
1582
 
1583
+ if ( isset( $field_config['choices_type'] ) || ! empty( $field_config['choices_type'] ) ) {
1584
+ $control_args['choices_type'] = $field_config['choices_type'];
1585
  }
1586
 
1587
+ if ( isset( $field_config['desc'] ) || ! empty( $field_config['desc'] ) ) {
1588
+ $control_args['description'] = $field_config['desc'];
1589
  }
1590
 
1591
 
1593
  break;
1594
 
1595
  case 'radio_image' :
1596
+ if ( ! isset( $field_config['choices'] ) || empty( $field_config['choices'] ) ) {
1597
  return;
1598
  }
1599
 
1600
+ $control_args['choices'] = $field_config['choices'];
1601
 
1602
+ if ( isset( $field_config['choices_type'] ) || ! empty( $field_config['choices_type'] ) ) {
1603
+ $control_args['choices_type'] = $field_config['choices_type'];
1604
  }
1605
 
1606
+ if ( isset( $field_config['desc'] ) || ! empty( $field_config['desc'] ) ) {
1607
+ $control_args['description'] = $field_config['desc'];
1608
  }
1609
 
1610
 
1612
  break;
1613
 
1614
  case 'button' :
1615
+ if ( ! isset( $field_config['action'] ) || empty( $field_config['action'] ) ) {
1616
  return;
1617
  }
1618
 
1619
+ $control_args['action'] = $field_config['action'];
1620
 
1621
  $control_class_name = 'Pix_Customize_Button_Control';
1622
 
1623
  break;
1624
 
1625
  case 'html' :
1626
+ if ( isset( $field_config['html'] ) || ! empty( $field_config['html'] ) ) {
1627
+ $control_args['html'] = $field_config['html'];
1628
  }
1629
 
1630
  $control_class_name = 'Pix_Customize_HTML_Control';
1631
  break;
1632
 
1633
  case 'import_demo_data' :
1634
+ if ( isset( $field_config['html'] ) || ! empty( $field_config['html'] ) ) {
1635
+ $control_args['html'] = $field_config['html'];
1636
  }
1637
 
1638
+ if ( ! isset( $field_config['label'] ) || empty( $field_config['label'] ) ) {
1639
  $control_args['label'] = esc_html__( 'Import', 'customify' );
1640
  } else {
1641
+ $control_args['label'] = $field_config['label'];
1642
  }
1643
 
1644
+ if ( isset( $field_config['notices'] ) && ! empty( $field_config['notices'] ) ) {
1645
+ $control_args['notices'] = $field_config['notices'];
1646
  }
1647
 
1648
  $control_class_name = 'Pix_Customize_Import_Demo_Data_Control';
1690
  }
1691
  }
1692
 
1693
+ /**
1694
+ * Print JavaScript for adding additional data to _wpCustomizeSettings.settings object of the main window (not the preview window).
1695
+ */
1696
+ public function customize_pane_settings_additional_data() {
1697
+ /**
1698
+ * @global WP_Customize_Manager $wp_customize
1699
+ */
1700
+ global $wp_customize;
1701
+
1702
+ // Without an options name we can't do much.
1703
+ if ( empty( $this->customizer_config['opt-name'] ) ) {
1704
+ return;
1705
+ }
1706
+
1707
+ $options_name = $this->customizer_config['opt-name'];
1708
+ $customizer_settings = $wp_customize->settings();
1709
+ ?>
1710
+ <script type="text/javascript">
1711
+ if ( 'undefined' === typeof _wpCustomizeSettings.settings ) {
1712
+ _wpCustomizeSettings.settings = {};
1713
+ }
1714
+
1715
+ <?php
1716
+ echo "(function ( sAdditional ){\n";
1717
+
1718
+ $options = $this->get_options();
1719
+ foreach ( $options as $option_id => $option_config ) {
1720
+ // If we have been explicitly given a setting ID we will use that
1721
+ if ( ! empty( $option_config['setting_id'] ) ) {
1722
+ $setting_id = $option_config['setting_id'];
1723
+ } else {
1724
+ $setting_id = $options_name . '[' . $option_id . ']';
1725
+ }
1726
+ // @todo Right now we only handle the connected_fields key - make this more dynamic by adding the keys that are not returned by WP_Customize_Setting->json()
1727
+ if ( ! empty( $customizer_settings[ $setting_id ] ) && ! empty( $option_config['connected_fields'] ) ) {
1728
+ // Pass through all the connected fields and make sure the id is in the final format
1729
+ $connected_fields = array();
1730
+ foreach ( $option_config['connected_fields'] as $key => $connected_field_config ) {
1731
+ $connected_field_data = array();
1732
+
1733
+ if ( is_string( $connected_field_config ) ) {
1734
+ $connected_field_id = $connected_field_config;
1735
+ } elseif ( is_array( $connected_field_config ) ) {
1736
+ // We have a full blown connected field config
1737
+ if ( is_string( $key ) ) {
1738
+ $connected_field_id = $key;
1739
+ } else {
1740
+ continue;
1741
+ }
1742
+
1743
+ // We will pass to JS all the configured connected field details.
1744
+ $connected_field_data = $connected_field_config;
1745
+ }
1746
+
1747
+ // Continue if we don't have a connected field ID to work with.
1748
+ if ( empty( $connected_field_id ) ) {
1749
+ continue;
1750
+ }
1751
+
1752
+ // We will need to determine if the connected field specifies a setting ID or we need to determine it.
1753
+ if ( ! empty( $options[ $connected_field_id ] ) && ! empty( $options[ $connected_field_id ]['setting_id'] ) ) {
1754
+ $connected_field_data['setting_id'] = $options[ $connected_field_id ]['setting_id'];
1755
+ } else {
1756
+ $connected_field_data['setting_id'] = $options_name . '[' . $connected_field_id . ']';
1757
+ }
1758
+
1759
+ $connected_fields[] = $connected_field_data;
1760
+ }
1761
+
1762
+ printf(
1763
+ "sAdditional[%s].%s = %s;\n",
1764
+ wp_json_encode( $setting_id ),
1765
+ 'connected_fields',
1766
+ wp_json_encode( $connected_fields, JSON_FORCE_OBJECT )
1767
+ );
1768
+ }
1769
+ }
1770
+ echo "})( _wpCustomizeSettings.settings );\n";
1771
+ ?>
1772
+ </script>
1773
+ <?php
1774
+ }
1775
+
1776
  public function get_base_path() {
1777
  return plugin_dir_path( $this->file );
1778
  }
1966
  return false;
1967
  }
1968
 
1969
+ public function get_customizer_config() {
1970
+ return $this->customizer_config;
1971
+ }
1972
+
1973
+ /**
1974
+ * Get the Customify configuration of a certain option.
1975
+ *
1976
+ * @param string $option_id
1977
+ *
1978
+ * @return array|false The option config or false on failure.
1979
+ */
1980
+ public function get_option_customizer_config( $option_id ) {
1981
+ // We need to search for the option configured under the given id (the array key)
1982
+ if ( isset ( $this->customizer_config['panels'] ) ) {
1983
+ foreach ( $this->customizer_config['panels'] as $panel_id => $panel_settings ) {
1984
+ if ( isset( $panel_settings['sections'] ) ) {
1985
+ foreach ( $panel_settings['sections'] as $section_id => $section_settings ) {
1986
+ if ( isset( $section_settings['options'] ) ) {
1987
+ foreach ( $section_settings['options'] as $id => $option_config ) {
1988
+ if ( $id === $option_id ) {
1989
+ return $option_config;
1990
+ }
1991
+ }
1992
+ }
1993
+ }
1994
+ }
1995
+ }
1996
+ }
1997
+
1998
+ if ( isset ( $this->customizer_config['sections'] ) ) {
1999
+ foreach ( $this->customizer_config['sections'] as $section_id => $section_settings ) {
2000
+ if ( isset( $section_settings['options'] ) ) {
2001
+ foreach ( $section_settings['options'] as $id => $option_config ) {
2002
+ if ( $id === $option_id ) {
2003
+ return $option_config;
2004
+ }
2005
+ }
2006
+ }
2007
+ }
2008
+ }
2009
+
2010
+ return false;
2011
+ }
2012
+
2013
  protected function get_config() {
2014
  if ( file_exists( $this->get_base_path() . 'plugin-config.php' ) ) {
2015
  return include( $this->get_base_path() . 'plugin-config.php' );
2128
  * @return string
2129
  */
2130
  public static function decodeURIComponent( $str ) {
2131
+ // If we get an array we just let it be
2132
  if ( is_string( $str ) ) {
2133
  $revert = array( '!' => '%21', '*' => '%2A', "'" => '%27', '(' => '%28', ')' => '%29' );
2134
  $str = rawurldecode( strtr( $str, $revert ) );
css/customizer.css CHANGED
@@ -164,11 +164,9 @@
164
  padding-right: 15px;
165
  padding-left: 15px;
166
 
167
- transition: all .1s;
168
-
169
  color: #f5fcff;
170
  border: none;
171
- border-radius: 4px;
172
  background: #aed2e5;
173
  box-shadow: 0 2px 0 0 #8dbed7;
174
  text-shadow: none;
@@ -507,7 +505,7 @@
507
  }
508
 
509
  .font-options__head,
510
- .wp-full-overlay-sidebar-content .customize-control input[type=text]:not(#_customize-input-wpcom_custom_css_content_width_control),
511
  .wp-full-overlay-sidebar-content .customize-control input[type=checkbox],
512
  .wp-full-overlay-sidebar-content .customize-control input[type=password],
513
  .wp-full-overlay-sidebar-content .customize-control input[type=color],
@@ -543,7 +541,7 @@ ul.font-options__options-list .select2-container .select2-selection--single,
543
  background: #fff;
544
  }
545
  .font-options__head:focus,
546
- .wp-full-overlay-sidebar-content .customize-control input[type=text]:focus:not(#_customize-input-wpcom_custom_css_content_width_control),
547
  .wp-full-overlay-sidebar-content .customize-control input[type=checkbox]:focus,
548
  .wp-full-overlay-sidebar-content .customize-control input[type=password]:focus,
549
  .wp-full-overlay-sidebar-content .customize-control input[type=color]:focus,
@@ -623,6 +621,11 @@ ul.font-options__options-list .select2-container [multiple].select2-selection--s
623
  color: white;
624
  }
625
 
 
 
 
 
 
626
  .wp-full-overlay-sidebar-content .customize-control.customize-control-checkbox:not(#customize-control-jetpack_css_mode_control) label:not(:only-of-type),
627
  .wp-full-overlay-sidebar-content .customize-control.customize-control-checkbox:not(#customize-control-jetpack_css_mode_control) > .customize-inside-control-row:not(:only-of-type),
628
  .wp-full-overlay-sidebar-content .customize-control.customize-control-radio label:not(:only-of-type),
@@ -1761,7 +1764,7 @@ ul.font-options__options-list .select2-container--default .select2-selection--si
1761
  #customize-theme-controls .select2-container .select2-selection--multiple
1762
  {
1763
  height: auto;
1764
- padding: 8px 8px 4px;
1765
 
1766
  background: none;
1767
 
@@ -1773,8 +1776,23 @@ ul.font-options__options-list .select2-container--default .select2-selection--si
1773
  }
1774
  #customize-theme-controls .select2-container .select2-selection--multiple .select2-selection__rendered
1775
  {
 
 
 
1776
  padding: 0;
1777
  }
 
 
 
 
 
 
 
 
 
 
 
 
1778
  #customize-theme-controls .select2-container .select2-selection--multiple .select2-selection__rendered .select2-selection__choice
1779
  {
1780
  margin-top: 0;
@@ -1786,7 +1804,17 @@ ul.font-options__options-list .select2-container--default .select2-selection--si
1786
  }
1787
  #customize-theme-controls .select2-container .select2-search--inline .select2-search__field
1788
  {
1789
- height: 24px;
 
 
 
 
 
 
 
 
 
 
1790
  }
1791
 
1792
  .select2-container .select2-dropdown
@@ -1947,3 +1975,154 @@ ul.font-options__options-list .select2-container--default .select2-selection--si
1947
  {
1948
  width: 130px;
1949
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  padding-right: 15px;
165
  padding-left: 15px;
166
 
 
 
167
  color: #f5fcff;
168
  border: none;
169
+ border-radius: 4px;
170
  background: #aed2e5;
171
  box-shadow: 0 2px 0 0 #8dbed7;
172
  text-shadow: none;
505
  }
506
 
507
  .font-options__head,
508
+ .wp-full-overlay-sidebar-content .customize-control input[type=text]:not(#_customize-input-wpcom_custom_css_content_width_control):not(.wp-color-picker),
509
  .wp-full-overlay-sidebar-content .customize-control input[type=checkbox],
510
  .wp-full-overlay-sidebar-content .customize-control input[type=password],
511
  .wp-full-overlay-sidebar-content .customize-control input[type=color],
541
  background: #fff;
542
  }
543
  .font-options__head:focus,
544
+ .wp-full-overlay-sidebar-content .customize-control input[type=text]:focus:not(#_customize-input-wpcom_custom_css_content_width_control):not(.wp-color-picker),
545
  .wp-full-overlay-sidebar-content .customize-control input[type=checkbox]:focus,
546
  .wp-full-overlay-sidebar-content .customize-control input[type=password]:focus,
547
  .wp-full-overlay-sidebar-content .customize-control input[type=color]:focus,
621
  color: white;
622
  }
623
 
624
+ .wp-full-overlay-sidebar-content .customize-control .awesome_preset input[type=radio]:checked
625
+ {
626
+ background: transparent;
627
+ }
628
+
629
  .wp-full-overlay-sidebar-content .customize-control.customize-control-checkbox:not(#customize-control-jetpack_css_mode_control) label:not(:only-of-type),
630
  .wp-full-overlay-sidebar-content .customize-control.customize-control-checkbox:not(#customize-control-jetpack_css_mode_control) > .customize-inside-control-row:not(:only-of-type),
631
  .wp-full-overlay-sidebar-content .customize-control.customize-control-radio label:not(:only-of-type),
1764
  #customize-theme-controls .select2-container .select2-selection--multiple
1765
  {
1766
  height: auto;
1767
+ padding: 4px 8px 4px;
1768
 
1769
  background: none;
1770
 
1776
  }
1777
  #customize-theme-controls .select2-container .select2-selection--multiple .select2-selection__rendered
1778
  {
1779
+ display: -ms-flexbox;
1780
+ display: flex;
1781
+
1782
  padding: 0;
1783
  }
1784
+ #customize-theme-controls .select2-container .select2-selection--multiple .select2-selection__rendered .select2-search--inline
1785
+ {
1786
+ -ms-flex: 1;
1787
+ flex: 1;
1788
+ }
1789
+ #customize-theme-controls .select2-container .select2-selection--multiple .select2-selection__rendered .select2-search--inline .select2-search__field[class]
1790
+ {
1791
+ min-width: 100%;
1792
+ margin-top: 3px !important;
1793
+
1794
+ border-width: 0;
1795
+ }
1796
  #customize-theme-controls .select2-container .select2-selection--multiple .select2-selection__rendered .select2-selection__choice
1797
  {
1798
  margin-top: 0;
1804
  }
1805
  #customize-theme-controls .select2-container .select2-search--inline .select2-search__field
1806
  {
1807
+ min-width: 9em;
1808
+ height: 29px;
1809
+ margin-top: 0;
1810
+ }
1811
+
1812
+ .select2-container--default .select2-results__option[aria-selected=true][class]
1813
+ {
1814
+ pointer-events: none;
1815
+
1816
+ opacity: .3;
1817
+ background: transparent;
1818
  }
1819
 
1820
  .select2-container .select2-dropdown
1975
  {
1976
  width: 130px;
1977
  }
1978
+
1979
+ .pix_customizer_setting .customize-inside-control-row
1980
+ {
1981
+ position: relative;
1982
+
1983
+ overflow: hidden;
1984
+
1985
+ width: 100% !important;
1986
+ height: 64px;
1987
+ margin-left: 0 !important;
1988
+
1989
+ text-indent: 0 !important;
1990
+
1991
+ border-radius: 5px;
1992
+ background-position: 50% 50%;
1993
+ background-size: cover;
1994
+ }
1995
+ .pix_customizer_setting .customize-inside-control-row:before
1996
+ {
1997
+ position: absolute;
1998
+ z-index: 10;
1999
+ top: 0;
2000
+ right: 0;
2001
+ bottom: 0;
2002
+ left: 0;
2003
+
2004
+ content: '';
2005
+ pointer-events: none;
2006
+
2007
+ box-shadow: inset 0 0 3px 0 rgba(0, 0, 0, .15), inset 0 1px 3px 0 rgba(0, 0, 0, .15);
2008
+ }
2009
+ .pix_customizer_setting .customize-inside-control-row:hover:before
2010
+ {
2011
+ box-shadow: inset 0 2px 3px 0 rgba(0, 0, 0, .15), inset 0 0 3px 0 rgba(0, 0, 0, .15);
2012
+ }
2013
+ .pix_customizer_setting .customize-inside-control-row:hover .palette__item
2014
+ {
2015
+ -webkit-transform: translateY(0%);
2016
+ transform: translateY(0%);
2017
+ }
2018
+ .pix_customizer_setting .customize-inside-control-row:hover label
2019
+ {
2020
+ left: 10px;
2021
+ }
2022
+ .pix_customizer_setting .customize-inside-control-row input
2023
+ {
2024
+ opacity: 0;
2025
+ }
2026
+ .pix_customizer_setting .customize-inside-control-row label
2027
+ {
2028
+ position: absolute;
2029
+ z-index: 2;
2030
+ top: 0;
2031
+ left: 0;
2032
+
2033
+ display: -ms-flexbox;
2034
+ display: flex;
2035
+
2036
+ width: 100%;
2037
+ height: 100%;
2038
+ margin-top: 0 !important;
2039
+ padding: 0 10px;
2040
+
2041
+ transition: all .3s ease;
2042
+
2043
+ -ms-flex-align: center;
2044
+ align-items: center;
2045
+ }
2046
+ .pix_customizer_setting .customize-inside-control-row .label__inner
2047
+ {
2048
+ z-index: 2;
2049
+
2050
+ padding: 7px 12px 7px 7px;
2051
+
2052
+ border-radius: 3px;
2053
+ box-shadow: 0 2px 5px rgba(0, 0, 0, .15);
2054
+ }
2055
+ .pix_customizer_setting .customize-inside-control-row .palette
2056
+ {
2057
+ position: absolute;
2058
+ z-index: 1;
2059
+ top: 0;
2060
+ left: 0;
2061
+
2062
+ display: -ms-flexbox;
2063
+ display: flex;
2064
+
2065
+ width: 100%;
2066
+ height: 100%;
2067
+
2068
+ transition: all .2s ease;
2069
+ }
2070
+ .pix_customizer_setting .customize-inside-control-row .palette__item
2071
+ {
2072
+ transition: all .3s ease;
2073
+ -webkit-transform: translateY(100%);
2074
+ transform: translateY(100%);
2075
+
2076
+ -ms-flex: 1;
2077
+ flex: 1;
2078
+ }
2079
+ .pix_customizer_setting .customize-inside-control-row .palette__item:nth-child(1)
2080
+ {
2081
+ transition-delay: 0s;
2082
+ }
2083
+ .pix_customizer_setting .customize-inside-control-row .palette__item:nth-child(2)
2084
+ {
2085
+ transition-delay: .05s;
2086
+ }
2087
+ .pix_customizer_setting .customize-inside-control-row .palette__item:nth-child(3)
2088
+ {
2089
+ transition-delay: .1s;
2090
+ }
2091
+ .pix_customizer_setting .customize-inside-control-row .palette__item:nth-child(4)
2092
+ {
2093
+ transition-delay: .15s;
2094
+ }
2095
+ .pix_customizer_setting .customize-inside-control-row .palette__item:nth-child(5)
2096
+ {
2097
+ transition-delay: .2s;
2098
+ }
2099
+ .pix_customizer_setting .customize-inside-control-row .palette__item:nth-child(6)
2100
+ {
2101
+ transition-delay: .25s;
2102
+ }
2103
+ .pix_customizer_setting .customize-inside-control-row .palette__item:nth-child(7)
2104
+ {
2105
+ transition-delay: .3s;
2106
+ }
2107
+ .pix_customizer_setting .customize-inside-control-row .palette__item:nth-child(8)
2108
+ {
2109
+ transition-delay: .35s;
2110
+ }
2111
+ .pix_customizer_setting .customize-inside-control-row .palette__item:nth-child(9)
2112
+ {
2113
+ transition-delay: .4s;
2114
+ }
2115
+ .pix_customizer_setting .customize-inside-control-row .palette__item:nth-child(10)
2116
+ {
2117
+ transition-delay: .45s;
2118
+ }
2119
+ .pix_customizer_setting .customize-inside-control-row .preview__letter
2120
+ {
2121
+ display: inline-block;
2122
+
2123
+ margin-right: 5px;
2124
+ padding: 3px 9px;
2125
+
2126
+ color: white;
2127
+ border-radius: 2px;
2128
+ }
customify.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Customify
4
  Plugin URI: https://wordpress.org/plugins/customify/
5
  Description: A Theme Customizer Booster
6
- Version: 1.5.7
7
  Author: Pixelgrade
8
  Author URI: https://pixelgrade.com
9
  Author Email: contact@pixelgrade.com
@@ -58,7 +58,7 @@ function PixCustomifyPlugin() {
58
  */
59
  require_once( plugin_dir_path( __FILE__ ) . 'class-pixcustomify.php' );
60
 
61
- $instance = PixCustomifyPlugin::instance( __FILE__, '1.5.7' );
62
 
63
  return $instance;
64
  }
3
  Plugin Name: Customify
4
  Plugin URI: https://wordpress.org/plugins/customify/
5
  Description: A Theme Customizer Booster
6
+ Version: 1.6.0
7
  Author: Pixelgrade
8
  Author URI: https://pixelgrade.com
9
  Author Email: contact@pixelgrade.com
58
  */
59
  require_once( plugin_dir_path( __FILE__ ) . 'class-pixcustomify.php' );
60
 
61
+ $instance = PixCustomifyPlugin::instance( __FILE__, '1.6.0' );
62
 
63
  return $instance;
64
  }
customify_config.php CHANGED
@@ -350,6 +350,4 @@ if ( ! function_exists('add_customify_base_options') ) {
350
  return $config;
351
  }
352
  }
353
-
354
-
355
  add_filter( 'customify_filter_fields', 'add_customify_base_options' );
350
  return $config;
351
  }
352
  }
 
 
353
  add_filter( 'customify_filter_fields', 'add_customify_base_options' );
features/class-Font_Selector.php CHANGED
@@ -39,7 +39,7 @@ class Customify_Font_Selector {
39
  (function ($) {
40
  $(window).load(function () {
41
  /**
42
- * @param iframe_id the id of the frame you whant to append the style
43
  * @param style_element the style element you want to append
44
  */
45
  var append_script_to_iframe = function (ifrm_id, scriptEl) {
39
  (function ($) {
40
  $(window).load(function () {
41
  /**
42
+ * @param iframe_id the id of the frame you want to append the style
43
  * @param style_element the style element you want to append
44
  */
45
  var append_script_to_iframe = function (ifrm_id, scriptEl) {
features/customizer/controls/class-Pix_Customize_Font_Control.php CHANGED
@@ -92,7 +92,8 @@ class Pix_Customize_Font_Control extends Pix_Customize_Control {
92
  $this->load_google_fonts();
93
  //$this->generate_google_fonts_json();
94
 
95
- // since 4.7 all the customizer data is saved in a post type named changeset this is how we get it.
 
96
  if ( method_exists( $wp_customize, 'changeset_data' ) ) {
97
  $changeset_data = $wp_customize->changeset_data();
98
 
92
  $this->load_google_fonts();
93
  //$this->generate_google_fonts_json();
94
 
95
+ // Since 4.7 all the customizer data is saved in a post type named changeset.
96
+ // This is how we get it.
97
  if ( method_exists( $wp_customize, 'changeset_data' ) ) {
98
  $changeset_data = $wp_customize->changeset_data();
99
 
features/customizer/controls/class-Pix_Customize_Preset_Control.php CHANGED
@@ -5,9 +5,9 @@
5
  * A simple Select2 Control
6
  */
7
  class Pix_Customize_Preset_Control extends Pix_Customize_Control {
8
- public $type = 'preset';
9
- public $choices_type = 'select';
10
- public $description = null;
11
 
12
  /**
13
  * Render the control's content.
@@ -29,14 +29,14 @@ class Pix_Customize_Preset_Control extends Pix_Customize_Control {
29
 
30
  <select <?php $this->link(); ?> class="customify_preset select">
31
  <?php
32
- foreach ( $this->choices as $value => $setts ){
33
- if ( ! isset( $setts['options']) || ! isset( $setts['label'] ) ) {
34
  continue;
35
  }
36
- $label = $setts['label'];
37
- $options = $setts['options'];
38
  $data = ' data-options=\'' . json_encode($options) . '\'';
39
- echo '<option value="' . esc_attr( $value ) . '"' . selected( $this->value(), $value, false ) . $data . ' >' . $label . '</option>';
40
  } ?>
41
  </select>
42
  </label>
@@ -52,22 +52,28 @@ class Pix_Customize_Preset_Control extends Pix_Customize_Control {
52
  <span class="description customize-control-description"><?php echo $this->description; ?></span>
53
  <?php } ?>
54
 
55
- <div class="customify_preset radio">
56
  <?php
57
- foreach ( $this->choices as $value => $setts ){
58
- if ( ! isset( $setts['options']) || ! isset( $setts['label'] ) ) {
59
  continue;
60
  }
61
  $color = '';
62
- if ( isset( $setts['color'] ) ) {
63
- $color .= ' style="background-color: ' . $setts['color'] . '"';
64
  }
65
 
66
- $label = $setts['label'];
67
- $options = $setts['options'];
68
- $data = ' data-options=\'' . json_encode($options) . '\'';?>
69
- <input <?php $this->link(); echo 'name="' . $this->setting->id . '" type="radio" value="' . esc_attr( $value ) . '"' . selected( $this->value(), $value, false ) . $data . $color .' >' . $label . '</input>';
70
- } ?>
 
 
 
 
 
 
71
  </div>
72
  </label>
73
  <?php break;
@@ -84,21 +90,21 @@ class Pix_Customize_Preset_Control extends Pix_Customize_Control {
84
 
85
  <div class="customify_preset radio_buttons">
86
  <?php
87
- foreach ( $this->choices as $value => $setts ){
88
- if ( ! isset( $setts['options']) || ! isset( $setts['label'] ) ) {
89
  continue;
90
  }
91
  $color = '';
92
- if ( isset( $setts['color'] ) ) {
93
- $color .= ' style="border-left-color: ' . $setts['color'] . '; color: ' . $setts['color'] . ';"';
94
  }
95
 
96
- $label = $setts['label'];
97
- $options = $setts['options'];
98
  $data = ' data-options=\'' . json_encode($options) . '\'';?>
99
 
100
  <fieldset class="customify_radio_button">
101
- <input <?php $this->link(); echo 'name="' . $this->setting->id . '" type="radio" value="' . esc_attr( $value ) . '"' . selected( $this->value(), $value, false ) . $data .' />'; ?>
102
  <label class="button" for="<?php echo $this->setting->id; ?>" <?php echo $color; ?>>
103
  <?php echo $label; ?>
104
  </label>
@@ -109,6 +115,99 @@ class Pix_Customize_Preset_Control extends Pix_Customize_Control {
109
  <?php break;
110
  }
111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  case 'awesome' : { ?>
113
  <label>
114
  <?php if ( ! empty( $this->label ) ) { ?>
@@ -120,8 +219,8 @@ class Pix_Customize_Preset_Control extends Pix_Customize_Control {
120
 
121
  $google_links = array();
122
 
123
- foreach ( $this->choices as $value => $setts ){
124
- if ( ! isset( $setts['options']) || ! isset( $setts['label'] ) ) {
125
  continue;
126
  }
127
 
@@ -130,16 +229,16 @@ class Pix_Customize_Preset_Control extends Pix_Customize_Control {
130
  $preset_text_color = ' style=" color: #ebebeb';
131
 
132
  $first_font = $second_font = '';
133
- if ( isset( $setts['preview'] ) ) {
134
 
135
- if ( isset( $setts['preview']['background-card'] ) ) {
136
  $preset_style = ' style="';
137
- $preset_style .= 'background-color: ' . $setts['preview']['background-card'] . ';';
138
  }
139
 
140
- if ( isset( $setts['preview']['background-label'] ) ) {
141
 
142
- $this_preset_color = $setts['preview']['background-label'];
143
 
144
  if ( $this->isLight( $this_preset_color ) ) {
145
  $this_preset_color = '#000000';
@@ -147,22 +246,22 @@ class Pix_Customize_Preset_Control extends Pix_Customize_Control {
147
  $this_preset_color = '#ffffff';
148
  }
149
  $preset_name_style = ' style="';
150
- $preset_name_style .= 'color: ' .$this_preset_color . ';background-color: ' . $setts['preview']['background-label'] . '; border-color: ' . $setts['preview']['background-label'];
151
  }
152
 
153
- if ( isset( $setts['preview']['color-text'] ) ) {
154
  $preset_text_color = ' style="';
155
- $preset_text_color .= 'color: ' . $setts['preview']['color-text'] . ';"';
156
  }
157
 
158
- if ( isset( $setts['preview']['font-main'] ) ) {
159
- $first_font = ' style="font-family: ' . $setts['preview']['font-main'] . '"' ;
160
- $google_links[] = str_replace( ' ', '+', $setts['preview']['font-main'] );
161
  }
162
 
163
- if ( isset( $setts['preview']['font-alt'] ) ) {
164
- $second_font = ' style="font-family: ' . $setts['preview']['font-alt'] . '"' ;
165
- $google_links[] = str_replace( ' ', '+', $setts['preview']['font-alt'] );
166
  }
167
  }
168
 
@@ -170,11 +269,11 @@ class Pix_Customize_Preset_Control extends Pix_Customize_Control {
170
  $preset_text_color .= '"';
171
  $preset_name_style .= '"';
172
 
173
- $label = $setts['label'];
174
- $options = $setts['options'];
175
  $data = ' data-options=\'' . json_encode($options) . '\'';?>
176
  <div class="awesome_preset" <?php echo $preset_text_color; ?>>
177
- <input <?php $this->link(); echo 'name="' . $this->setting->id . '" type="radio" value="' . esc_attr( $value ) . '"' . selected( $this->value(), $value, false ) . $data .' >' . '</input>'; ?>
178
  <div class="preset-wrap">
179
  <div class="preset-color" <?php echo $preset_style; ?>>
180
  <span class="first-font" <?php echo $first_font; ?>><?php echo substr( get_bloginfo('name'), 0, 2); ?></span>
@@ -219,4 +318,77 @@ class Pix_Customize_Preset_Control extends Pix_Customize_Control {
219
  $b = hexdec($color[4].$color[5]);
220
  return (( $r*299 + $g*587 + $b*114 )/1000 > 130);
221
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
  }
5
  * A simple Select2 Control
6
  */
7
  class Pix_Customize_Preset_Control extends Pix_Customize_Control {
8
+ public $type = 'preset';
9
+ public $choices_type = 'select';
10
+ public $description = null;
11
 
12
  /**
13
  * Render the control's content.
29
 
30
  <select <?php $this->link(); ?> class="customify_preset select">
31
  <?php
32
+ foreach ( $this->choices as $choice_value => $choice_config ){
33
+ if ( ! isset( $choice_config['options']) || ! isset( $choice_config['label'] ) ) {
34
  continue;
35
  }
36
+ $label = $choice_config['label'];
37
+ $options = $this->convertChoiceOptionsIdsToSettingIds( $choice_config['options'] );
38
  $data = ' data-options=\'' . json_encode($options) . '\'';
39
+ echo '<option value="' . esc_attr( $choice_value ) . '" ' . selected( $this->value(), $choice_value, false ) . $data . ' >' . $label . '</option>';
40
  } ?>
41
  </select>
42
  </label>
52
  <span class="description customize-control-description"><?php echo $this->description; ?></span>
53
  <?php } ?>
54
 
55
+ <div class="customify_preset radio customize-control customize-control-radio">
56
  <?php
57
+ foreach ( $this->choices as $choice_value => $choice_config ){
58
+ if ( ! isset( $choice_config['options']) || ! isset( $choice_config['label'] ) ) {
59
  continue;
60
  }
61
  $color = '';
62
+ if ( isset( $choice_config['color'] ) ) {
63
+ $color .= ' style="background-color: ' . $choice_config['color'] . '"';
64
  }
65
 
66
+ $label = $choice_config['label'];
67
+ $options = $this->convertChoiceOptionsIdsToSettingIds( $choice_config['options'] );
68
+ $data = ' data-options=\'' . json_encode( $options ) . '\''; ?>
69
+
70
+ <span class="customize-inside-control-row">
71
+ <input <?php $this->link(); echo 'name="' . $this->setting->id . '" id="' . esc_attr( $choice_value ) . '" type="radio" value="' . esc_attr( $choice_value ) . '" ' . selected( $this->value(), $choice_value, false ) . $data . $color .' />'; ?>
72
+ <label for="<?php echo esc_attr( $choice_value ); ?>">
73
+ <?php echo $label; ?>
74
+ </label>
75
+ </span>
76
+ <?php } ?>
77
  </div>
78
  </label>
79
  <?php break;
90
 
91
  <div class="customify_preset radio_buttons">
92
  <?php
93
+ foreach ( $this->choices as $choice_value => $choice_config ){
94
+ if ( ! isset( $choice_config['options']) || ! isset( $choice_config['label'] ) ) {
95
  continue;
96
  }
97
  $color = '';
98
+ if ( isset( $choice_config['color'] ) ) {
99
+ $color .= ' style="border-left-color: ' . $choice_config['color'] . '; color: ' . $choice_config['color'] . ';"';
100
  }
101
 
102
+ $label = $choice_config['label'];
103
+ $options = $this->convertChoiceOptionsIdsToSettingIds( $choice_config['options'] );
104
  $data = ' data-options=\'' . json_encode($options) . '\'';?>
105
 
106
  <fieldset class="customify_radio_button">
107
+ <input <?php $this->link(); echo 'name="' . $this->setting->id . '" type="radio" value="' . esc_attr( $choice_value ) . '" ' . selected( $this->value(), $choice_value, false ) . $data .' />'; ?>
108
  <label class="button" for="<?php echo $this->setting->id; ?>" <?php echo $color; ?>>
109
  <?php echo $label; ?>
110
  </label>
115
  <?php break;
116
  }
117
 
118
+ case 'color_palette' : { ?>
119
+ <label>
120
+ <?php if ( ! empty( $this->label ) ) { ?>
121
+ <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
122
+ <?php }
123
+
124
+ if ( ! empty( $this->description ) ) { ?>
125
+ <span class="description customize-control-description"><?php echo $this->description; ?></span>
126
+ <?php } ?>
127
+
128
+ <div class="customify_preset color_palette customize-control customize-control-radio">
129
+ <?php
130
+ foreach ( $this->choices as $choice_value => $choice_config ){
131
+ if ( empty( $choice_config['options'] ) ) {
132
+ continue;
133
+ }
134
+
135
+ // Make sure that the defaults are in place
136
+ $choice_config = wp_parse_args( $choice_config, array(
137
+ 'label' => '',
138
+ 'preview' => array(),
139
+ ) );
140
+
141
+ // Make sure that the preview defaults are in place
142
+ $choice_config['preview'] = wp_parse_args( $choice_config['preview'], array(
143
+ 'sample_letter' => 'A',
144
+ 'background_image_url' => plugins_url( 'images/color_palette_image.jpg', PixCustomifyPlugin()->file ),
145
+ ) );
146
+
147
+ // Determine a (primary) color with fallback for missing options
148
+ $sm_color = '#777777';
149
+ if ( isset( $choice_config['options']['sm_color_primary'] ) ) {
150
+ $sm_color = $choice_config['options']['sm_color_primary'];
151
+ } elseif ( isset( $choice_config['options']['sm_color_secondary'] ) ) {
152
+ $sm_color = $choice_config['options']['sm_color_secondary'];
153
+ } elseif ( isset( $choice_config['options']['sm_color_tertiary'] ) ) {
154
+ $sm_color = $choice_config['options']['sm_color_tertiary'];
155
+ } elseif ( isset( $choice_config['options']['sm_color_quaternary'] ) ) {
156
+ $sm_color = $choice_config['options']['sm_color_quaternary'];
157
+ } elseif ( isset( $choice_config['options']['sm_color_quinary'] ) ) {
158
+ $sm_color = $choice_config['options']['sm_color_quinary'];
159
+ }
160
+
161
+ // Determine a (primary) dark color with fallback for missing options
162
+ $sm_dark = '#000000';
163
+ if ( isset( $choice_config['options']['sm_dark_primary'] ) ) {
164
+ $sm_dark = $choice_config['options']['sm_dark_primary'];
165
+ } elseif ( isset( $choice_config['options']['sm_dark_secondary'] ) ) {
166
+ $sm_dark = $choice_config['options']['sm_dark_secondary'];
167
+ } elseif ( isset( $choice_config['options']['sm_dark_tertiary'] ) ) {
168
+ $sm_dark = $choice_config['options']['sm_dark_tertiary'];
169
+ } elseif ( isset( $choice_config['options']['sm_dark_quaternary'] ) ) {
170
+ $sm_dark = $choice_config['options']['sm_dark_quaternary'];
171
+ } elseif ( isset( $choice_config['options']['sm_dark_quinary'] ) ) {
172
+ $sm_dark = $choice_config['options']['sm_dark_quinary'];
173
+ }
174
+
175
+ // Determine a (primary) light color with fallback for missing options
176
+ $sm_light = '#FFFFFF';
177
+ if ( isset( $choice_config['options']['sm_light_primary'] ) ) {
178
+ $sm_light = $choice_config['options']['sm_light_primary'];
179
+ } elseif ( isset( $choice_config['options']['sm_light_secondary'] ) ) {
180
+ $sm_light = $choice_config['options']['sm_light_secondary'];
181
+ } elseif ( isset( $choice_config['options']['sm_light_tertiary'] ) ) {
182
+ $sm_light = $choice_config['options']['sm_light_tertiary'];
183
+ } elseif ( isset( $choice_config['options']['sm_light_quaternary'] ) ) {
184
+ $sm_light = $choice_config['options']['sm_light_quaternary'];
185
+ } elseif ( isset( $choice_config['options']['sm_light_quinary'] ) ) {
186
+ $sm_light = $choice_config['options']['sm_light_quinary'];
187
+ }
188
+
189
+ $label = $choice_config['label'];
190
+ $options = $this->convertChoiceOptionsIdsToSettingIds( $choice_config['options'] );
191
+ $data = ' data-options=\'' . json_encode( $options ) . '\''; ?>
192
+
193
+ <span class="customize-inside-control-row <?php echo ( (string) $this->value() === (string) $choice_value ? 'current-color-palette' : '' );?>" style="background-image: url( <?php echo esc_url( $choice_config['preview']['background_image_url'] ); ?> );">
194
+ <input <?php $this->link(); echo 'name="' . $this->setting->id . '" id="' . esc_attr( $choice_value ) . '" type="radio" value="' . esc_attr( $choice_value ) . '" ' . selected( $this->value(), $choice_value, false ) . $data .' />'; ?>
195
+ <label for="<?php echo esc_attr( $choice_value ); ?>">
196
+ <span class="label__inner" style="color: <?php echo esc_attr( $this->lightOrDark( $sm_light ) ); ?>; background: <?php echo esc_attr( $sm_light ); ?>;"><span class="preview__letter" style="background: <?php echo $sm_color; ?>"><?php echo $choice_config['preview']['sample_letter']; ?></span><?php echo esc_html( $label ); ?></span>
197
+ </label>
198
+ <div class="palette">
199
+ <?php foreach ( $choice_config['options'] as $color_name => $color_value ) {
200
+ echo '<div class="palette__item ' . esc_attr( $color_name ) . '" style="background: ' . esc_attr( $color_value ) . '"></div>' . PHP_EOL;
201
+ } ?>
202
+ </div>
203
+ </span>
204
+ <?php } ?>
205
+ </div>
206
+ </label>
207
+
208
+ <?php break;
209
+ }
210
+
211
  case 'awesome' : { ?>
212
  <label>
213
  <?php if ( ! empty( $this->label ) ) { ?>
219
 
220
  $google_links = array();
221
 
222
+ foreach ( $this->choices as $choice_value => $choice_config ){
223
+ if ( ! isset( $choice_config['options']) || ! isset( $choice_config['label'] ) ) {
224
  continue;
225
  }
226
 
229
  $preset_text_color = ' style=" color: #ebebeb';
230
 
231
  $first_font = $second_font = '';
232
+ if ( isset( $choice_config['preview'] ) ) {
233
 
234
+ if ( isset( $choice_config['preview']['background-card'] ) ) {
235
  $preset_style = ' style="';
236
+ $preset_style .= 'background-color: ' . $choice_config['preview']['background-card'] . ';';
237
  }
238
 
239
+ if ( isset( $choice_config['preview']['background-label'] ) ) {
240
 
241
+ $this_preset_color = $choice_config['preview']['background-label'];
242
 
243
  if ( $this->isLight( $this_preset_color ) ) {
244
  $this_preset_color = '#000000';
246
  $this_preset_color = '#ffffff';
247
  }
248
  $preset_name_style = ' style="';
249
+ $preset_name_style .= 'color: ' .$this_preset_color . ';background-color: ' . $choice_config['preview']['background-label'] . '; border-color: ' . $choice_config['preview']['background-label'];
250
  }
251
 
252
+ if ( isset( $choice_config['preview']['color-text'] ) ) {
253
  $preset_text_color = ' style="';
254
+ $preset_text_color .= 'color: ' . $choice_config['preview']['color-text'] . ';"';
255
  }
256
 
257
+ if ( isset( $choice_config['preview']['font-main'] ) ) {
258
+ $first_font = ' style="font-family: ' . $choice_config['preview']['font-main'] . '"' ;
259
+ $google_links[] = str_replace( ' ', '+', $choice_config['preview']['font-main'] );
260
  }
261
 
262
+ if ( isset( $choice_config['preview']['font-alt'] ) ) {
263
+ $second_font = ' style="font-family: ' . $choice_config['preview']['font-alt'] . '"' ;
264
+ $google_links[] = str_replace( ' ', '+', $choice_config['preview']['font-alt'] );
265
  }
266
  }
267
 
269
  $preset_text_color .= '"';
270
  $preset_name_style .= '"';
271
 
272
+ $label = $choice_config['label'];
273
+ $options = $this->convertChoiceOptionsIdsToSettingIds( $choice_config['options'] );
274
  $data = ' data-options=\'' . json_encode($options) . '\'';?>
275
  <div class="awesome_preset" <?php echo $preset_text_color; ?>>
276
+ <input <?php $this->link(); echo 'name="' . $this->setting->id . '" type="radio" value="' . esc_attr( $choice_value ) . '" ' . selected( $this->value(), $choice_value, false ) . $data .' >' . '</input>'; ?>
277
  <div class="preset-wrap">
278
  <div class="preset-color" <?php echo $preset_style; ?>>
279
  <span class="first-font" <?php echo $first_font; ?>><?php echo substr( get_bloginfo('name'), 0, 2); ?></span>
318
  $b = hexdec($color[4].$color[5]);
319
  return (( $r*299 + $g*587 + $b*114 )/1000 > 130);
320
  }
321
+
322
+ /**
323
+ * Detect if we should use a light or dark color on a background color.
324
+ *
325
+ * Taken from WooCommerce: woocommerce/includes/wc-formatting-functions.php
326
+ * @link http://woocommerce.wp-a2z.org/oik_api/wc_light_or_dark/
327
+ *
328
+ * @param mixed $color Color.
329
+ * @param string $dark Darkest reference.
330
+ * Defaults to '#000000'.
331
+ * @param string $light Lightest reference.
332
+ * Defaults to '#FFFFFF'.
333
+ * @return string
334
+ */
335
+ function lightOrDark( $color, $dark = '#000000', $light = '#FFFFFF' ) {
336
+
337
+ $hex = str_replace( '#', '', $color );
338
+
339
+ $c_r = hexdec( substr( $hex, 0, 2 ) );
340
+ $c_g = hexdec( substr( $hex, 2, 2 ) );
341
+ $c_b = hexdec( substr( $hex, 4, 2 ) );
342
+
343
+ $brightness = ( ( $c_r * 299 ) + ( $c_g * 587 ) + ( $c_b * 114 ) ) / 1000;
344
+
345
+ return $brightness > 180 ? $dark : $light;
346
+ }
347
+
348
+ /**
349
+ * We will receive the choice options IDs as defined in the Customify config (the options array keys) and we will convert them to actual setting IDs.
350
+ *
351
+ * @param array $options
352
+ *
353
+ * @return array
354
+ */
355
+ protected function convertChoiceOptionsIdsToSettingIds( $options ) {
356
+ $settings = array();
357
+
358
+ if ( empty( $options ) ) {
359
+ return $settings;
360
+ }
361
+
362
+ $localPlugin = PixCustomifyPlugin();
363
+ $customizer_config = $localPlugin->get_customizer_config();
364
+
365
+ // first check the very needed options name
366
+ if ( empty( $customizer_config['opt-name'] ) ) {
367
+ return $settings;
368
+ }
369
+ $options_name = $customizer_config['opt-name'];
370
+
371
+ // Coerce a single string into an array and treat it as a field ID.
372
+ if ( is_string( $options ) ) {
373
+ $options = array( $options );
374
+ }
375
+
376
+ foreach ( $options as $option_id => $option_value ) {
377
+ $option_config = $localPlugin->get_option_customizer_config( $option_id );
378
+ if ( empty( $option_config ) ) {
379
+ continue;
380
+ }
381
+
382
+ // If we have been explicitly given a setting ID we will use that
383
+ if ( ! empty( $option_config['setting_id'] ) ) {
384
+ $setting_id = $option_config['setting_id'];
385
+ } else {
386
+ $setting_id = $options_name . '[' . $option_id . ']';
387
+ }
388
+
389
+ $settings[ $setting_id ] = $option_value;
390
+ }
391
+
392
+ return $settings;
393
+ }
394
  }
images/check.svg ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="14px" height="10px" viewBox="0 0 14 10" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+ <!-- Generator: Sketch 49.1 (51147) - http://www.bohemiancoding.com/sketch -->
4
+ <title></title>
5
+ <desc>Created with Sketch.</desc>
6
+ <defs></defs>
7
+ <g id="Customify" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" font-family="FontAwesome" font-size="14" font-weight="normal">
8
+ <g id="Customify-1.5.0---Default-State" transform="translate(-48.000000, -273.000000)" fill="#FAEFE6">
9
+ <text id="">
10
+ <tspan x="48" y="283"></tspan>
11
+ </text>
12
+ </g>
13
+ </g>
14
+ </svg>
images/color_palette_image.jpg ADDED
Binary file
js/customizer.js CHANGED
@@ -2,11 +2,42 @@
2
  'use strict';
3
 
4
  var api = wp.customize;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
  // when the customizer is ready prepare our fields events
7
  wp.customize.bind('ready', function () {
8
  var timeout = null;
9
 
 
 
 
 
 
 
 
10
  // add ace editors
11
  $('.customify_ace_editor').each(function ( key, el ) {
12
  var id = $(this).attr('id'),
@@ -68,6 +99,8 @@
68
  customifyHandleRangeFields(this);
69
  });
70
 
 
 
71
  if ( $('button[data-action="reset_customify"]').length > 0 ) {
72
  // reset_button
73
  $(document).on('click', '#customize-control-reset_customify button', function ( ev ) {
@@ -80,16 +113,11 @@
80
  }
81
 
82
  $.each(api.settings.controls, function ( key, ctrl ) {
83
- var id = key.replace('_control', '');
84
- var setting = customify_settings.settings[id];
85
 
86
  if ( !_.isUndefined(setting) && !_.isUndefined(setting.default) ) {
87
-
88
- var start_pos = id.indexOf('[') + 1;
89
- var end_pos = id.indexOf(']', start_pos);
90
-
91
- id = id.substring(start_pos, end_pos);
92
- api_set_setting_value(id, setting.default);
93
  }
94
  });
95
 
@@ -126,16 +154,11 @@
126
 
127
  if ( controls.length > 0 ) {
128
  $.each(controls, function ( key, ctrl ) {
129
- var id = ctrl.id.replace('_control', ''),
130
- setting = customify_settings.settings[id];
131
 
132
  if ( !_.isUndefined(setting) && !_.isUndefined(setting.default) ) {
133
-
134
- var start_pos = id.indexOf('[') + 1,
135
- end_pos = id.indexOf(']', start_pos);
136
-
137
- id = id.substring(start_pos, end_pos);
138
- api_set_setting_value(id, setting.default);
139
  }
140
  });
141
  }
@@ -173,16 +196,11 @@
173
 
174
  if ( controls.length > 0 ) {
175
  $.each(controls, function ( key, ctrl ) {
176
- var id = ctrl.id.replace('_control', ''),
177
- setting = customify_settings.settings[id];
178
 
179
  if ( !_.isUndefined(setting) && !_.isUndefined(setting.default) ) {
180
-
181
- var start_pos = id.indexOf('[') + 1,
182
- end_pos = id.indexOf(']', start_pos);
183
-
184
- id = id.substring(start_pos, end_pos);
185
- api_set_setting_value(id, setting.default);
186
  }
187
  });
188
  }
@@ -226,31 +244,28 @@
226
  $input.trigger('change');
227
  });
228
 
229
- // presets
230
  $(document).on('change', '.customify_preset.select', function () {
231
  var this_option = $(this).children('[value="' + $(this).val() + '"]'),
232
  data = $(this_option).data('options');
233
 
234
  if ( !_.isUndefined(data) ) {
235
- $.each(data, function ( id, value ) {
236
- api_set_setting_value(id, value);
237
  });
238
  }
239
-
240
- api.previewer.refresh();
241
  });
242
 
243
- $(document).on('click', '.customify_preset.radio input, .customify_preset.radio_buttons input, .awesome_presets input', function () {
244
- var this_option = this,//$(this).children('[value="' + $(this).val() + '"]');
 
245
  data = $(this_option).data('options');
246
 
247
  if ( !_.isUndefined(data) ) {
248
- $.each(data, function ( id, value ) {
249
- api_set_setting_value(id, value);
250
  });
251
  }
252
-
253
- api.previewer.refresh();
254
  });
255
 
256
  // bind our event on click
@@ -286,7 +301,7 @@
286
 
287
  customifyBackgroundJsControl.init();
288
 
289
- // sometimes there may be needed a php save
290
  if ( getUrlVars('save_customizer_once') ) {
291
  api.previewer.save();
292
  }
@@ -334,7 +349,7 @@
334
  })();
335
  });
336
 
337
- var customifyHandleRangeFields = function (el) {
338
 
339
  // For each range input add a number field (for preview mainly - but it can also be used for input)
340
  $(el).find('input[type="range"]').each(function () {
@@ -343,7 +358,8 @@
343
 
344
  $clone
345
  .attr('type', 'number')
346
- .attr('class', 'range-value');
 
347
 
348
  $(this).after($clone);
349
  }
@@ -358,7 +374,51 @@
358
  $(this).siblings('input[type="range"]').val($(this).val());
359
  });
360
  });
361
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362
 
363
  /**
364
  * This function will search for all the interdependend fields and make a bound between them.
@@ -552,6 +612,7 @@
552
  };
553
 
554
  // get each typography field and bind events
 
555
  var prepare_typography_field = function () {
556
 
557
  var $typos = $('.customify_typography_font_family');
@@ -568,32 +629,30 @@
568
  });
569
  };
570
 
571
- var api_set_setting_value = function ( id, value ) {
572
-
573
- var setting_id = customify_settings.options_name + '[' + id + ']',
574
- setting = api(setting_id),
575
  field = $('[data-customize-setting-link="' + setting_id + '"]'),
576
  field_class = $(field).parent().attr('class');
577
 
578
  // Legacy field type
579
  if ( !_.isUndefined(field_class) && field_class === 'customify_typography' ) {
580
 
581
- var family_select = field.siblings('select');
582
 
583
  if ( _.isString(value) ) {
584
- var this_option = family_select.find('option[value="' + value + '"]');
585
  $(this_option[0]).attr('selected', 'selected');
586
  update_siblings_selects(family_select);
587
  } else if ( _.isObject(value) ) {
588
- var this_family_option = family_select.find('option[value="' + value['font_family'] + '"]');
 
589
  $(this_family_option[0]).attr('selected', 'selected');
590
 
591
  update_siblings_selects(this_family_option);
592
 
593
  setTimeout(function () {
594
- var weight_select = field.parent().siblings('.options').find('.customify_typography_font_weight');
595
-
596
- var this_weight_option = weight_select.find('option[value="' + value['selected_variants'] + '"]');
597
 
598
  $(this_weight_option[0]).attr('selected', 'selected');
599
 
@@ -607,22 +666,21 @@
607
 
608
  } else if( !_.isUndefined(field_class) && field_class === 'font-options__wrapper' ) {
609
 
610
- // if the values is a simple string it should be the font family
611
  if ( _.isString( value ) ) {
612
-
613
- var option = field.parent().find('option[value="' + value + '"]');
614
 
615
  option.attr('selected', 'selected');
616
  // option.parents('select').trigger('change');
617
  } else if ( _.isObject(value) ) {
618
  // Find the options list wrapper
619
- var optionsList = field.parent().children('.font-options__options-list');
620
 
621
  if ( optionsList.length ) {
622
  // We will process each font property and update it
623
  _.each(value, function (val, key) {
624
  // We need to map the keys to the data attributes we are using - I know :(
625
- var mappedKey = key;
626
  switch (key) {
627
  case 'font-family':
628
  mappedKey = 'font_family';
@@ -642,7 +700,7 @@
642
  default:
643
  break;
644
  }
645
- var subField = optionsList.find('[data-field="' + mappedKey + '"]');
646
  if ( subField.length ) {
647
  subField.val(val);
648
  subField.trigger('change');
@@ -1019,130 +1077,150 @@
1019
  }
1020
  })(jQuery);
1021
 
 
1022
  var customifyFontSelect = (function () {
1023
- var fontSelector = '.customify_font_family',
1024
- selectPlacehoder = "Select a font family",
1025
- weightPlaceholder = "Select a font weight",
1026
- subsetPlaceholder = "Select a font subset";
 
 
 
 
 
 
 
 
 
 
1027
 
1028
  function init( wpapi ) {
1029
- $(fontSelector).select2({
1030
- placeholder: selectPlacehoder
1031
- }).on('change', function ( e ) {
1032
- var new_option = $(e.target).find('option:selected'),
1033
- wraper = $(e.target).closest('.font-options__wrapper'),
1034
- type = $(new_option).data('type');
1035
 
1036
- update_weight_field(new_option, wraper);
 
 
 
 
 
1037
 
1038
- update_subset_field(new_option, wraper);
 
1039
 
1040
- // serialize stuff and refresh
1041
- update_font_value(wraper);
1042
- });
1043
-
1044
- $('.customify_font_weight').each(function ( i, el ) {
1045
 
1046
- var select2_args = {
1047
- debug: false
1048
- };
1049
-
1050
- // all this fuss is for the case when the font doesn't come with variants from PHP, like a theme_font
1051
- if ( this.options.length === 0 ) {
1052
- var wraper = $(el).closest('.font-options__wrapper'),
1053
- font = wraper.find('.customify_font_family'),
1054
- option = font[0].options[font[0].selectedIndex],
1055
- variants = maybeJsonParse( $(option).data('variants') ),
1056
- data = [],
1057
- selecter_variants = $(el).data('default') || null;
1058
-
1059
- if ( typeof variants === "undefined" ) {
1060
- $(this).hide();
1061
- return;
1062
- }
1063
 
1064
- $.each( variants, function ( index, weight ) {
1065
- var this_value = {
1066
- id: weight,
1067
- text: weight
1068
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1069
 
1070
- if ( selecter_variants !== null && weight == selecter_variants ) {
1071
- this_value.selected = true;
1072
- }
1073
 
1074
- data.push(this_value);
1075
- } );
 
 
1076
 
1077
- if ( data !== [] ) {
1078
- select2_args.data = data;
1079
- }
1080
- }
1081
 
1082
- $(this).select2( select2_args )
1083
- .on('change', function ( e ) {
1084
- var wraper = $(e.target).closest('.font-options__wrapper');
1085
- var current_value = update_font_value(wraper);
1086
- // temporary just set the new value and refresh the previewer
1087
- // we may update this with a live version sometime
1088
- var value_holder = wraper.children('.customify_font_values');
1089
- var setting_id = $(value_holder).data('customize-setting-link');
1090
- var setting = wp.customize(setting_id);
1091
- setting.set(encodeValues(current_value));
1092
- });
1093
- });
1094
 
1095
- $('.customify_font_subsets')
 
1096
  .select2({
1097
- placeholder: "Extra Subsets"
1098
  })
1099
  .on('change', function ( e ) {
1100
- var wraper = $(e.target).closest('.font-options__wrapper');
1101
- var current_value = update_font_value(wraper);
1102
- // temporary just set the new value and refresh the previewr
1103
- // we may update this with a live version sometime
1104
- var value_holder = wraper.children('.customify_font_values');
1105
- var setting_id = $(value_holder).data('customize-setting-link');
1106
- var setting = wp.customize(setting_id);
1107
- setting.set(encodeValues(current_value));
1108
  });
1109
 
1110
- var rangers = $(fontSelector).parents('.font-options__wrapper').find('input[type=range]');
1111
- var selects = $(fontSelector).parents('.font-options__wrapper').find('select');
1112
 
 
1113
  if ( selects.length > 0 ) {
1114
  selects.on('change', function ( e ) {
1115
- var wraper = $(e.target).closest('.font-options__wrapper');
1116
- var current_value = update_font_value(wraper);
1117
- // temporary just set the new value and refresh the previewr
1118
- // we may update this with a live version sometime
1119
- var value_holder = wraper.children('.customify_font_values');
1120
- var setting_id = $(value_holder).data('customize-setting-link');
1121
- var setting = wp.customize(setting_id);
1122
- setting.set(encodeValues(current_value));
1123
  });
1124
  }
1125
 
 
1126
  if ( rangers.length > 0 ) {
1127
- rangers.on('mousemove', function ( e ) {
1128
- var wraper = $(e.target).closest('.font-options__wrapper');
1129
- var current_value = update_font_value(wraper);
1130
- // temporary just set the new value and refresh the previewr
1131
- // we may update this with a live version sometime
1132
- var value_holder = wraper.children('.customify_font_values');
1133
- var setting_id = $(value_holder).data('customize-setting-link');
1134
- var setting = wp.customize(setting_id);
1135
- setting.set(encodeValues(current_value));
1136
 
1137
  wp.customize.previewer.send( 'font-changed' );
1138
  });
1139
  }
1140
 
 
1141
  var self = this;
1142
-
1143
  wp.customize.previewer.bind( 'ready', function () {
1144
  self.render_fonts();
1145
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1146
  }
1147
 
1148
  /**
@@ -1152,12 +1230,11 @@
1152
  * @param wraper
1153
  */
1154
  function update_weight_field( option, wraper ) {
1155
- var variants = $(option).data('variants'),
1156
- font_weights = wraper.find('.customify_font_weight'),
1157
  selected_variant = font_weights.data('default'),
1158
  new_variants = [],
1159
- type = $(option).data('type'),
1160
- id = wraper.find('.customify_font_values').data('customizeSettingLink');
1161
 
1162
  variants = maybeJsonParse(variants);
1163
 
@@ -1168,25 +1245,26 @@
1168
  }
1169
 
1170
  // we need to turn the data array into a specific form like [{id:"id", text:"Text"}]
1171
- $.each(variants, function ( i, j ) {
1172
- new_variants[i] = {
1173
- 'id': j,
1174
- 'text': j
1175
  };
1176
 
1177
- if ( selected_variant == j ) {
1178
- new_variants[i].selected = true;
1179
  }
1180
  });
1181
 
1182
- // we need to clear the old values
1183
  $(font_weights).select2().empty();
1184
  $(font_weights).select2({
1185
  data: new_variants
1186
  }).on('change', function ( e ) {
1187
- var select_element = e.target;
1188
- var wraper = $(select_element).closest('.font-options__wrapper');
1189
- update_font_value(wraper);
 
1190
  });
1191
  }
1192
 
@@ -1196,9 +1274,8 @@
1196
  * @param wraper
1197
  */
1198
  function update_subset_field( option, wraper ) {
1199
- var subsets = $(option).data('subsets'),
1200
- font_subsets = wraper.find('.customify_font_subsets'),
1201
- selected_subsets = font_subsets.data('default'),
1202
  new_subsets = [],
1203
  type = $(option).data('type');
1204
 
@@ -1207,9 +1284,12 @@
1207
  return;
1208
  }
1209
 
1210
- var current_value = wraper.children('.customify_font_values').val();
1211
 
1212
  current_value = maybeJsonParse( current_value );
 
 
 
1213
  current_value = current_value.selected_subsets;
1214
 
1215
  subsets = maybeJsonParse( subsets );
@@ -1221,26 +1301,27 @@
1221
  }
1222
 
1223
  // we need to turn the data array into a specific form like [{id:"id", text:"Text"}]
1224
- $.each(subsets, function ( i, j ) {
1225
- new_subsets[i] = {
1226
- 'id': j,
1227
- 'text': j
1228
  };
1229
 
1230
  // current_subsets
1231
- if ( typeof current_value !== 'undefined' && current_value !== null && current_value.indexOf( j ) !== -1 ) {
1232
- new_subsets[i].selected = true;
1233
  }
1234
  });
1235
 
1236
- // we need to clear the old values
1237
  $(font_subsets).select2().empty();
1238
  $(font_subsets).select2({
1239
  data: new_subsets
1240
  }).on('change', function ( e ) {
1241
- var select_element = e.target;
1242
- var wraper = $(select_element).closest('.font-options__wrapper');
1243
- update_font_value(wraper);
 
1244
  });
1245
  }
1246
 
@@ -1249,52 +1330,107 @@
1249
  * It collects values and saves them (encoded) into the `.customify_font_values` input's value
1250
  */
1251
  function update_font_value( wraper ) {
1252
- var element = $(wraper).find('.font-options__wrapper'),
1253
- options_list = $(wraper).find('.font-options__options-list'),
1254
- inputs = options_list.find('select, input'),
1255
- value_holder = wraper.children('.customify_font_values'),
1256
- new_vals = {};
1257
-
1258
- inputs.each(function ( key, el ) {
1259
- var field = $(el).data('field'),
1260
- value = $(el).val();
1261
-
1262
- if ( field === 'font_family' ) {
1263
- // the font family also holds the type
1264
- var selected_opt = $(el.options[el.selectedIndex]),
1265
- type = selected_opt.data('type'),
1266
- subsets = selected_opt.data('subsets'),
1267
- variants = selected_opt.data('variants');
1268
-
1269
- if ( typeof type !== "undefined") {
1270
- new_vals['type'] = type;
1271
- if ( type === 'theme_font' ) {
1272
- new_vals['src'] = selected_opt.data('src');
1273
- }
1274
- }
1275
 
1276
- if ( typeof variants !== "undefined") {
1277
- new_vals['variants'] = maybeJsonParse(variants);
1278
- }
 
1279
 
1280
- if ( typeof subsets !== "undefined") {
1281
- new_vals['subsets'] = maybeJsonParse(subsets);
1282
- }
1283
- }
1284
 
 
 
 
1285
 
1286
- if ( typeof field !== "undefined" && typeof value !== "undefined" && value !== "" ) {
1287
- new_vals[field] = value;
1288
- }
1289
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1290
 
1291
- value_holder.val(encodeValues(new_vals));
1292
 
1293
- return new_vals;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1294
  }
1295
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1296
  var maybeJsonParse = function ( value ) {
1297
- var parsed;
1298
 
1299
  //try and parse it, with decodeURIComponent
1300
  try {
@@ -1502,3 +1638,67 @@
1502
  return true;
1503
  };
1504
  })(jQuery, window, wp);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  'use strict';
3
 
4
  var api = wp.customize;
5
+ var $window = $(window);
6
+
7
+ var scaleIframe = function() {
8
+ var $previewIframe = $('.wp-full-overlay');
9
+
10
+ $previewIframe.find( 'iframe' ).removeAttr( 'style' );
11
+
12
+ if ( api.previewedDevice.get() !== 'desktop' ) { return; }
13
+
14
+ var iframeWidth = $previewIframe.width();
15
+ var windowWidth = $window.width();
16
+ var windowHeight = $window.height();
17
+
18
+ var scale = windowWidth / iframeWidth;
19
+
20
+ if (iframeWidth > 720) {
21
+ $previewIframe.find( 'iframe' ).css( {
22
+ width: iframeWidth * scale,
23
+ height: windowHeight * scale,
24
+ 'transform-origin': 'left top',
25
+ transform: 'scale(' + 1 / scale + ')'
26
+ } );
27
+ }
28
+ };
29
 
30
  // when the customizer is ready prepare our fields events
31
  wp.customize.bind('ready', function () {
32
  var timeout = null;
33
 
34
+ wp.customize.previewer.bind('synced', function() {
35
+ scaleIframe();
36
+
37
+ api.previewedDevice.bind( scaleIframe );
38
+ $window.on('resize', scaleIframe);
39
+ });
40
+
41
  // add ace editors
42
  $('.customify_ace_editor').each(function ( key, el ) {
43
  var id = $(this).attr('id'),
99
  customifyHandleRangeFields(this);
100
  });
101
 
102
+ customifyHandleConnectedFields();
103
+
104
  if ( $('button[data-action="reset_customify"]').length > 0 ) {
105
  // reset_button
106
  $(document).on('click', '#customize-control-reset_customify button', function ( ev ) {
113
  }
114
 
115
  $.each(api.settings.controls, function ( key, ctrl ) {
116
+ var setting_id = key.replace('_control', '');
117
+ var setting = customify_settings.settings[setting_id];
118
 
119
  if ( !_.isUndefined(setting) && !_.isUndefined(setting.default) ) {
120
+ api_set_setting_value(setting_id, setting.default);
 
 
 
 
 
121
  }
122
  });
123
 
154
 
155
  if ( controls.length > 0 ) {
156
  $.each(controls, function ( key, ctrl ) {
157
+ var setting_id = ctrl.id.replace('_control', ''),
158
+ setting = customify_settings.settings[setting_id];
159
 
160
  if ( !_.isUndefined(setting) && !_.isUndefined(setting.default) ) {
161
+ api_set_setting_value(setting_id, setting.default);
 
 
 
 
 
162
  }
163
  });
164
  }
196
 
197
  if ( controls.length > 0 ) {
198
  $.each(controls, function ( key, ctrl ) {
199
+ var setting_id = ctrl.id.replace('_control', ''),
200
+ setting = customify_settings.settings[setting_id];
201
 
202
  if ( !_.isUndefined(setting) && !_.isUndefined(setting.default) ) {
203
+ api_set_setting_value(setting_id, setting.default);
 
 
 
 
 
204
  }
205
  });
206
  }
244
  $input.trigger('change');
245
  });
246
 
247
+ // presets with select
248
  $(document).on('change', '.customify_preset.select', function () {
249
  var this_option = $(this).children('[value="' + $(this).val() + '"]'),
250
  data = $(this_option).data('options');
251
 
252
  if ( !_.isUndefined(data) ) {
253
+ $.each(data, function ( setting_id, value ) {
254
+ api_set_setting_value(setting_id, value);
255
  });
256
  }
 
 
257
  });
258
 
259
+ // presets with radio and other
260
+ $(document).on('click', '.customify_preset.radio input, .customify_preset.radio_buttons input, .customify_preset.color_palette input, .awesome_presets input', function () {
261
+ var this_option = this,
262
  data = $(this_option).data('options');
263
 
264
  if ( !_.isUndefined(data) ) {
265
+ $.each(data, function ( setting_id, value ) {
266
+ api_set_setting_value(setting_id, value);
267
  });
268
  }
 
 
269
  });
270
 
271
  // bind our event on click
301
 
302
  customifyBackgroundJsControl.init();
303
 
304
+ // sometimes a php save may be needed
305
  if ( getUrlVars('save_customizer_once') ) {
306
  api.previewer.save();
307
  }
349
  })();
350
  });
351
 
352
+ const customifyHandleRangeFields = function (el) {
353
 
354
  // For each range input add a number field (for preview mainly - but it can also be used for input)
355
  $(el).find('input[type="range"]').each(function () {
358
 
359
  $clone
360
  .attr('type', 'number')
361
+ .attr('class', 'range-value')
362
+ .removeAttr('data-field');
363
 
364
  $(this).after($clone);
365
  }
374
  $(this).siblings('input[type="range"]').val($(this).val());
375
  });
376
  });
377
+ };
378
+
379
+ /**
380
+ * Setup the necessary binding and logic for the workings of connected fields.
381
+ *
382
+ * A field can define a series of connected fields and when its value changes it will enforce it also on the connected fields.
383
+ * We do this with a light touch taking advantage as much as possible of the wiring already done by the Customizer core logic.
384
+ */
385
+ const customifyHandleConnectedFields = function () {
386
+ // Iterate through all the registered settings and setup the ones that define connected_fields.
387
+ _.each(wp.customize.settings.settings, function (parent_setting_data, parent_setting_id) {
388
+ if (parent_setting_data.hasOwnProperty('connected_fields')) {
389
+ _.each(parent_setting_data.connected_fields, function (connected_field_data) {
390
+ if (_.isUndefined(connected_field_data.setting_id) || !_.isString(connected_field_data.setting_id)) {
391
+ return;
392
+ }
393
+
394
+ // We need to bind to the controlling setting change event and update the connected fields value/setting.
395
+ let parent_setting = wp.customize(parent_setting_id),
396
+ connected_setting = wp.customize(connected_field_data.setting_id);
397
+
398
+ if (!_.isUndefined(parent_setting) && !_.isUndefined(connected_setting)) {
399
+ parent_setting.bind(function (new_value, old_value) {
400
+ // First determine if we need to apply certain filters before setting the new value
401
+ if (!_.isUndefined(connected_field_data.filters)) {
402
+ _.each(connected_field_data.filters, function(filter_config) {
403
+ // @todo The `filter_config` can also have `checks` each with `js_callback` that should be passed before applying.
404
+
405
+ if (!_.isUndefined(filter_config.js_callback) && !_.isUndefined(window[filter_config.js_callback])) {
406
+ // @todo The `filter_config` can also contain `arguments` that should pe passed to the callback
407
+ new_value = window[filter_config.js_callback](new_value);
408
+ }
409
+ })
410
+ }
411
+
412
+ // Update the connected setting value.
413
+ // This will trigger all the necessary events just like in the case of manually setting it.
414
+ connected_setting.set(new_value);
415
+ });
416
+ }
417
+
418
+ })
419
+ }
420
+ });
421
+ };
422
 
423
  /**
424
  * This function will search for all the interdependend fields and make a bound between them.
612
  };
613
 
614
  // get each typography field and bind events
615
+ // @todo Are we still using the typography field since we have the font field?
616
  var prepare_typography_field = function () {
617
 
618
  var $typos = $('.customify_typography_font_family');
629
  });
630
  };
631
 
632
+ var api_set_setting_value = function ( setting_id, value ) {
633
+ let setting = api(setting_id),
 
 
634
  field = $('[data-customize-setting-link="' + setting_id + '"]'),
635
  field_class = $(field).parent().attr('class');
636
 
637
  // Legacy field type
638
  if ( !_.isUndefined(field_class) && field_class === 'customify_typography' ) {
639
 
640
+ let family_select = field.siblings('select');
641
 
642
  if ( _.isString(value) ) {
643
+ let this_option = family_select.find('option[value="' + value + '"]');
644
  $(this_option[0]).attr('selected', 'selected');
645
  update_siblings_selects(family_select);
646
  } else if ( _.isObject(value) ) {
647
+ let this_family_option = family_select.find('option[value="' + value['font_family'] + '"]');
648
+
649
  $(this_family_option[0]).attr('selected', 'selected');
650
 
651
  update_siblings_selects(this_family_option);
652
 
653
  setTimeout(function () {
654
+ let weight_select = field.parent().siblings('.options').find('.customify_typography_font_weight'),
655
+ this_weight_option = weight_select.find('option[value="' + value['selected_variants'] + '"]');
 
656
 
657
  $(this_weight_option[0]).attr('selected', 'selected');
658
 
666
 
667
  } else if( !_.isUndefined(field_class) && field_class === 'font-options__wrapper' ) {
668
 
669
+ // if the value is a simple string it must be the font family
670
  if ( _.isString( value ) ) {
671
+ let option = field.parent().find('option[value="' + value + '"]');
 
672
 
673
  option.attr('selected', 'selected');
674
  // option.parents('select').trigger('change');
675
  } else if ( _.isObject(value) ) {
676
  // Find the options list wrapper
677
+ let optionsList = field.parent().children('.font-options__options-list');
678
 
679
  if ( optionsList.length ) {
680
  // We will process each font property and update it
681
  _.each(value, function (val, key) {
682
  // We need to map the keys to the data attributes we are using - I know :(
683
+ let mappedKey = key;
684
  switch (key) {
685
  case 'font-family':
686
  mappedKey = 'font_family';
700
  default:
701
  break;
702
  }
703
+ let subField = optionsList.find('[data-field="' + mappedKey + '"]');
704
  if ( subField.length ) {
705
  subField.val(val);
706
  subField.trigger('change');
1077
  }
1078
  })(jQuery);
1079
 
1080
+ // This is for the Font control
1081
  var customifyFontSelect = (function () {
1082
+ const
1083
+ wrapperSelector = '.font-options__wrapper',
1084
+ valueHolderSelector = '.customify_font_values',
1085
+ fontFamilySelector = '.customify_font_family',
1086
+ fontWeightSelector = '.customify_font_weight',
1087
+ fontSubsetsSelector = '.customify_font_subsets',
1088
+ selectPlaceholder = "Select a font family",
1089
+ weightPlaceholder = "Select a font weight",
1090
+ subsetPlaceholder = "Extra Subsets";
1091
+
1092
+ // We will use this to remember that we are self-updating the field from the subfields.
1093
+ // We will save this info for each setting ID.
1094
+ var updatingValue = {},
1095
+ loadingValue = {};
1096
 
1097
  function init( wpapi ) {
1098
+ let $fontFamilyFields = $(fontFamilySelector);
 
 
 
 
 
1099
 
1100
+ // Initialize the select2 field for the font family
1101
+ $fontFamilyFields.select2({
1102
+ placeholder: selectPlaceholder
1103
+ }).on('change', function (e) {
1104
+ let new_option = $(e.target).find('option:selected'),
1105
+ wrapper = $(e.target).closest(wrapperSelector);
1106
 
1107
+ // Update the weight subfield with the new options given by the selected font family.
1108
+ update_weight_field(new_option, wrapper);
1109
 
1110
+ // Update the subset subfield with the new options given by the selected font family.
1111
+ update_subset_field(new_option, wrapper);
 
 
 
1112
 
1113
+ // Serialize subfield values and refresh the fonts in the preview window.
1114
+ update_font_value(wrapper);
1115
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1116
 
1117
+ // Initialize the select2 field for the font weight
1118
+ $(fontWeightSelector).each(function (i, el) {
1119
+
1120
+ let select2_args = {
1121
+ placeholder: weightPlaceholder
1122
+ };
1123
+
1124
+ // all this fuss is for the case when the font doesn't come with variants from PHP, like a theme_font
1125
+ if (this.options.length === 0) {
1126
+ var wrapper = $(el).closest(wrapperSelector),
1127
+ font = wrapper.find(fontFamilySelector),
1128
+ option = font[0].options[font[0].selectedIndex],
1129
+ variants = maybeJsonParse($(option).data('variants')),
1130
+ data = [],
1131
+ selecter_variants = $(el).data('default') || null;
1132
+
1133
+ if (typeof variants === "undefined") {
1134
+ $(this).hide();
1135
+ return;
1136
+ }
1137
+
1138
+ $.each(variants, function (index, weight) {
1139
+ let this_value = {
1140
+ id: weight,
1141
+ text: weight
1142
+ };
1143
+
1144
+ if (selecter_variants !== null && weight == selecter_variants) {
1145
+ this_value.selected = true;
1146
+ }
1147
 
1148
+ data.push(this_value);
1149
+ });
 
1150
 
1151
+ if (data !== []) {
1152
+ select2_args.data = data;
1153
+ }
1154
+ }
1155
 
1156
+ $(this).select2(
1157
+ select2_args
1158
+ ).on('change', function (e) {
1159
+ let wrapper = $(e.target).closest(wrapperSelector);
1160
 
1161
+ // Serialize subfield values and refresh the fonts in the preview window.
1162
+ update_font_value(wrapper);
1163
+ });
1164
+ });
 
 
 
 
 
 
 
 
1165
 
1166
+ // Initialize the select2 field for the font subsets
1167
+ $(fontSubsetsSelector)
1168
  .select2({
1169
+ placeholder: subsetPlaceholder
1170
  })
1171
  .on('change', function ( e ) {
1172
+ let wrapper = $(e.target).closest(wrapperSelector);
1173
+
1174
+ // Serialize subfield values and refresh the fonts in the preview window.
1175
+ update_font_value(wrapper);
 
 
 
 
1176
  });
1177
 
1178
+ let rangers = $fontFamilyFields.parents(wrapperSelector).find('input[type=range]'),
1179
+ selects = $fontFamilyFields.parents(wrapperSelector).find('select').not("select[class*=' select2'],select[class^='select2']");
1180
 
1181
+ // Initialize the all the regular selects in the font controls
1182
  if ( selects.length > 0 ) {
1183
  selects.on('change', function ( e ) {
1184
+ let wrapper = $(e.target).closest(wrapperSelector);
1185
+
1186
+ // Serialize subfield values and refresh the fonts in the preview window.
1187
+ update_font_value(wrapper);
 
 
 
 
1188
  });
1189
  }
1190
 
1191
+ // Initialize the all the range fields in the font controls
1192
  if ( rangers.length > 0 ) {
1193
+ rangers.on('change', function ( e ) {
1194
+ let wrapper = $(e.target).closest(wrapperSelector);
1195
+
1196
+ // Serialize subfield values and refresh the fonts in the preview window.
1197
+ update_font_value(wrapper);
 
 
 
 
1198
 
1199
  wp.customize.previewer.send( 'font-changed' );
1200
  });
1201
  }
1202
 
1203
+ // When the previewer window is ready, render the fonts
1204
  var self = this;
 
1205
  wp.customize.previewer.bind( 'ready', function () {
1206
  self.render_fonts();
1207
  });
1208
+
1209
+ // Handle the reverse value direction, when the customize setting is updated and the subfields need to update their values.
1210
+ $fontFamilyFields.each( function( i, el ) {
1211
+ let wrapper = $(el).closest(wrapperSelector),
1212
+ value_holder = wrapper.children(valueHolderSelector),
1213
+ setting_id = $(value_holder).data('customize-setting-link'),
1214
+ setting = wp.customize(setting_id);
1215
+
1216
+ setting.bind( function( newValue, oldValue ) {
1217
+ if ( ! updatingValue[this.id] ) {
1218
+ value_holder.val(newValue);
1219
+
1220
+ load_font_value(wrapper);
1221
+ }
1222
+ })
1223
+ })
1224
  }
1225
 
1226
  /**
1230
  * @param wraper
1231
  */
1232
  function update_weight_field( option, wraper ) {
1233
+ let variants = $(option).data('variants'),
1234
+ font_weights = wraper.find(fontWeightSelector),
1235
  selected_variant = font_weights.data('default'),
1236
  new_variants = [],
1237
+ id = wraper.find(valueHolderSelector).data('customizeSettingLink');
 
1238
 
1239
  variants = maybeJsonParse(variants);
1240
 
1245
  }
1246
 
1247
  // we need to turn the data array into a specific form like [{id:"id", text:"Text"}]
1248
+ $.each(variants, function ( index, variant ) {
1249
+ new_variants[index] = {
1250
+ 'id': variant,
1251
+ 'text': variant
1252
  };
1253
 
1254
+ if ( selected_variant == variant ) {
1255
+ new_variants[index].selected = true;
1256
  }
1257
  });
1258
 
1259
+ // We need to clear the old select2 field and reinitialize it.
1260
  $(font_weights).select2().empty();
1261
  $(font_weights).select2({
1262
  data: new_variants
1263
  }).on('change', function ( e ) {
1264
+ let wrapper = $(e.target).closest(wrapperSelector);
1265
+
1266
+ // Serialize subfield values and refresh the fonts in the preview window.
1267
+ update_font_value(wrapper);
1268
  });
1269
  }
1270
 
1274
  * @param wraper
1275
  */
1276
  function update_subset_field( option, wraper ) {
1277
+ let subsets = $(option).data('subsets'),
1278
+ font_subsets = wraper.find(fontSubsetsSelector),
 
1279
  new_subsets = [],
1280
  type = $(option).data('type');
1281
 
1284
  return;
1285
  }
1286
 
1287
+ let current_value = wraper.children(valueHolderSelector).val();
1288
 
1289
  current_value = maybeJsonParse( current_value );
1290
+ if ( _.isUndefined( current_value.selected_subsets ) ) {
1291
+ return;
1292
+ }
1293
  current_value = current_value.selected_subsets;
1294
 
1295
  subsets = maybeJsonParse( subsets );
1301
  }
1302
 
1303
  // we need to turn the data array into a specific form like [{id:"id", text:"Text"}]
1304
+ $.each(subsets, function ( index, subset ) {
1305
+ new_subsets[index] = {
1306
+ 'id': subset,
1307
+ 'text': subset
1308
  };
1309
 
1310
  // current_subsets
1311
+ if ( typeof current_value !== 'undefined' && current_value !== null && current_value.indexOf( subset ) !== -1 ) {
1312
+ new_subsets[index].selected = true;
1313
  }
1314
  });
1315
 
1316
+ // We need to clear the old select2 field and reinitialize it.
1317
  $(font_subsets).select2().empty();
1318
  $(font_subsets).select2({
1319
  data: new_subsets
1320
  }).on('change', function ( e ) {
1321
+ let wrapper = $(e.target).closest(wrapperSelector);
1322
+
1323
+ // Serialize subfield values and refresh the fonts in the preview window.
1324
+ update_font_value(wrapper);
1325
  });
1326
  }
1327
 
1330
  * It collects values and saves them (encoded) into the `.customify_font_values` input's value
1331
  */
1332
  function update_font_value( wraper ) {
1333
+ let options_list = $(wraper).find('.font-options__options-list'),
1334
+ inputs = options_list.find('[data-field]'),
1335
+ value_holder = wraper.children(valueHolderSelector),
1336
+ setting_id = $(value_holder).data('customize-setting-link'),
1337
+ setting = wp.customize(setting_id),
1338
+ newFontData = {};
1339
+
1340
+ // If we are already self-updating this and we haven't finished, we need to stop here to prevent infinite loops
1341
+ // This call might have come from a subfield detecting the change the triggering a further update_font_value()
1342
+ if ( true === updatingValue[setting_id] ) {
1343
+ return;
1344
+ }
 
 
 
 
 
 
 
 
 
 
 
1345
 
1346
+ // If we are loading this setting value and haven't finished, there is no point in updating it as this would cause infinite loops.
1347
+ if ( true === loadingValue[setting_id] ) {
1348
+ return;
1349
+ }
1350
 
1351
+ // Mark the fact that we are self-updating the field value
1352
+ updatingValue[setting_id] = true;
 
 
1353
 
1354
+ inputs.each(function (key, el) {
1355
+ let field = $(el).data('field'),
1356
+ value = $(el).val();
1357
 
1358
+ if ('font_family' === field) {
1359
+ // the font family also holds the type
1360
+ let selected_opt = $(el.options[el.selectedIndex]),
1361
+ type = selected_opt.data('type'),
1362
+ subsets = selected_opt.data('subsets'),
1363
+ variants = selected_opt.data('variants');
1364
+
1365
+ if (!_.isUndefined(type)) {
1366
+ newFontData['type'] = type;
1367
+ if (type === 'theme_font') {
1368
+ newFontData['src'] = selected_opt.data('src');
1369
+ }
1370
+ }
1371
+
1372
+ if (!_.isUndefined( variants)) {
1373
+ newFontData['variants'] = maybeJsonParse(variants);
1374
+ }
1375
+
1376
+ if (!_.isUndefined(subsets)) {
1377
+ newFontData['subsets'] = maybeJsonParse(subsets);
1378
+ }
1379
+ }
1380
 
 
1381
 
1382
+ if (!_.isUndefined(field) && !_.isUndefined(value) && !_.isNull(value) && value !== '' ) {
1383
+ newFontData[field] = value;
1384
+ }
1385
+ });
1386
+
1387
+ // Serialize the newly gathered font data
1388
+ let serializedNewFontData = encodeValues(newFontData);
1389
+ // Set the serialized value in the hidden field.
1390
+ value_holder.val(serializedNewFontData);
1391
+ // Update also the Customizer setting value.
1392
+ setting.set(serializedNewFontData);
1393
+
1394
+
1395
+ // Finished with the field value self-updating.
1396
+ updatingValue[setting_id] = false;
1397
+
1398
+ return newFontData;
1399
  }
1400
 
1401
+ /**
1402
+ * This function is a reverse of update_font_value(), initializing the entire font field controls based on the value stored in the hidden input.
1403
+ */
1404
+ function load_font_value( wrapper ) {
1405
+ let options_list = $(wrapper).find('.font-options__options-list'),
1406
+ inputs = options_list.find('[data-field]'),
1407
+ value_holder = wrapper.children(valueHolderSelector),
1408
+ value = maybeJsonParse( value_holder.val() ),
1409
+ setting_id = $(value_holder).data('customize-setting-link');
1410
+
1411
+ // If we are already loading this setting value and haven't finished, there is no point in starting again.
1412
+ if ( true === loadingValue[setting_id] ) {
1413
+ return;
1414
+ }
1415
+
1416
+ // Mark the fact that we are loading the field value
1417
+ loadingValue[setting_id] = true;
1418
+
1419
+ inputs.each(function ( key, el ) {
1420
+ let field = $(el).data('field');
1421
+
1422
+ // In the case of select2, only the original selects have the data field, thus excluding select2 created select DOM elements
1423
+ if ( typeof field !== "undefined" && field !== "" && typeof value[field] !== "undefined" ) {
1424
+ $(el).val(value[field]).trigger('change');
1425
+ }
1426
+ });
1427
+
1428
+ // Finished with the field value loading.
1429
+ loadingValue[setting_id] = false;
1430
+ }
1431
+
1432
  var maybeJsonParse = function ( value ) {
1433
+ let parsed;
1434
 
1435
  //try and parse it, with decodeURIComponent
1436
  try {
1638
  return true;
1639
  };
1640
  })(jQuery, window, wp);
1641
+
1642
+
1643
+ // Reverses a hex color to either black or white
1644
+ function customifyInverseHexColorToBlackOrWhite (hex) {
1645
+ return customifyInverseHexColor(hex, true);
1646
+ }
1647
+
1648
+ // Taken from here: https://stackoverflow.com/a/35970186/6260836
1649
+ function customifyInverseHexColor (hex, bw) {
1650
+ if (hex.indexOf('#') === 0) {
1651
+ hex = hex.slice(1);
1652
+ }
1653
+ // convert 3-digit hex to 6-digits.
1654
+ if (hex.length === 3) {
1655
+ hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
1656
+ }
1657
+ if (hex.length !== 6) {
1658
+ throw new Error('Invalid HEX color.');
1659
+ }
1660
+ var r = parseInt(hex.slice(0, 2), 16),
1661
+ g = parseInt(hex.slice(2, 4), 16),
1662
+ b = parseInt(hex.slice(4, 6), 16);
1663
+ if (bw) {
1664
+ // http://stackoverflow.com/a/3943023/112731
1665
+ return (r * 0.299 + g * 0.587 + b * 0.114) > 186
1666
+ ? '#000000'
1667
+ : '#FFFFFF';
1668
+ }
1669
+ // invert color components
1670
+ r = (255 - r).toString(16);
1671
+ g = (255 - g).toString(16);
1672
+ b = (255 - b).toString(16);
1673
+ // pad each with zeros and return
1674
+ return "#" + customifyPadZero(r) + customifyPadZero(g) + customifyPadZero(b);
1675
+ }
1676
+
1677
+ function customifyPadZero(str, len) {
1678
+ len = len || 2;
1679
+ var zeros = new Array(len).join('0');
1680
+ return (zeros + str).slice(-len);
1681
+ }
1682
+
1683
+ // Shading, Blending and Converting colors
1684
+ // Taken from here: https://github.com/PimpTrizkit/PJs/wiki/12.-Shade,-Blend-and-Convert-a-Web-Color-(pSBC.js)
1685
+ const pSBC = function (p, from, to) {
1686
+ if(typeof(p)!="number"||p<-1||p>1||typeof(from)!="string"||(from[0]!='r'&&from[0]!='#')||(to&&typeof(to)!="string"))return null; //ErrorCheck
1687
+ if(!this.pSBCr)this.pSBCr=(d)=>{
1688
+ let l=d.length,RGB={};
1689
+ if(l>9){
1690
+ d=d.split(",");
1691
+ if(d.length<3||d.length>4)return null;//ErrorCheck
1692
+ RGB[0]=i(d[0].split("(")[1]),RGB[1]=i(d[1]),RGB[2]=i(d[2]),RGB[3]=d[3]?parseFloat(d[3]):-1;
1693
+ }else{
1694
+ if(l==8||l==6||l<4)return null; //ErrorCheck
1695
+ if(l<6)d="#"+d[1]+d[1]+d[2]+d[2]+d[3]+d[3]+(l>4?d[4]+""+d[4]:""); //3 or 4 digit
1696
+ d=i(d.slice(1),16),RGB[0]=d>>16&255,RGB[1]=d>>8&255,RGB[2]=d&255,RGB[3]=-1;
1697
+ if(l==9||l==5)RGB[3]=r((RGB[2]/255)*10000)/10000,RGB[2]=RGB[1],RGB[1]=RGB[0],RGB[0]=d>>24&255;
1698
+ }
1699
+ return RGB;}
1700
+ var i=parseInt,r=Math.round,h=from.length>9,h=typeof(to)=="string"?to.length>9?true:to=="c"?!h:false:h,b=p<0,p=b?p*-1:p,to=to&&to!="c"?to:b?"#000000":"#FFFFFF",f=this.pSBCr(from),t=this.pSBCr(to);
1701
+ if(!f||!t)return null; //ErrorCheck
1702
+ if(h)return "rgb"+(f[3]>-1||t[3]>-1?"a(":"(")+r((t[0]-f[0])*p+f[0])+","+r((t[1]-f[1])*p+f[1])+","+r((t[2]-f[2])*p+f[2])+(f[3]<0&&t[3]<0?")":","+(f[3]>-1&&t[3]>-1?r(((t[3]-f[3])*p+f[3])*10000)/10000:t[3]<0?f[3]:t[3])+")");
1703
+ else return "#"+(0x100000000+r((t[0]-f[0])*p+f[0])*0x1000000+r((t[1]-f[1])*p+f[1])*0x10000+r((t[2]-f[2])*p+f[2])*0x100+(f[3]>-1&&t[3]>-1?r(((t[3]-f[3])*p+f[3])*255):t[3]>-1?r(t[3]*255):f[3]>-1?r(f[3]*255):255)).toString(16).slice(1,f[3]>-1||t[3]>-1?undefined:-2);
1704
+ };
js/jquery-react.js CHANGED
@@ -1,6 +1,8 @@
1
  /*
2
  * React JQuery plugin
3
  *
 
 
4
  * Copyright 2011, Nathan Davis Olds
5
  * Distributed under the MIT license.
6
  */
1
  /*
2
  * React JQuery plugin
3
  *
4
+ * https://github.com/natedavisolds/jquery-react
5
+ *
6
  * Copyright 2011, Nathan Davis Olds
7
  * Distributed under the MIT license.
8
  */
mock_style_manager_config.php ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! function_exists('mock_style_manager_section') ) {
3
+
4
+ /**
5
+ * Setup the Style Manager Customizer section and mock some color palettes.
6
+ *
7
+ * @param $config array This holds required keys for the plugin config like 'opt-name', 'panels', 'settings'
8
+ * @return $config
9
+ */
10
+ function mock_style_manager_section( $config ) {
11
+ // If the theme hasn't declared support for style manager, bail.
12
+ if ( ! current_theme_supports( 'customizer_style_manager' ) ) {
13
+ return $config;
14
+ }
15
+
16
+ if ( ! isset( $config['sections']['style_manager_section'] ) ) {
17
+ $config['sections']['style_manager_section'] = array();
18
+ }
19
+
20
+ // The section might be already defined, thus we merge, not replace the entire section config.
21
+ $config['sections']['style_manager_section'] = array_replace_recursive( $config['sections']['style_manager_section'], array(
22
+ 'title' => esc_html__( 'Style Manager', 'customify' ),
23
+ 'section_id' => 'style_manager_section', // We will force this section id preventing prefixing and other regular processing.
24
+ 'options' => array(
25
+ 'sm_color_palette' => array(
26
+ 'type' => 'preset',
27
+ // We will bypass the plugin setting regarding where to store - we will store it cross-theme in wp_options
28
+ 'setting_type' => 'option',
29
+ // We will force this setting id preventing prefixing and other regular processing.
30
+ 'setting_id' => 'sm_color_palette',
31
+ // We don't want to refresh the preview window, even though we have no direct effect on it through this field.
32
+ 'live' => true,
33
+ 'label' => __( 'Select a color palette:', 'customify' ),
34
+ 'desc' => __( 'Conveniently change the design of your site with color palettes. Easy as pie.', 'customify' ),
35
+ 'default' => 'lilac',
36
+ 'choices_type' => 'color_palette',
37
+ 'choices' => array(
38
+ 'vasco' => array(
39
+ 'label' => __( 'Vasco Theme', 'customify' ),
40
+ 'preview' => array(
41
+ 'background_image_url' => 'http://pxgcdn.com/images/style-manager/color-palettes/vasco-theme-palette.jpg',
42
+ ),
43
+ 'options' => array(
44
+ 'sm_color_primary' => '#38C3C8',
45
+ 'sm_color_secondary' => '#F59828',
46
+ 'sm_dark_primary' => '#2b2b28',
47
+ 'sm_dark_secondary' => '#2B3D39',
48
+ 'sm_dark_tertiary' => '#65726F',
49
+ 'sm_light_primary' => '#F5F6F1',
50
+ 'sm_light_secondary' => '#E6F7F7',
51
+ ),
52
+ ),
53
+ 'felt' => array(
54
+ 'label' => __( 'Felt Theme', 'customify' ),
55
+ 'preview' => array(
56
+ 'background_image_url' => 'http://pxgcdn.com/images/style-manager/color-palettes/felt-theme-palette.jpg',
57
+ ),
58
+ 'options' => array(
59
+ 'sm_color_primary' => '#ff6000',
60
+ 'sm_color_secondary' => '#FF9200',
61
+ 'sm_dark_primary' => '#1C1C1C',
62
+ 'sm_dark_secondary' => '#161616',
63
+ 'sm_light_primary' => '#FFFCFC',
64
+ 'sm_light_secondary' => '#fff4e8',
65
+ ),
66
+ ),
67
+ 'julia' => array(
68
+ 'label' => __( 'Julia Theme', 'customify' ),
69
+ 'preview' => array(
70
+ 'background_image_url' => 'http://pxgcdn.com/images/style-manager/color-palettes/julia-theme-palette.jpg',
71
+ ),
72
+ 'options' => array(
73
+ 'sm_color_primary' => '#3349B8',
74
+ 'sm_color_secondary' => '#3393B8',
75
+ 'sm_dark_primary' => '#161616',
76
+ 'sm_dark_secondary' => '#383C50',
77
+ 'sm_light_primary' => '#f7f6f5',
78
+ 'sm_light_secondary' => '#e7f2f8',
79
+ ),
80
+ ),
81
+ 'gema' => array(
82
+ 'label' => __( 'Gema Theme', 'customify' ),
83
+ 'preview' => array(
84
+ 'background_image_url' => 'http://pxgcdn.com/images/style-manager/color-palettes/gema-theme-palette.jpg',
85
+ ),
86
+ 'options' => array(
87
+ 'sm_color_primary' => '#E03A3A',
88
+ 'sm_color_secondary' => '#E03A3A',
89
+ 'sm_dark_primary' => '#000000',
90
+ 'sm_dark_secondary' => '#000000',
91
+ 'sm_dark_tertiary' => '#A3A3A1',
92
+ 'sm_light_primary' => '#FFFFFF',
93
+ 'sm_light_secondary' => '#FFFFFF',
94
+ ),
95
+ ),
96
+ 'patch' => array(
97
+ 'label' => __( 'Patch Theme', 'customify' ),
98
+ 'preview' => array(
99
+ 'background_image_url' => 'http://pxgcdn.com/images/style-manager/color-palettes/patch-theme-palette.jpg',
100
+ ),
101
+ 'options' => array(
102
+ 'sm_color_primary' => '#ffeb00',
103
+ 'sm_color_secondary' => '#3200B2',
104
+ 'sm_dark_primary' => '#171617',
105
+ 'sm_dark_secondary' => '#3d3e40',
106
+ 'sm_dark_tertiary' => '#b5b5b5',
107
+ 'sm_light_primary' => '#FFFFFF',
108
+ 'sm_light_secondary' => '#FFFFFF',
109
+ ),
110
+ ),
111
+ 'silk' => array(
112
+ 'label' => __( 'Silk Theme', 'customify' ),
113
+ 'preview' => array(
114
+ 'background_image_url' => 'http://pxgcdn.com/images/style-manager/color-palettes/silk-theme-palette.jpg',
115
+ ),
116
+ 'options' => array(
117
+ 'sm_color_primary' => '#A33B61',
118
+ 'sm_color_secondary' => '#FCC9B0',
119
+ 'sm_dark_primary' => '#000000',
120
+ 'sm_dark_secondary' => '#000000',
121
+ 'sm_dark_tertiary' => '#A3A3A1',
122
+ 'sm_light_primary' => '#FFFFFF',
123
+ 'sm_light_secondary' => '#FFFFFF',
124
+ ),
125
+ ),
126
+ 'hive' => array(
127
+ 'label' => __( 'Hive Theme', 'customify' ),
128
+ 'preview' => array(
129
+ 'background_image_url' => 'http://pxgcdn.com/images/style-manager/color-palettes/hive-theme-palette.jpg',
130
+ ),
131
+ 'options' => array(
132
+ 'sm_color_primary' => '#ffeb00',
133
+ 'sm_color_secondary' => '#3200B2',
134
+ 'sm_dark_primary' => '#171617',
135
+ 'sm_dark_secondary' => '#171617',
136
+ 'sm_dark_tertiary' => '#363636',
137
+ 'sm_light_primary' => '#FFFFFF',
138
+ 'sm_light_secondary' => '#FFFFFF',
139
+ ),
140
+ ),
141
+ 'lilac' => array(
142
+ 'label' => __( 'Lilac', 'customify' ),
143
+ 'preview' => array(
144
+ 'background_image_url' => 'http://pxgcdn.com/images/style-manager/color-palettes/lilac-palette.jpg',
145
+ ),
146
+ 'options' => array(
147
+ 'sm_color_primary' => '#DD8CA9',
148
+ 'sm_color_secondary' => '#8C9CDE',
149
+ 'sm_dark_primary' => '#303030',
150
+ 'sm_dark_secondary' => '#303030',
151
+ 'sm_dark_tertiary' => '#A3A3A1',
152
+ 'sm_light_primary' => '#ECEEED',
153
+ 'sm_light_secondary' => '#8C9CDE',
154
+ 'sm_light_tertiary' => '#afafaf',
155
+ ),
156
+ ),
157
+ ),
158
+ ),
159
+ 'sm_color_primary' => array(
160
+ 'type' => 'color',
161
+ // We will bypass the plugin setting regarding where to store - we will store it cross-theme in wp_options
162
+ 'setting_type' => 'option',
163
+ // We will force this setting id preventing prefixing and other regular processing.
164
+ 'setting_id' => 'sm_color_primary',
165
+ // We don't want to refresh the preview window, even though we have no direct effect on it through this field.
166
+ 'live' => true,
167
+ 'label' => esc_html__( 'Color Primary', 'customify' ),
168
+ 'default' => '#ffeb00',
169
+ 'connected_fields' => array(),
170
+ ),
171
+ 'sm_color_secondary' => array(
172
+ 'type' => 'color',
173
+ 'setting_type' => 'option',
174
+ 'setting_id' => 'sm_color_secondary',
175
+ 'live' => true,
176
+ 'label' => esc_html__( 'Color Secondary', 'customify' ),
177
+ 'default' => '#00ecff',
178
+ 'connected_fields' => array(),
179
+ ),
180
+ 'sm_dark_primary' => array(
181
+ 'type' => 'color',
182
+ 'setting_type' => 'option',
183
+ 'setting_id' => 'sm_dark_primary',
184
+ 'live' => true,
185
+ 'label' => esc_html__( 'Dark Primary', 'customify' ),
186
+ 'default' => '#171617',
187
+ 'connected_fields' => array(),
188
+ ),
189
+ 'sm_dark_secondary' => array(
190
+ 'type' => 'color',
191
+ 'setting_type' => 'option',
192
+ 'setting_id' => 'sm_dark_secondary',
193
+ 'live' => true,
194
+ 'label' => esc_html__( 'Dark Secondary', 'customify' ),
195
+ 'default' => '#383c50',
196
+ 'connected_fields' => array(),
197
+ ),
198
+ 'sm_dark_tertiary' => array(
199
+ 'type' => 'color',
200
+ 'setting_type' => 'option',
201
+ 'setting_id' => 'sm_dark_tertiary',
202
+ 'live' => true,
203
+ 'label' => esc_html__( 'Dark Tertiary', 'customify' ),
204
+ 'default' => '#65726F',
205
+ 'connected_fields' => array(),
206
+ ),
207
+ 'sm_light_primary' => array(
208
+ 'type' => 'color',
209
+ 'setting_type' => 'option',
210
+ 'setting_id' => 'sm_light_primary',
211
+ 'live' => true,
212
+ 'label' => esc_html__( 'Light Primary', 'customify' ),
213
+ 'default' => '#ffffff',
214
+ 'connected_fields' => array(),
215
+ ),
216
+ 'sm_light_secondary' => array(
217
+ 'type' => 'color',
218
+ 'setting_type' => 'option',
219
+ 'setting_id' => 'sm_light_secondary',
220
+ 'live' => true,
221
+ 'label' => esc_html__( 'Light Secondary', 'customify' ),
222
+ 'default' => '#ffffff',
223
+ 'connected_fields' => array(),
224
+ ),
225
+ ),
226
+ ) );
227
+
228
+ return $config;
229
+ }
230
+ }
231
+ add_filter( 'customify_filter_fields', 'mock_style_manager_section', 12, 1 );
plugin-config.php CHANGED
@@ -11,6 +11,10 @@ $debug = true;
11
 
12
  $customify_config = require $basepath . 'customify_config.php';
13
 
 
 
 
 
14
  return array(
15
  'plugin-name' => 'pixcustomify',
16
  'settings-key' => 'pixcustomify_settings',
@@ -59,4 +63,4 @@ return array(
59
 
60
  )
61
 
62
- ); # config
11
 
12
  $customify_config = require $basepath . 'customify_config.php';
13
 
14
+ // Load our mock customizer section
15
+ // @todo Remove this at some point.
16
+ require_once $basepath . 'mock_style_manager_config.php';
17
+
18
  return array(
19
  'plugin-name' => 'pixcustomify',
20
  'settings-key' => 'pixcustomify_settings',
63
 
64
  )
65
 
66
+ ); # config
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: pixelgrade, euthelup, babbardel, vlad.olaru, cristianfrumusanu, raduconstantin
3
  Tags: customizer, css, editor, live, preview, customizer
4
  Requires at least: 4.7.0
5
- Tested up to: 4.9.1
6
- Stable tag: 1.5.7
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -35,8 +35,21 @@ With [Customify](https://github.com/pixelgrade/customify), developers can easily
35
 
36
  **Made with love by Pixelgrade**
37
 
 
 
 
 
 
 
 
 
38
  == Changelog ==
39
 
 
 
 
 
 
40
  = 1.5.7 =
41
  * Improved development logic for easier testing
42
  * Improved and fixed reset settings buttons
2
  Contributors: pixelgrade, euthelup, babbardel, vlad.olaru, cristianfrumusanu, raduconstantin
3
  Tags: customizer, css, editor, live, preview, customizer
4
  Requires at least: 4.7.0
5
+ Tested up to: 4.9.5
6
+ Stable tag: 1.6.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
35
 
36
  **Made with love by Pixelgrade**
37
 
38
+ == Credits ==
39
+
40
+ * [Select2](https://select2.github.io) JavaScript library - License: MIT
41
+ * [CSSOM.js](https://github.com/NV/CSSOM) JavaScript library - License: MIT
42
+ * [Ace Editor](https://ace.c9.io/) JavaScript editor - License: BSD
43
+ * [jQuery React](https://github.com/natedavisolds/jquery-react) JavaScript jQuery plugin - License: MIT
44
+ * Default [image](https://unsplash.com/photos/OgM4RKdr2kY) for Style Manager Color Palette control - License: (Unsplash)[https://unsplash.com/license]
45
+
46
  == Changelog ==
47
 
48
+ = 1.6.0 =
49
+ * Added Style Manager Customizer section with theme supports logic
50
+ * Added connected fields logic for easy chaining of Customizer controls
51
+ * Fixed a couple of styling inconsistencies regarding the Customizer
52
+
53
  = 1.5.7 =
54
  * Improved development logic for easier testing
55
  * Improved and fixed reset settings buttons
scss/customizer.scss CHANGED
@@ -235,8 +235,6 @@ $background-hover : #f5fcff;
235
  box-shadow: 0px 2px 0px 0px #8DBED7;
236
  border-radius: $fields_border-radius;
237
 
238
- transition: all 0.1s;
239
-
240
  &:hover {
241
  color: white;
242
  text-shadow: none;
@@ -677,7 +675,7 @@ $background-hover : #f5fcff;
677
 
678
  .wp-full-overlay-sidebar-content .customize-control {
679
 
680
- input[type=text]:not(#_customize-input-wpcom_custom_css_content_width_control),
681
  input[type=checkbox],
682
  input[type=password],
683
  input[type=color],
@@ -730,6 +728,10 @@ $background-hover : #f5fcff;
730
  }
731
  }
732
 
 
 
 
 
733
  &.customize-control-checkbox:not(#customize-control-jetpack_css_mode_control),
734
  &.customize-control-radio {
735
 
@@ -1568,7 +1570,7 @@ ul.font-options__options-list {
1568
  @extend %select;
1569
  -webkit-appearance: initial;
1570
 
1571
- padding: 8px 8px 4px;
1572
  height: auto;
1573
  background: none;
1574
 
@@ -1578,6 +1580,17 @@ ul.font-options__options-list {
1578
 
1579
  .select2-selection__rendered {
1580
  padding: 0;
 
 
 
 
 
 
 
 
 
 
 
1581
 
1582
  .select2-selection__choice {
1583
  padding: 3px 7px;
@@ -1593,12 +1606,20 @@ ul.font-options__options-list {
1593
  .select2-search--inline {
1594
 
1595
  .select2-search__field {
1596
- height: 24px;
 
 
1597
  }
1598
  }
1599
 
1600
  }
1601
 
 
 
 
 
 
 
1602
  .select2-container {
1603
  .select2-dropdown {
1604
  border-color: $borders;
@@ -1789,4 +1810,128 @@ ul.font-options__options-list {
1789
  .condition-top select {
1790
  width: 130px;
1791
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1792
  }
235
  box-shadow: 0px 2px 0px 0px #8DBED7;
236
  border-radius: $fields_border-radius;
237
 
 
 
238
  &:hover {
239
  color: white;
240
  text-shadow: none;
675
 
676
  .wp-full-overlay-sidebar-content .customize-control {
677
 
678
+ input[type=text]:not(#_customize-input-wpcom_custom_css_content_width_control):not(.wp-color-picker),
679
  input[type=checkbox],
680
  input[type=password],
681
  input[type=color],
728
  }
729
  }
730
 
731
+ .awesome_preset input[type=radio]:checked {
732
+ background: transparent;
733
+ }
734
+
735
  &.customize-control-checkbox:not(#customize-control-jetpack_css_mode_control),
736
  &.customize-control-radio {
737
 
1570
  @extend %select;
1571
  -webkit-appearance: initial;
1572
 
1573
+ padding: 4px 8px 4px;
1574
  height: auto;
1575
  background: none;
1576
 
1580
 
1581
  .select2-selection__rendered {
1582
  padding: 0;
1583
+ display: flex;
1584
+
1585
+ .select2-search--inline {
1586
+ flex: 1;
1587
+
1588
+ .select2-search__field[class] {
1589
+ min-width: 100%;
1590
+ border-width: 0;
1591
+ margin-top: 3px !important;
1592
+ }
1593
+ }
1594
 
1595
  .select2-selection__choice {
1596
  padding: 3px 7px;
1606
  .select2-search--inline {
1607
 
1608
  .select2-search__field {
1609
+ height: 29px;
1610
+ min-width: 9em;
1611
+ margin-top: 0;
1612
  }
1613
  }
1614
 
1615
  }
1616
 
1617
+ .select2-container--default .select2-results__option[aria-selected=true][class] {
1618
+ background: transparent;
1619
+ opacity: 0.3;
1620
+ pointer-events: none;
1621
+ }
1622
+
1623
  .select2-container {
1624
  .select2-dropdown {
1625
  border-color: $borders;
1810
  .condition-top select {
1811
  width: 130px;
1812
  }
1813
+ }
1814
+
1815
+
1816
+
1817
+ //------------------------------------*\
1818
+ // STYLE MANAGER
1819
+ //------------------------------------*/
1820
+
1821
+ .pix_customizer_setting {
1822
+ .customize-inside-control-row {
1823
+ position: relative;
1824
+ width: 100% !important;
1825
+ margin-left: 0 !important;
1826
+ text-indent: 0 !important;
1827
+ background-size: cover;
1828
+ background-position: 50% 50%;
1829
+ height: 64px;
1830
+ border-radius: 5px;
1831
+ overflow: hidden;
1832
+
1833
+ &:before {
1834
+ content: '';
1835
+ position: absolute;
1836
+ top: 0;
1837
+ bottom: 0;
1838
+ left: 0;
1839
+ right: 0;
1840
+ z-index: 10;
1841
+ pointer-events: none;
1842
+
1843
+ box-shadow: inset 0 0 3px 0 rgba(0,0,0,0.15), inset 0 1px 3px 0 rgba(0,0,0,0.15);
1844
+ }
1845
+
1846
+ // Color Palette Hover
1847
+ &:hover {
1848
+
1849
+ &:before {
1850
+ // Increase the inner shadow strongness
1851
+ box-shadow: inset 0 2px 3px 0 rgba(0,0,0,0.15), inset 0 0 3px 0 rgba(0,0,0,0.15);
1852
+ }
1853
+
1854
+ .palette {
1855
+
1856
+ }
1857
+
1858
+ .palette__item {
1859
+ transform: translateY(0%);
1860
+ }
1861
+
1862
+ label {
1863
+ left: 10px;
1864
+ }
1865
+ }
1866
+
1867
+ input {
1868
+ opacity: 0;
1869
+ }
1870
+
1871
+ label {
1872
+ position: absolute;
1873
+ display: flex;
1874
+ z-index: 2;
1875
+
1876
+ width: 100%;
1877
+ height: 100%;
1878
+ top: 0;
1879
+ left: 0;
1880
+
1881
+ padding: 0 10px;
1882
+ margin-top: 0 !important;
1883
+ align-items: center;
1884
+
1885
+ transition: all .3s ease;
1886
+ }
1887
+
1888
+ .label__inner {
1889
+ padding: 7px 12px 7px 7px;
1890
+ z-index: 2;
1891
+ border-radius: 3px;
1892
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);
1893
+ }
1894
+
1895
+ .palette {
1896
+ position: absolute;
1897
+ display: flex;
1898
+ top: 0;
1899
+ left: 0;
1900
+ z-index: 1;
1901
+ width: 100%;
1902
+ height: 100%;
1903
+
1904
+ transition: all .2s ease;
1905
+ }
1906
+
1907
+ // Colors Bars
1908
+ .palette__item {
1909
+ flex: 1;
1910
+ transform: translateY(100%);
1911
+
1912
+ transition: all .3s ease;
1913
+
1914
+ // Assume maximum 10 colors
1915
+ @for $i from 1 through 10 {
1916
+ &:nth-child(#{$i}) {
1917
+ transition-delay: 0s + $i/20 - 1/20;
1918
+
1919
+ // PLAYGROUND:
1920
+ // Size items based on color accent
1921
+ // Higher size for accent colors
1922
+ // Lower sizes for light colors
1923
+
1924
+ // flex-grow: 1/$i * 10 + $i/10;
1925
+ }
1926
+ }
1927
+ }
1928
+
1929
+ .preview__letter {
1930
+ display: inline-block;
1931
+ padding: 3px 9px;
1932
+ border-radius: 2px;
1933
+ color: white;
1934
+ margin-right: 5px;
1935
+ }
1936
+ }
1937
  }