Unyson - Version 2.6.2

Version Description

  • Option-types must be loaded on fw_option_types_init action #1827
  • Option-type icon-v2 refactor
  • Fixed #1491, #1979, #1970, #1954
Download this release

Release Info

Developer Unyson
Plugin Icon 128x128 Unyson
Version 2.6.2
Comparing to
See all releases

Code changes from version 2.6.1 to 2.6.2

Files changed (47) hide show
  1. framework/bin/load-latest-fonts.php +22 -1
  2. framework/core/Fw.php +0 -2
  3. framework/core/components/backend.php +33 -86
  4. framework/core/extends/class-fw-option-type.php +4 -4
  5. framework/core/extends/interface-fw-option-handler.php +1 -0
  6. framework/helpers/class-fw-db-options-model.php +2 -3
  7. framework/helpers/class-fw-file-cache.php +50 -17
  8. framework/includes/container-types/tab/view.php +4 -1
  9. framework/includes/hooks.php +36 -6
  10. framework/includes/option-types/addable-box/class-fw-option-type-addable-box.php +19 -13
  11. framework/includes/option-types/addable-option/class-fw-option-type-addable-option.php +19 -13
  12. framework/includes/option-types/addable-popup/class-fw-option-type-addable-popup.php +20 -14
  13. framework/includes/option-types/color-picker/class-fw-option-type-color-picker.php +1 -1
  14. framework/includes/option-types/color-picker/static/js/scripts.js +12 -19
  15. framework/includes/option-types/gradient/static/js/scripts.js +14 -11
  16. framework/includes/option-types/icon-v2/class-fw-option-type-icon-v2.php +27 -22
  17. framework/includes/option-types/icon-v2/includes/class-fw-icon-v2-favorites.php +12 -0
  18. framework/includes/option-types/icon-v2/includes/class-fw-icon-v2-packs-loader.php +47 -9
  19. framework/includes/option-types/icon-v2/static/css/picker.css +2 -2
  20. framework/includes/option-types/icon-v2/static/js/icon-picker-v2.js +496 -0
  21. framework/includes/option-types/icon-v2/static/js/icon-picker.js +0 -466
  22. framework/includes/option-types/icon-v2/static/js/render-icon-previews.js +20 -4
  23. framework/includes/option-types/icon-v2/views/templates.php +176 -0
  24. framework/includes/option-types/icon-v2/{view.php → views/view.php} +1 -0
  25. framework/includes/option-types/image-picker/class-fw-option-type-image-picker.php +7 -4
  26. framework/includes/option-types/multi-picker/class-fw-option-type-multi-picker.php +19 -13
  27. framework/includes/option-types/multi/class-fw-option-type-multi.php +12 -6
  28. framework/includes/option-types/multi/static/css/styles.css +4 -0
  29. framework/includes/option-types/oembed/view.php +10 -7
  30. framework/includes/option-types/popup/class-fw-option-type-popup.php +26 -15
  31. framework/includes/option-types/upload/static/js/any-files.js +49 -20
  32. framework/includes/option-types/upload/static/js/images-only.js +103 -68
  33. framework/manifest.php +1 -1
  34. framework/static/css/backend-options.css +1 -0
  35. framework/static/css/option-types.css +8 -3
  36. framework/static/js/backend-options.js +4 -2
  37. framework/static/js/fw-form-helpers.js +47 -29
  38. framework/static/js/fw.js +22 -5
  39. framework/static/libs/font-awesome/fonts/FontAwesome.otf +0 -0
  40. framework/static/libs/font-awesome/fonts/fontawesome-webfont.eot +0 -0
  41. framework/static/libs/font-awesome/fonts/fontawesome-webfont.svg +8 -8
  42. framework/static/libs/font-awesome/fonts/fontawesome-webfont.ttf +0 -0
  43. framework/static/libs/font-awesome/fonts/fontawesome-webfont.woff +0 -0
  44. framework/static/libs/font-awesome/fonts/fontawesome-webfont.woff2 +0 -0
  45. framework/views/backend-settings-form.php +7 -0
  46. readme.txt +6 -1
  47. unyson.php +1 -1
framework/bin/load-latest-fonts.php CHANGED
@@ -60,6 +60,21 @@ $packs = array(
60
  'to' => "url('../fonts/typicons"
61
  )
62
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  )
64
  );
65
 
@@ -86,10 +101,16 @@ function download_css($pack) {
86
 
87
  $url = github_or_network_for($pack['css-file'], $pack);
88
 
 
 
 
 
 
 
89
  download_file(
90
  $url,
91
  // __DIR__ . '/static/css/' . $pack['name'] . '.css'
92
- get_libs_dir() . $pack['name'] . '/css/' . $pack['name'] . '.css'
93
  );
94
  }
95
 
60
  'to' => "url('../fonts/typicons"
61
  )
62
  )
63
+ ),
64
+
65
+ 'font-awesome' => array(
66
+ 'name' => 'font-awesome',
67
+ 'github-repo' => 'FortAwesome/Font-Awesome',
68
+ 'css-file' => 'css/font-awesome.min.css',
69
+ 'css-file-output' => 'font-awesome.min.css',
70
+ 'fonts' => array(
71
+ 'fonts/FontAwesome.otf',
72
+ 'fonts/fontawesome-webfont.eot',
73
+ 'fonts/fontawesome-webfont.svg',
74
+ 'fonts/fontawesome-webfont.ttf',
75
+ 'fonts/fontawesome-webfont.woff',
76
+ 'fonts/fontawesome-webfont.woff2'
77
+ )
78
  )
79
  );
80
 
101
 
102
  $url = github_or_network_for($pack['css-file'], $pack);
103
 
104
+ $file_name = $pack['name'] . '.css';
105
+
106
+ if (isset($pack['css-file-output'])) {
107
+ $file_name = $pack['css-file-output'];
108
+ }
109
+
110
  download_file(
111
  $url,
112
  // __DIR__ . '/static/css/' . $pack['name'] . '.css'
113
+ get_libs_dir() . $pack['name'] . '/css/' . $file_name
114
  );
115
  }
116
 
framework/core/Fw.php CHANGED
@@ -45,8 +45,6 @@ final class _Fw
45
  }
46
 
47
  require $fw_dir .'/core/extends/class-fw-extension.php';
48
- require $fw_dir .'/core/extends/class-fw-option-type.php';
49
- require $fw_dir .'/core/extends/class-fw-container-type.php';
50
  require $fw_dir .'/core/extends/interface-fw-option-handler.php'; // option handler (experimental)
51
 
52
  // components
45
  }
46
 
47
  require $fw_dir .'/core/extends/class-fw-extension.php';
 
 
48
  require $fw_dir .'/core/extends/interface-fw-option-handler.php'; // option handler (experimental)
49
 
50
  // components
framework/core/components/backend.php CHANGED
@@ -703,7 +703,6 @@ final class _FW_Component_Backend {
703
  'limit_option_types' => false,
704
  'limit_container_types' => false,
705
  'limit_level' => 1,
706
- 'info_wrapper' => true,
707
  ) );
708
 
709
  if (empty($collected)) {
@@ -712,27 +711,27 @@ final class _FW_Component_Backend {
712
 
713
  $values = fw_get_db_post_option( $post->ID );
714
 
715
- foreach ( $collected as &$option ) {
716
  if (
717
- $option['group'] === 'container'
718
  &&
719
- $option['option']['type'] === 'box'
720
  ) { // this is a box, add it as a metabox
721
- $context = isset( $option['option']['context'] )
722
- ? $option['option']['context']
723
  : 'normal';
724
- $priority = isset( $option['option']['priority'] )
725
- ? $option['option']['priority']
726
  : 'default';
727
 
728
  add_meta_box(
729
- 'fw-options-box-' . $option['id'],
730
- empty( $option['option']['title'] ) ? ' ' : $option['option']['title'],
731
  $this->print_meta_box_content_callback,
732
  $post_type,
733
  $context,
734
  $priority,
735
- $this->render_options( $option['option']['options'], $values )
736
  );
737
  } else { // this is not a box, wrap it in auto-generated box
738
  add_meta_box(
@@ -742,7 +741,7 @@ final class _FW_Component_Backend {
742
  $post_type,
743
  'normal',
744
  'default',
745
- $this->render_options( array($option['id'] => $option['option']), $values )
746
  );
747
  }
748
  }
@@ -842,39 +841,6 @@ final class _FW_Component_Backend {
842
  }
843
  }
844
 
845
- /**
846
- * Experimental custom options save
847
- * @param array $options
848
- * @param array $values
849
- * @return array
850
- */
851
- private function process_options_handlers($options, $values)
852
- {
853
- $handled_values = array();
854
-
855
- foreach (
856
- fw_extract_only_options($options)
857
- as $option_id => $option
858
- ) {
859
- if (
860
- isset($option['option_handler'])
861
- &&
862
- $option['option_handler'] instanceof FW_Option_Handler
863
- ) {
864
- /*
865
- * if the option has a custom option_handler
866
- * the saving is delegated to the handler,
867
- * so it does not go to the post_meta
868
- */
869
- $option['option_handler']->save_option_value($option_id, $option, $values[$option_id]);
870
-
871
- $handled_values[$option_id] = true;
872
- }
873
- }
874
-
875
- return $handled_values;
876
- }
877
-
878
  /**
879
  * Save meta from $_POST to fw options (post meta)
880
  * @param int $post_id
@@ -907,19 +873,12 @@ final class _FW_Component_Backend {
907
  }
908
 
909
  $old_values = (array)fw_get_db_post_option($post_id);
910
- $current_values = fw_get_options_values_from_input(
911
- fw()->theme->get_post_options($post->post_type)
912
- );
913
 
914
  fw_set_db_post_option(
915
  $post_id,
916
  null,
917
- array_diff_key( // remove handled values
918
- $current_values,
919
- $this->process_options_handlers(
920
- fw()->theme->get_post_options($post->post_type),
921
- $current_values
922
- )
923
  )
924
  );
925
 
@@ -949,19 +908,11 @@ final class _FW_Component_Backend {
949
  break;
950
  }
951
 
952
- $current_values = fw_get_options_values_from_input(
953
- fw()->theme->get_post_options($parent->post_type)
954
- );
955
-
956
  fw_set_db_post_option(
957
  $post->ID,
958
  null,
959
- array_diff_key( // remove handled values
960
- $current_values,
961
- $this->process_options_handlers(
962
- fw()->theme->get_post_options($parent->post_type),
963
- $current_values
964
- )
965
  )
966
  );
967
  } while(false);
@@ -1266,7 +1217,9 @@ final class _FW_Component_Backend {
1266
  }
1267
 
1268
  wp_send_json_success( array(
1269
- 'html' => fw()->backend->render_options( $options, $values, $data )
 
 
1270
  ) );
1271
  }
1272
 
@@ -1557,6 +1510,8 @@ final class _FW_Component_Backend {
1557
  * @param array $options
1558
  */
1559
  public function enqueue_options_static( $options ) {
 
 
1560
  if (
1561
  !doing_action('admin_enqueue_scripts')
1562
  &&
@@ -1574,11 +1529,15 @@ final class _FW_Component_Backend {
1574
  * in case if this method is called before enqueue_scripts action
1575
  * and option types has some of these in their dependencies
1576
  */
1577
- $this->register_static();
1578
-
1579
- wp_enqueue_media();
1580
- wp_enqueue_style( 'fw-backend-options' );
1581
- wp_enqueue_script( 'fw-backend-options' );
 
 
 
 
1582
  }
1583
 
1584
  $collected = array();
@@ -1644,18 +1603,6 @@ final class _FW_Component_Backend {
1644
  $data['id_prefix'] = FW_Option_Type::get_default_id_prefix();
1645
  }
1646
 
1647
- if (
1648
- isset($option['option_handler']) &&
1649
- $option['option_handler'] instanceof FW_Option_Handler
1650
- ) {
1651
-
1652
- /*
1653
- * if the option has a custom option_handler
1654
- * then the handler provides the option's value
1655
- */
1656
- $data['value'] = $option['option_handler']->get_option_value($id, $option, $data);
1657
- }
1658
-
1659
  $data = apply_filters(
1660
  'fw:backend:option-render:data',
1661
  $data
@@ -1851,8 +1798,8 @@ final class _FW_Component_Backend {
1851
  * @return FW_Option_Type|FW_Option_Type_Undefined
1852
  */
1853
  public function option_type( $option_type ) {
1854
- if ( is_array( $this->option_types_pending_registration ) ) {
1855
- // This method is called first time
1856
 
1857
  do_action('fw_option_types_init');
1858
 
@@ -1898,8 +1845,8 @@ final class _FW_Component_Backend {
1898
  * @return FW_Container_Type|FW_Container_Type_Undefined
1899
  */
1900
  public function container_type( $container_type ) {
1901
- if ( is_array( $this->container_types_pending_registration ) ) {
1902
- // This method is called first time
1903
 
1904
  do_action('fw_container_types_init');
1905
 
703
  'limit_option_types' => false,
704
  'limit_container_types' => false,
705
  'limit_level' => 1,
 
706
  ) );
707
 
708
  if (empty($collected)) {
711
 
712
  $values = fw_get_db_post_option( $post->ID );
713
 
714
+ foreach ( $collected as $id => &$option ) {
715
  if (
716
+ isset($option['options']) // container
717
  &&
718
+ $option['type'] === 'box'
719
  ) { // this is a box, add it as a metabox
720
+ $context = isset( $option['context'] )
721
+ ? $option['context']
722
  : 'normal';
723
+ $priority = isset( $option['priority'] )
724
+ ? $option['priority']
725
  : 'default';
726
 
727
  add_meta_box(
728
+ 'fw-options-box-' . $id,
729
+ empty( $option['title'] ) ? ' ' : $option['title'],
730
  $this->print_meta_box_content_callback,
731
  $post_type,
732
  $context,
733
  $priority,
734
+ $this->render_options( $option['options'], $values )
735
  );
736
  } else { // this is not a box, wrap it in auto-generated box
737
  add_meta_box(
741
  $post_type,
742
  'normal',
743
  'default',
744
+ $this->render_options( array($id => $option), $values )
745
  );
746
  }
747
  }
841
  }
842
  }
843
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
844
  /**
845
  * Save meta from $_POST to fw options (post meta)
846
  * @param int $post_id
873
  }
874
 
875
  $old_values = (array)fw_get_db_post_option($post_id);
 
 
 
876
 
877
  fw_set_db_post_option(
878
  $post_id,
879
  null,
880
+ fw_get_options_values_from_input(
881
+ fw()->theme->get_post_options($post->post_type)
 
 
 
 
882
  )
883
  );
884
 
908
  break;
909
  }
910
 
 
 
 
 
911
  fw_set_db_post_option(
912
  $post->ID,
913
  null,
914
+ fw_get_options_values_from_input(
915
+ fw()->theme->get_post_options($parent->post_type)
 
 
 
 
916
  )
917
  );
918
  } while(false);
1217
  }
1218
 
1219
  wp_send_json_success( array(
1220
+ 'html' => fw()->backend->render_options( $options, $values, $data ),
1221
+ /** @since 2.6.1 */
1222
+ 'default_values' => fw_get_options_values_from_input($options, array()),
1223
  ) );
1224
  }
1225
 
1510
  * @param array $options
1511
  */
1512
  public function enqueue_options_static( $options ) {
1513
+ static $static_enqueue = true;
1514
+
1515
  if (
1516
  !doing_action('admin_enqueue_scripts')
1517
  &&
1529
  * in case if this method is called before enqueue_scripts action
1530
  * and option types has some of these in their dependencies
1531
  */
1532
+ if ($static_enqueue) {
1533
+ $this->register_static();
1534
+
1535
+ wp_enqueue_media();
1536
+ wp_enqueue_style( 'fw-backend-options' );
1537
+ wp_enqueue_script( 'fw-backend-options' );
1538
+
1539
+ $static_enqueue = false;
1540
+ }
1541
  }
1542
 
1543
  $collected = array();
1603
  $data['id_prefix'] = FW_Option_Type::get_default_id_prefix();
1604
  }
1605
 
 
 
 
 
 
 
 
 
 
 
 
 
1606
  $data = apply_filters(
1607
  'fw:backend:option-render:data',
1608
  $data
1798
  * @return FW_Option_Type|FW_Option_Type_Undefined
1799
  */
1800
  public function option_type( $option_type ) {
1801
+ if ( is_array( $this->option_types_pending_registration ) ) { // This method is called for the first time
1802
+ require_once dirname(__FILE__) .'/../extends/class-fw-option-type.php';
1803
 
1804
  do_action('fw_option_types_init');
1805
 
1845
  * @return FW_Container_Type|FW_Container_Type_Undefined
1846
  */
1847
  public function container_type( $container_type ) {
1848
+ if ( is_array( $this->container_types_pending_registration ) ) { // This method is called for the first time
1849
+ require_once dirname(__FILE__) .'/../extends/class-fw-container-type.php';
1850
 
1851
  do_action('fw_container_types_init');
1852
 
framework/core/extends/class-fw-option-type.php CHANGED
@@ -198,6 +198,10 @@ abstract class FW_Option_Type
198
  */
199
  final public function enqueue_static($id = '', $option = array(), $data = array())
200
  {
 
 
 
 
201
  if (
202
  !doing_action('admin_enqueue_scripts')
203
  &&
@@ -233,10 +237,6 @@ abstract class FW_Option_Type
233
  }
234
  }
235
 
236
- if ($this->static_enqueued) {
237
- return false;
238
- }
239
-
240
  $this->prepare($id, $option, $data);
241
 
242
  $call_next_time = $this->_enqueue_static($id, $option, $data);
198
  */
199
  final public function enqueue_static($id = '', $option = array(), $data = array())
200
  {
201
+ if ($this->static_enqueued) {
202
+ return false;
203
+ }
204
+
205
  if (
206
  !doing_action('admin_enqueue_scripts')
207
  &&
237
  }
238
  }
239
 
 
 
 
 
240
  $this->prepare($id, $option, $data);
241
 
242
  $call_next_time = $this->_enqueue_static($id, $option, $data);
framework/core/extends/interface-fw-option-handler.php CHANGED
@@ -2,6 +2,7 @@
2
 
3
  /**
4
  * @deprecated since 2.5.0
 
5
  */
6
  interface FW_Option_Handler
7
  {
2
 
3
  /**
4
  * @deprecated since 2.5.0
5
+ * Will be removed soon https://github.com/ThemeFuse/Unyson/issues/1937
6
  */
7
  interface FW_Option_Handler
8
  {
framework/helpers/class-fw-db-options-model.php CHANGED
@@ -128,8 +128,7 @@ abstract class FW_Db_Options_Model {
128
 
129
  /**
130
  * If db value is not found and default value is provided
131
- * return default value before loading options file
132
- * to prevent infinite recursion in case if this function is called in options file
133
  */
134
  if ( ! is_null($default_value) ) {
135
  if ( empty( $option_id ) ) {
@@ -258,4 +257,4 @@ abstract class FW_Db_Options_Model {
258
 
259
  $this->_after_set($item_id, $option_id, $sub_keys, $old_value, $extra_data);
260
  }
261
- }
128
 
129
  /**
130
  * If db value is not found and default value is provided
131
+ * return default value before the options file is loaded
 
132
  */
133
  if ( ! is_null($default_value) ) {
134
  if ( empty( $option_id ) ) {
257
 
258
  $this->_after_set($item_id, $option_id, $sub_keys, $old_value, $extra_data);
259
  }
260
+ }
framework/helpers/class-fw-file-cache.php CHANGED
@@ -41,6 +41,13 @@ class FW_File_Cache {
41
  */
42
  private static $cache;
43
 
 
 
 
 
 
 
 
44
  private static function get_defaults() {
45
  return array(
46
  'created' => time(),
@@ -50,18 +57,33 @@ class FW_File_Cache {
50
  }
51
 
52
  private static function load() {
53
- if ( is_array( self::$cache ) ) {
54
- return true; // already loaded
 
 
 
 
 
 
 
55
  }
56
 
57
- $dir = dirname(self::$path);
58
- $path = self::$path;
59
  $code = '<?php return array();';
60
  $shhh = defined('DOING_AJAX') && DOING_AJAX; // prevent warning in ajax requests
61
 
 
 
 
62
  // check directory
63
  if ( ! file_exists($dir) ) {
64
- if ( ! mkdir($dir, 0755, true) ) {
 
 
 
 
 
65
  return false;
66
  }
67
  }
@@ -75,7 +97,10 @@ class FW_File_Cache {
75
  : unlink($path)
76
  )
77
  &&
78
- file_put_contents($path, $code, LOCK_EX)
 
 
 
79
  ) {
80
  // file re-created
81
  } else {
@@ -122,11 +147,13 @@ class FW_File_Cache {
122
  return true;
123
  }
124
 
125
- private static function update_path() {
126
- $path = wp_upload_dir();
127
- $path = fw_fix_path($path['basedir']) .'/fw/file-cache.php';
 
 
128
 
129
- self::$path = $path;
130
  }
131
 
132
  /**
@@ -139,7 +166,7 @@ class FW_File_Cache {
139
  }
140
 
141
  self::save();
142
- self::update_path();
143
  self::$cache = self::get_defaults();
144
  self::$changed = true;
145
 
@@ -155,10 +182,10 @@ class FW_File_Cache {
155
 
156
  if (!(
157
  $shhh
158
- ? @file_put_contents(self::$path, '<?php return ' . var_export(self::$cache, true) . ';', LOCK_EX)
159
- : file_put_contents(self::$path, '<?php return ' . var_export(self::$cache, true) . ';', LOCK_EX)
160
  )) {
161
- @file_put_contents(self::$path, '<?php return array();', LOCK_EX);
162
  }
163
 
164
  self::$changed = false;
@@ -168,8 +195,6 @@ class FW_File_Cache {
168
  * @internal
169
  */
170
  public static function _init() {
171
- self::update_path();
172
-
173
  /**
174
  * Reset when current user is administrator
175
  * because it can be a developer that added/removed some files
@@ -183,7 +208,6 @@ class FW_File_Cache {
183
  * - after some files was added/deleted
184
  */
185
  foreach (array(
186
- 'switch_blog' => true,
187
  'fw_extensions_before_activation' => true,
188
  'fw_extensions_after_activation' => true,
189
  'fw_extensions_before_deactivation' => true,
@@ -197,12 +221,14 @@ class FW_File_Cache {
197
  'upgrader_post_install' => true,
198
  'automatic_updates_complete' => true,
199
  'upgrader_process_complete' => true,
 
200
  ) as $action => $x) {
201
  add_action( $action, array(__CLASS__, 'reset') );
202
  }
203
  }
204
 
205
  add_action( 'shutdown', array(__CLASS__, 'save') );
 
206
  }
207
 
208
  /**
@@ -238,6 +264,13 @@ class FW_File_Cache {
238
 
239
  return true;
240
  }
 
 
 
 
 
 
 
241
  }
242
 
243
  class FW_File_Cache_Not_Found_Exception extends Exception {}
41
  */
42
  private static $cache;
43
 
44
+ /**
45
+ * If this was changed then cache must reset
46
+ * Fixes https://github.com/ThemeFuse/Unyson/issues/1986
47
+ * @var int
48
+ */
49
+ private static $blog_id;
50
+
51
  private static function get_defaults() {
52
  return array(
53
  'created' => time(),
57
  }
58
 
59
  private static function load() {
60
+ if ( is_null(self::$blog_id) ) {
61
+ self::$blog_id = get_current_blog_id();
62
+ self::reset();
63
+ } else {
64
+ if (is_array(self::$cache)) {
65
+ return true; // already loaded
66
+ } elseif (false === self::$cache) {
67
+ return false;
68
+ }
69
  }
70
 
71
+ $dir = dirname(self::get_path());
72
+ $path = self::get_path();
73
  $code = '<?php return array();';
74
  $shhh = defined('DOING_AJAX') && DOING_AJAX; // prevent warning in ajax requests
75
 
76
+ // prevent useless multiple execution of this method when uploads/ is not writable
77
+ self::$cache = false;
78
+
79
  // check directory
80
  if ( ! file_exists($dir) ) {
81
+ if ( ! is_writable( dirname( $dir ) )) { // check parent dir if writable ( should be uploads/ )
82
+ return false;
83
+ } elseif ( ! ( $shhh
84
+ ? @mkdir($dir, 0755, true)
85
+ : mkdir($dir, 0755, true)
86
+ ) ) {
87
  return false;
88
  }
89
  }
97
  : unlink($path)
98
  )
99
  &&
100
+ ( $shhh
101
+ ? @file_put_contents($path, $code, LOCK_EX)
102
+ : file_put_contents($path, $code, LOCK_EX)
103
+ )
104
  ) {
105
  // file re-created
106
  } else {
147
  return true;
148
  }
149
 
150
+ private static function get_path() {
151
+ if (is_null(self::$path)) {
152
+ self::$path = wp_upload_dir();
153
+ self::$path = fw_fix_path(self::$path['basedir']) . '/fw/file-cache.php';
154
+ }
155
 
156
+ return self::$path;
157
  }
158
 
159
  /**
166
  }
167
 
168
  self::save();
169
+ self::$path = null;
170
  self::$cache = self::get_defaults();
171
  self::$changed = true;
172
 
182
 
183
  if (!(
184
  $shhh
185
+ ? @file_put_contents(self::get_path(), '<?php return ' . var_export(self::$cache, true) . ';', LOCK_EX)
186
+ : file_put_contents(self::get_path(), '<?php return ' . var_export(self::$cache, true) . ';', LOCK_EX)
187
  )) {
188
+ @file_put_contents(self::get_path(), '<?php return array();', LOCK_EX);
189
  }
190
 
191
  self::$changed = false;
195
  * @internal
196
  */
197
  public static function _init() {
 
 
198
  /**
199
  * Reset when current user is administrator
200
  * because it can be a developer that added/removed some files
208
  * - after some files was added/deleted
209
  */
210
  foreach (array(
 
211
  'fw_extensions_before_activation' => true,
212
  'fw_extensions_after_activation' => true,
213
  'fw_extensions_before_deactivation' => true,
221
  'upgrader_post_install' => true,
222
  'automatic_updates_complete' => true,
223
  'upgrader_process_complete' => true,
224
+ // 'switch_blog' => true, // fixes https://github.com/ThemeFuse/Unyson/issues/1986
225
  ) as $action => $x) {
226
  add_action( $action, array(__CLASS__, 'reset') );
227
  }
228
  }
229
 
230
  add_action( 'shutdown', array(__CLASS__, 'save') );
231
+ add_action( 'switch_blog', array(__CLASS__, '_reset_blog_id') );
232
  }
233
 
234
  /**
264
 
265
  return true;
266
  }
267
+
268
+ /**
269
+ * @internal
270
+ */
271
+ public function _reset_blog_id() {
272
+ self::$blog_id = null;
273
+ }
274
  }
275
 
276
  class FW_File_Cache_Not_Found_Exception extends Exception {}
framework/includes/container-types/tab/view.php CHANGED
@@ -5,7 +5,8 @@
5
  * @var array $options_data
6
  */
7
 
8
- $lazy_tabs = fw()->theme->get_config('lazy_tabs');
 
9
  ?>
10
  <div class="fw-options-tabs-wrapper">
11
  <div class="fw-options-tabs-list">
@@ -27,6 +28,8 @@ $lazy_tabs = fw()->theme->get_config('lazy_tabs');
27
  {
28
  $attr = isset($tab['attr']) ? $tab['attr'] : array();
29
 
 
 
30
  $attr['id'] = 'fw-options-tab-'. esc_attr($tab_id);
31
 
32
  if (!isset($attr['class'])) {
5
  * @var array $options_data
6
  */
7
 
8
+ $global_lazy_tabs = fw()->theme->get_config('lazy_tabs');
9
+
10
  ?>
11
  <div class="fw-options-tabs-wrapper">
12
  <div class="fw-options-tabs-list">
28
  {
29
  $attr = isset($tab['attr']) ? $tab['attr'] : array();
30
 
31
+ $lazy_tabs = isset($tab['lazy_tabs']) ? $tab['lazy_tabs'] : $global_lazy_tabs;
32
+
33
  $attr['id'] = 'fw-options-tab-'. esc_attr($tab_id);
34
 
35
  if (!isset($attr['class'])) {
framework/includes/hooks.php CHANGED
@@ -16,16 +16,46 @@
16
  add_action('fw_option_types_init', '_action_fw_init_option_types');
17
 
18
  /**
19
- * This option type has `add_action('wp_ajax_...`
 
 
20
  */
21
- if (is_admin()) {
22
- require_once dirname(__FILE__) . '/option-types/multi-select/class-fw-option-type-multi-select.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
- if (!class_exists('FW_Option_Type_Icon_v2')) {
25
- require_once dirname(__FILE__) .
26
- '/option-types/icon-v2/class-fw-option-type-icon-v2.php';
 
 
 
 
27
  }
28
  }
 
29
  }
30
 
31
  /**
16
  add_action('fw_option_types_init', '_action_fw_init_option_types');
17
 
18
  /**
19
+ * Some option-types have add_action('wp_ajax_...')
20
+ * so init all option-types if current request is ajax
21
+ * @since 2.6.1
22
  */
23
+ if (defined('DOING_AJAX') && DOING_AJAX) {
24
+ function _action_fw_init_option_types_on_ajax() {
25
+ fw()->backend->option_type('text');
26
+ }
27
+ add_action('fw_init', '_action_fw_init_option_types_on_ajax');
28
+ }
29
+
30
+ /**
31
+ * Prevent Fatal Error if someone is registering option-types in old way (right away)
32
+ * not in 'fw_option_types_init' action
33
+ * @param string $class
34
+ */
35
+ function _fw_autoload_option_types($class) {
36
+ if ('FW_Option_Type' === $class) {
37
+ require_once dirname(__FILE__) .'/../core/extends/class-fw-option-type.php';
38
+
39
+ if (is_admin()) {
40
+ FW_Flash_Messages::add(
41
+ 'option-type-register-wrong',
42
+ __("Please register option-types on 'fw_option_types_init' action", 'fw'),
43
+ 'warning'
44
+ );
45
+ }
46
+ } elseif ('FW_Container_Type' === $class) {
47
+ require_once dirname(__FILE__) .'/../core/extends/class-fw-container-type.php';
48
 
49
+ if (is_admin()) {
50
+ FW_Flash_Messages::add(
51
+ 'container-type-register-wrong',
52
+ __("Please register container-types on 'fw_container_types_init' action", 'fw'),
53
+ 'warning'
54
+ );
55
+ }
56
  }
57
  }
58
+ spl_autoload_register('_fw_autoload_option_types');
59
  }
60
 
61
  /**
framework/includes/option-types/addable-box/class-fw-option-type-addable-box.php CHANGED
@@ -16,20 +16,26 @@ class FW_Option_Type_Addable_Box extends FW_Option_Type
16
  */
17
  protected function _enqueue_static($id, $option, $data)
18
  {
19
- wp_enqueue_style(
20
- 'fw-option-'. $this->get_type(),
21
- fw_get_framework_directory_uri('/includes/option-types/'. $this->get_type() .'/static/css/styles.css'),
22
- array(),
23
- fw()->manifest->get_version()
24
- );
 
 
 
25
 
26
- wp_enqueue_script(
27
- 'fw-option-'. $this->get_type(),
28
- fw_get_framework_directory_uri('/includes/option-types/'. $this->get_type() .'/static/js/scripts.js'),
29
- array('fw-events', 'jquery-ui-sortable'),
30
- fw()->manifest->get_version(),
31
- true
32
- );
 
 
 
33
 
34
  fw()->backend->enqueue_options_static($option['box-options']);
35
 
16
  */
17
  protected function _enqueue_static($id, $option, $data)
18
  {
19
+ static $enqueue = true;
20
+
21
+ if ($enqueue) {
22
+ wp_enqueue_style(
23
+ 'fw-option-'. $this->get_type(),
24
+ fw_get_framework_directory_uri('/includes/option-types/'. $this->get_type() .'/static/css/styles.css'),
25
+ array(),
26
+ fw()->manifest->get_version()
27
+ );
28
 
29
+ wp_enqueue_script(
30
+ 'fw-option-'. $this->get_type(),
31
+ fw_get_framework_directory_uri('/includes/option-types/'. $this->get_type() .'/static/js/scripts.js'),
32
+ array('fw-events', 'jquery-ui-sortable'),
33
+ fw()->manifest->get_version(),
34
+ true
35
+ );
36
+
37
+ $enqueue = false;
38
+ }
39
 
40
  fw()->backend->enqueue_options_static($option['box-options']);
41
 
framework/includes/option-types/addable-option/class-fw-option-type-addable-option.php CHANGED
@@ -34,20 +34,26 @@ class FW_Option_Type_Addable_Option extends FW_Option_Type
34
  */
35
  protected function _enqueue_static($id, $option, $data)
36
  {
37
- wp_enqueue_style(
38
- 'fw-option-'. $this->get_type(),
39
- fw_get_framework_directory_uri('/includes/option-types/'. $this->get_type() .'/static/css/styles.css'),
40
- array(),
41
- fw()->manifest->get_version()
42
- );
43
 
44
- wp_enqueue_script(
45
- 'fw-option-'. $this->get_type(),
46
- fw_get_framework_directory_uri('/includes/option-types/'. $this->get_type() .'/static/js/scripts.js'),
47
- array('fw-events', 'jquery-ui-sortable'),
48
- fw()->manifest->get_version(),
49
- true
50
- );
 
 
 
 
 
 
 
 
 
 
 
51
 
52
  fw()->backend->option_type($option['option']['type'])->enqueue_static();
53
 
34
  */
35
  protected function _enqueue_static($id, $option, $data)
36
  {
37
+ static $enqueue = true;
 
 
 
 
 
38
 
39
+ if ($enqueue) {
40
+ wp_enqueue_style(
41
+ 'fw-option-'. $this->get_type(),
42
+ fw_get_framework_directory_uri('/includes/option-types/'. $this->get_type() .'/static/css/styles.css'),
43
+ array(),
44
+ fw()->manifest->get_version()
45
+ );
46
+
47
+ wp_enqueue_script(
48
+ 'fw-option-'. $this->get_type(),
49
+ fw_get_framework_directory_uri('/includes/option-types/'. $this->get_type() .'/static/js/scripts.js'),
50
+ array('fw-events', 'jquery-ui-sortable'),
51
+ fw()->manifest->get_version(),
52
+ true
53
+ );
54
+
55
+ $enqueue = false;
56
+ }
57
 
58
  fw()->backend->option_type($option['option']['type'])->enqueue_static();
59
 
framework/includes/option-types/addable-popup/class-fw-option-type-addable-popup.php CHANGED
@@ -13,20 +13,26 @@ class FW_Option_Type_Addable_Popup extends FW_Option_Type
13
  */
14
  protected function _enqueue_static($id, $option, $data)
15
  {
16
- wp_enqueue_style(
17
- 'fw-option-' . $this->get_type(),
18
- fw_get_framework_directory_uri('/includes/option-types/' . $this->get_type() . '/static/css/styles.css'),
19
- array('fw'),
20
- fw()->manifest->get_version()
21
- );
22
-
23
- wp_enqueue_script(
24
- 'fw-option-' . $this->get_type(),
25
- fw_get_framework_directory_uri('/includes/option-types/' . $this->get_type() . '/static/js/' . $this->get_type() . '.js'),
26
- array('underscore', 'fw-events', 'jquery-ui-sortable', 'fw'),
27
- fw()->manifest->get_version(),
28
- true
29
- );
 
 
 
 
 
 
30
 
31
  fw()->backend->enqueue_options_static($option['popup-options']);
32
 
13
  */
14
  protected function _enqueue_static($id, $option, $data)
15
  {
16
+ static $enqueue = true;
17
+
18
+ if ($enqueue) {
19
+ wp_enqueue_style(
20
+ 'fw-option-' . $this->get_type(),
21
+ fw_get_framework_directory_uri('/includes/option-types/' . $this->get_type() . '/static/css/styles.css'),
22
+ array('fw'),
23
+ fw()->manifest->get_version()
24
+ );
25
+
26
+ wp_enqueue_script(
27
+ 'fw-option-' . $this->get_type(),
28
+ fw_get_framework_directory_uri('/includes/option-types/' . $this->get_type() . '/static/js/' . $this->get_type() . '.js'),
29
+ array('underscore', 'fw-events', 'jquery-ui-sortable', 'fw'),
30
+ fw()->manifest->get_version(),
31
+ true
32
+ );
33
+
34
+ $enqueue = false;
35
+ }
36
 
37
  fw()->backend->enqueue_options_static($option['popup-options']);
38
 
framework/includes/option-types/color-picker/class-fw-option-type-color-picker.php CHANGED
@@ -48,7 +48,7 @@ class FW_Option_Type_Color_Picker extends FW_Option_Type
48
  */
49
  protected function _render($id, $option, $data)
50
  {
51
- $option['attr']['value'] = (string)$data['value'];
52
  $option['attr']['class'] .= ' code';
53
  $option['attr']['size'] = '7';
54
  $option['attr']['maxlength'] = '7';
48
  */
49
  protected function _render($id, $option, $data)
50
  {
51
+ $option['attr']['value'] = strtolower($data['value']);
52
  $option['attr']['class'] .= ' code';
53
  $option['attr']['size'] = '7';
54
  $option['attr']['maxlength'] = '7';
framework/includes/option-types/color-picker/static/js/scripts.js CHANGED
@@ -54,6 +54,8 @@ jQuery(document).ready(function($){
54
  * Do not initialize all pickers on the page, for performance reasons, maybe none of them will be opened
55
  */
56
  $input.one('focus', function(){
 
 
57
  $input.iris({
58
  hide: true,
59
  defaultColor: false,
@@ -64,6 +66,14 @@ jQuery(document).ready(function($){
64
  */
65
  clearTimeout(changeTimeoutId);
66
  changeTimeoutId = setTimeout(function(){
 
 
 
 
 
 
 
 
67
  $input.trigger('fw:color:picker:changed', { // should be 'fw:option-type:color-picker:change'
68
  $element: $input,
69
  event : event,
@@ -75,6 +85,8 @@ jQuery(document).ready(function($){
75
  palettes: JSON.parse($input.attr('data-palettes'))
76
  });
77
 
 
 
78
  var $picker = helpers.getInstance($input).picker;
79
 
80
  $picker.addClass(helpers.optionClass +'-iris');
@@ -181,24 +193,5 @@ jQuery(document).ready(function($){
181
 
182
  $input.addClass('initialized');
183
  });
184
-
185
- /*
186
- // fixme: where this code is needed? why it does full page selectors instead of only specific initialized option?
187
- $('.fw-inner').on('click', '.fw-option-type-color-picker', function () {
188
- var $this = $(this);
189
- $('.fw-option-type-color-picker.initialized').iris('hide');
190
-
191
- $this.iris('show');
192
-
193
- var widthParent = $this.closest('.fw-backend-option').outerWidth(),
194
- widthPiker = $this.next('.iris-picker').outerWidth(),
195
- offsetPiker = ($this.next('.iris-picker').offset().left - $this.closest('.fw-backend-option').offset().left) + widthPiker;
196
-
197
- if (offsetPiker > widthParent) {
198
- $this.next('.iris-picker').css('right', '0');
199
- }
200
- return false;
201
- });
202
- */
203
  });
204
  });
54
  * Do not initialize all pickers on the page, for performance reasons, maybe none of them will be opened
55
  */
56
  $input.one('focus', function(){
57
+ var initialValue = $input.val();
58
+
59
  $input.iris({
60
  hide: true,
61
  defaultColor: false,
66
  */
67
  clearTimeout(changeTimeoutId);
68
  changeTimeoutId = setTimeout(function(){
69
+ // prevent useless 'change' event when nothing has changed (happens right after init)
70
+ if (initialValue !== null && $input.val() === initialValue) {
71
+ initialValue = null;
72
+ return;
73
+ } else {
74
+ initialValue = null; // make sure the above `if` is executed only once
75
+ }
76
+
77
  $input.trigger('fw:color:picker:changed', { // should be 'fw:option-type:color-picker:change'
78
  $element: $input,
79
  event : event,
85
  palettes: JSON.parse($input.attr('data-palettes'))
86
  });
87
 
88
+ $input.addClass('iris-initialized');
89
+
90
  var $picker = helpers.getInstance($input).picker;
91
 
92
  $picker.addClass(helpers.optionClass +'-iris');
193
 
194
  $input.addClass('initialized');
195
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  });
197
  });
framework/includes/option-types/gradient/static/js/scripts.js CHANGED
@@ -1,17 +1,20 @@
1
- (function ($) {
2
  fwEvents.on('fw:options:init', function (data) {
3
  data.$elements.find('.fw-option.fw-option-type-gradient:not(.initialized)').each(function(){
4
- // onChange primary, set secondary with primary color
5
- $(this).on('fw:color:picker:changed', function (event, data) {
6
- if (data.$element.closest('.primary-color').length === 1) {
7
- data.$element.closest('.fw-option-type-gradient')
8
- .find('.secondary-color input.fw-option-type-color-picker.secondary.initialized')
9
- .val(data.ui.color.toString())
10
- .trigger('change');
 
 
 
11
  }
12
- });
13
 
14
- $(this).addClass('initialized');
15
- });
 
16
  });
17
  })(jQuery);
1
+ (function($){
2
  fwEvents.on('fw:options:init', function (data) {
3
  data.$elements.find('.fw-option.fw-option-type-gradient:not(.initialized)').each(function(){
4
+ var $option = $(this);
5
+
6
+ // update secondary color when primary color has changed
7
+ $option.on('fw:color:picker:changed', '.fw-option-type-color-picker.primary', function (event, data) {
8
+ var $secondary = $option.find('.fw-option-type-color-picker.secondary:first');
9
+
10
+ if (!$secondary.hasClass('iris-initialized')) {
11
+ $secondary
12
+ .trigger('focus') // color-picker is lazy initialized on 'focus'
13
+ .iris('hide');
14
  }
 
15
 
16
+ $secondary.val(data.ui.color.toString()).trigger('change');
17
+ });
18
+ }).addClass('initialized');
19
  });
20
  })(jQuery);
framework/includes/option-types/icon-v2/class-fw-option-type-icon-v2.php CHANGED
@@ -17,9 +17,6 @@ class FW_Option_Type_Icon_v2 extends FW_Option_Type
17
 
18
  public function _init()
19
  {
20
- $this->packs_loader = new FW_Icon_V2_Packs_Loader();
21
- $this->favorites = new FW_Icon_V2_Favorites_Manager();
22
-
23
  /**
24
  * CSS for each pack is not loaded by default in frontend.
25
  *
@@ -27,10 +24,21 @@ class FW_Option_Type_Icon_v2 extends FW_Option_Type
27
  *
28
  * fw()->backend->option_type('icon-v2')->packs_loader->enqueue_frontend_css()
29
  */
 
 
 
 
 
 
30
  }
31
 
32
  protected function _enqueue_static($id, $option, $data)
33
  {
 
 
 
 
 
34
  $this->packs_loader->enqueue_admin_css();
35
 
36
  $static_URI = fw_get_framework_directory_uri(
@@ -49,12 +57,11 @@ class FW_Option_Type_Icon_v2 extends FW_Option_Type
49
  );
50
 
51
  wp_enqueue_script(
52
- 'fw-option-type-'. $this->get_type() .'-backend-picker',
53
- $static_URI . 'js/icon-picker.js',
54
- array(
55
- 'fw-option-type-'. $this->get_type() .'-backend-previews'
56
- ),
57
- fw()->manifest->get_version()
58
  );
59
 
60
  wp_enqueue_style(
@@ -69,18 +76,16 @@ class FW_Option_Type_Icon_v2 extends FW_Option_Type
69
  'fw_icon_v2_data',
70
  array(
71
  'edit_icon_label' => __('Change Icon', 'fw'),
72
- 'add_icon_label' => __('Add Icon', 'fw'),
73
- 'icon_fonts_label' => __('Icons', 'fw'),
74
- 'custom_upload_label' => __('Upload', 'fw'),
75
- 'favorites_label' => __('Favorites', 'fw'),
76
- 'search_label' => __('Search Icon', 'fw'),
77
- 'select_pack_label' => __('Select Pack', 'fw'),
78
- 'all_packs_label' => __('All Packs', 'fw'),
79
- 'favorites_empty_label' => __(
80
- '<h4>You have no favorite icons yet.</h4> To add icons here, simply click on the star (<i class="fw-icon-v2-info dashicons dashicons-star-filled"></i>) button that\'s on top of each icon.',
81
- 'fw'
82
- ),
83
- 'icons' => $this->packs_loader->get_packs()
84
  )
85
  );
86
  }
@@ -92,7 +97,7 @@ class FW_Option_Type_Icon_v2 extends FW_Option_Type
92
  $option['attr']['value'] = $json;
93
 
94
  return fw_render_view(
95
- dirname(__FILE__) . '/view.php',
96
  compact('id', 'option', 'data', 'json')
97
  );
98
  }
17
 
18
  public function _init()
19
  {
 
 
 
20
  /**
21
  * CSS for each pack is not loaded by default in frontend.
22
  *
24
  *
25
  * fw()->backend->option_type('icon-v2')->packs_loader->enqueue_frontend_css()
26
  */
27
+ $this->packs_loader = new FW_Icon_V2_Packs_Loader();
28
+
29
+ if (! is_admin()) { return; }
30
+
31
+ $this->favorites = new FW_Icon_V2_Favorites_Manager();
32
+
33
  }
34
 
35
  protected function _enqueue_static($id, $option, $data)
36
  {
37
+ add_action(
38
+ 'admin_footer',
39
+ array($this, 'load_templates')
40
+ );
41
+
42
  $this->packs_loader->enqueue_admin_css();
43
 
44
  $static_URI = fw_get_framework_directory_uri(
57
  );
58
 
59
  wp_enqueue_script(
60
+ 'fw-option-type-'. $this->get_type() .'-backend-picker-v2',
61
+ $static_URI . 'js/icon-picker-v2.js',
62
+ array( 'fw' ),
63
+ fw()->manifest->get_version(),
64
+ true
 
65
  );
66
 
67
  wp_enqueue_style(
76
  'fw_icon_v2_data',
77
  array(
78
  'edit_icon_label' => __('Change Icon', 'fw'),
79
+ 'add_icon_label' => __('Add Icon', 'fw')
80
+ )
81
+ );
82
+ }
83
+
84
+ public function load_templates() {
85
+ echo fw_render_view(
86
+ dirname(__FILE__) . '/views/templates.php',
87
+ array(
88
+ 'packs_loader' => $this->packs_loader
 
 
89
  )
90
  );
91
  }
97
  $option['attr']['value'] = $json;
98
 
99
  return fw_render_view(
100
+ dirname(__FILE__) . '/views/view.php',
101
  compact('id', 'option', 'data', 'json')
102
  );
103
  }
framework/includes/option-types/icon-v2/includes/class-fw-icon-v2-favorites.php CHANGED
@@ -17,6 +17,18 @@ class FW_Icon_V2_Favorites_Manager
17
  'wp_ajax_fw_icon_v2_get_favorites',
18
  array($this, 'get_favorites_action')
19
  );
 
 
 
 
 
 
 
 
 
 
 
 
20
  }
21
 
22
  public function set_favorites_action()
17
  'wp_ajax_fw_icon_v2_get_favorites',
18
  array($this, 'get_favorites_action')
19
  );
20
+
21
+ add_action(
22
+ 'wp_ajax_fw_icon_v2_get_icons',
23
+ array($this, 'get_icon_packs')
24
+ );
25
+ }
26
+
27
+ public function get_icon_packs()
28
+ {
29
+ wp_send_json_success(
30
+ fw()->backend->option_type('icon-v2')->packs_loader->get_packs(true)
31
+ );
32
  }
33
 
34
  public function set_favorites_action()
framework/includes/option-types/icon-v2/includes/class-fw-icon-v2-packs-loader.php CHANGED
@@ -14,6 +14,8 @@ class FW_Icon_V2_Packs_Loader
14
  */
15
  public $filtered_icon_packs = null;
16
 
 
 
17
  public function __construct()
18
  {
19
  /**
@@ -44,6 +46,14 @@ class FW_Icon_V2_Packs_Loader
44
  * 'css_file' => 'path_to_your_css_file',
45
  * 'css_file_uri' => 'network_accessible_path_to_your_css_file',
46
  *
 
 
 
 
 
 
 
 
47
  * // By default, the option type will enqueue all CSS from all
48
  * // packs. You can handle CSS by yourself by making this option falsy.
49
  * //
@@ -101,6 +111,8 @@ class FW_Icon_V2_Packs_Loader
101
  'css_class_prefix' => $pack_name,
102
  'css_file' => false,
103
  'css_file_uri' => false,
 
 
104
  'require_css_file' => true,
105
  'icons' => false,
106
  'apply_root_class' => true
@@ -115,7 +127,7 @@ class FW_Icon_V2_Packs_Loader
115
 
116
  public function enqueue_frontend_css()
117
  {
118
- foreach ($this->icon_packs as $pack_name => $pack) {
119
  /**
120
  * The file will be required on the frontend side only if you want
121
  * it to. You can totally change this behavior by using
@@ -132,10 +144,16 @@ class FW_Icon_V2_Packs_Loader
132
  */
133
  if ($pack['require_css_file']) {
134
 
 
 
 
 
 
135
  wp_enqueue_style(
136
- 'fw-option-type-icon-v2-pack-' . $pack_name . '-css',
137
  $pack['css_file_uri'],
138
- array()
 
139
  );
140
 
141
  }
@@ -150,19 +168,31 @@ class FW_Icon_V2_Packs_Loader
150
  */
151
  public function enqueue_admin_css()
152
  {
153
- foreach ($this->icon_packs as $pack_name => $pack) {
 
 
 
 
 
154
  wp_enqueue_style(
155
- 'fw-option-type-icon-v2-pack-' . $pack_name . '-css',
156
  $pack['css_file_uri'],
157
  array(),
158
- '1.0'
159
  );
160
  }
161
  }
162
 
163
- public function get_packs()
164
  {
165
- $this->_load_icons_for_each_pack();
 
 
 
 
 
 
 
166
  $this->_load_filtered_icon_packs();
167
 
168
  return $this->_get_packs_for_names(
@@ -183,6 +213,8 @@ class FW_Icon_V2_Packs_Loader
183
 
184
  private function _load_icons_for_each_pack()
185
  {
 
 
186
  foreach ($this->icon_packs as $pack_name => $pack) {
187
  $this->icon_packs[$pack_name]['icons'] = array();
188
 
@@ -229,6 +261,8 @@ class FW_Icon_V2_Packs_Loader
229
  }
230
  }
231
  }
 
 
232
  }
233
 
234
  private function _load_filtered_icon_packs()
@@ -272,6 +306,8 @@ class FW_Icon_V2_Packs_Loader
272
  'css_file_uri' => fw_get_framework_directory_uri(
273
  '/static/libs/font-awesome/css/font-awesome.min.css'
274
  ),
 
 
275
  ),
276
 
277
  'entypo' => array(
@@ -335,7 +371,9 @@ class FW_Icon_V2_Packs_Loader
335
  'css_file' => fw_get_framework_directory( '/static/libs/unycon/unycon.css' ),
336
  'css_file_uri' => fw_get_framework_directory_uri(
337
  '/static/libs/unycon/unycon.css'
338
- )
 
 
339
  )
340
  );
341
  }
14
  */
15
  public $filtered_icon_packs = null;
16
 
17
+ private $icons_for_packs_parsed = null;
18
+
19
  public function __construct()
20
  {
21
  /**
46
  * 'css_file' => 'path_to_your_css_file',
47
  * 'css_file_uri' => 'network_accessible_path_to_your_css_file',
48
  *
49
+ * // Sometimes, you don't want to enqueue one more CSS file for
50
+ * // an already existing pack. Just give the correct handle here
51
+ * // and it'll work as expected.
52
+ * // Please note that the handle should be correctly registered
53
+ * // with wp_register_style() or wp_enqueue_style().
54
+ * 'admin_wp_enqueue_handle' => null,
55
+ * 'frontend_wp_enqueue_handle' => null,
56
+ *
57
  * // By default, the option type will enqueue all CSS from all
58
  * // packs. You can handle CSS by yourself by making this option falsy.
59
  * //
111
  'css_class_prefix' => $pack_name,
112
  'css_file' => false,
113
  'css_file_uri' => false,
114
+ 'admin_wp_enqueue_handle' => null,
115
+ 'frontend_wp_enqueue_handle' => null,
116
  'require_css_file' => true,
117
  'icons' => false,
118
  'apply_root_class' => true
127
 
128
  public function enqueue_frontend_css()
129
  {
130
+ foreach ($this->get_packs() as $pack_name => $pack) {
131
  /**
132
  * The file will be required on the frontend side only if you want
133
  * it to. You can totally change this behavior by using
144
  */
145
  if ($pack['require_css_file']) {
146
 
147
+ if ($pack['frontend_wp_enqueue_handle']) {
148
+ wp_enqueue_style($pack['frontend_wp_enqueue_handle']);
149
+ continue;
150
+ }
151
+
152
  wp_enqueue_style(
153
+ 'fw-option-type-icon-v2-pack-' . $pack_name,
154
  $pack['css_file_uri'],
155
+ array(),
156
+ fw()->manifest->get_version()
157
  );
158
 
159
  }
168
  */
169
  public function enqueue_admin_css()
170
  {
171
+ foreach ($this->get_packs() as $pack_name => $pack) {
172
+ if ($pack['admin_wp_enqueue_handle']) {
173
+ wp_enqueue_style($pack['admin_wp_enqueue_handle']);
174
+ continue;
175
+ }
176
+
177
  wp_enqueue_style(
178
+ 'fw-option-type-icon-v2-pack-' . $pack_name,
179
  $pack['css_file_uri'],
180
  array(),
181
+ fw()->manifest->get_version()
182
  );
183
  }
184
  }
185
 
186
+ public function get_packs($needs_to_load_icons_for_each_pack = false)
187
  {
188
+ /**
189
+ * Be aggressive about doing this operation. It costs lots of time.
190
+ * Totally don't want it to be in frontend.
191
+ */
192
+ if ($needs_to_load_icons_for_each_pack) {
193
+ $this->_load_icons_for_each_pack();
194
+ }
195
+
196
  $this->_load_filtered_icon_packs();
197
 
198
  return $this->_get_packs_for_names(
213
 
214
  private function _load_icons_for_each_pack()
215
  {
216
+ if ($this->icons_for_packs_parsed) { return; }
217
+
218
  foreach ($this->icon_packs as $pack_name => $pack) {
219
  $this->icon_packs[$pack_name]['icons'] = array();
220
 
261
  }
262
  }
263
  }
264
+
265
+ $this->icons_for_packs_parsed = true;
266
  }
267
 
268
  private function _load_filtered_icon_packs()
306
  'css_file_uri' => fw_get_framework_directory_uri(
307
  '/static/libs/font-awesome/css/font-awesome.min.css'
308
  ),
309
+
310
+ 'admin_wp_enqueue_handle' => 'fw-font-awesome'
311
  ),
312
 
313
  'entypo' => array(
371
  'css_file' => fw_get_framework_directory( '/static/libs/unycon/unycon.css' ),
372
  'css_file_uri' => fw_get_framework_directory_uri(
373
  '/static/libs/unycon/unycon.css'
374
+ ),
375
+
376
+ 'admin_wp_enqueue_handle' => 'fw-unycon'
377
  )
378
  );
379
  }
framework/includes/option-types/icon-v2/static/css/picker.css CHANGED
@@ -201,7 +201,7 @@
201
  }
202
 
203
  .fw-icon-v2-picker-modal h2:only-of-type {
204
- display: none;
205
  }
206
 
207
  .fw-icon-v2-picker-modal h2 span {
@@ -361,4 +361,4 @@
361
  .fw-icon-v2-picker-modal .fw-icon-v2-toolbar > input:-ms-input-placeholder {
362
  font-style: normal;
363
  color: #333333;
364
- }
201
  }
202
 
203
  .fw-icon-v2-picker-modal h2:only-of-type {
204
+ /* display: none; */
205
  }
206
 
207
  .fw-icon-v2-picker-modal h2 span {
361
  .fw-icon-v2-picker-modal .fw-icon-v2-toolbar > input:-ms-input-placeholder {
362
  font-style: normal;
363
  color: #333333;
364
+ }
framework/includes/option-types/icon-v2/static/js/icon-picker-v2.js ADDED
@@ -0,0 +1,496 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function ($) {
2
+ window.fwOptionTypeIconV2Picker = fw.Modal.extend({
3
+ defaults: _.extend({}, fw.Modal.prototype.defaults, {
4
+ title: 'Icon V2',
5
+ size: 'small',
6
+ modalCustomClass: 'fw-icon-v2-picker-modal',
7
+ emptyHtmlOnClose: false
8
+ }),
9
+
10
+ ContentView: fw.Modal.prototype.ContentView.extend({
11
+ events: {
12
+ 'input .fw-icon-v2-icons-library .fw-icon-v2-toolbar input': 'onSearch',
13
+ 'click .fw-icon-v2-library-icon': 'markIconAsSelected',
14
+ 'click .fw-icon-v2-library-icon a': 'markIconAsFavorite',
15
+ 'submit': 'onSubmit'
16
+ },
17
+
18
+ initialize: function () {
19
+ fw.Modal.prototype.ContentView.prototype.initialize.call(this);
20
+
21
+ // keep track of current searches for better performance
22
+ this.previousSearch = '';
23
+
24
+ this.throttledApplyFilters = _.throttle(
25
+ _.bind(this.model.applyFilters, this.model),
26
+ 200
27
+ );
28
+ },
29
+
30
+ computeModalHeight: function() {
31
+ var $icons = this.model.frame.$el.find('.fw-icon-v2-library-packs-wrapper');
32
+ var toolbarHeight = this.model.frame.$el.find('.fw-icon-v2-toolbar').height();
33
+ var $tabsList = this.model.frame.$el.find('.fw-options-tabs-list');
34
+
35
+ $icons.height(
36
+ this.model.frame.$el.find(
37
+ '> .media-frame-content'
38
+ ).height() - $tabsList.height() - toolbarHeight - 75
39
+ );
40
+ },
41
+
42
+ onSubmit: function(e) {
43
+ this.model.resolveResult();
44
+ var content = this;
45
+
46
+ e.preventDefault();
47
+
48
+ setTimeout(function () {
49
+ content.model.frame.modal.$el.find('.media-modal-close').trigger('click');
50
+ }, 0);
51
+ },
52
+
53
+ markIconAsSelected: function markIconAsSelected (e) {
54
+ e.preventDefault();
55
+ var $el = $(e.currentTarget);
56
+
57
+ this.model.result['icon-class'] = $el.attr('data-fw-icon-v2').trim();
58
+
59
+ this.refreshSelectedIcon();
60
+ },
61
+
62
+ refreshSelectedIcon: function refreshSelectedIcon() {
63
+ var currentValue = this.model.result['icon-class'];
64
+
65
+ this.model.frame.$el
66
+ .find('.fw-icon-v2-library-icon.selected')
67
+ .removeClass('selected');
68
+
69
+ if (currentValue) {
70
+ this.model.frame.$el.find('[data-fw-icon-v2$="' + currentValue + '"]')
71
+ .addClass('selected');
72
+ }
73
+ },
74
+
75
+ refreshAttachment: function() {
76
+ var currentId = this.model.result['attachment-id'];
77
+
78
+ this.model.frame.$el
79
+ .find('.fw-option-type-upload > input[type="hidden"]')
80
+ .val(currentId).trigger('change');
81
+ },
82
+
83
+ markIconAsFavorite: function markIconAsFavorite (e) {
84
+ e.preventDefault();
85
+ e.stopPropagation();
86
+
87
+ var icon = $(e.currentTarget).closest('.fw-icon-v2-library-icon').attr(
88
+ 'data-fw-icon-v2'
89
+ );
90
+
91
+ this.model.markAsFavorite(icon);
92
+
93
+ this.renderFavorites();
94
+ this.refreshFavorites();
95
+ },
96
+
97
+ refreshFavorites: function() {
98
+ $('.fw-icon-v2-favorite').removeClass('fw-icon-v2-favorite');
99
+
100
+ _.map(
101
+ this.model.currentFavorites,
102
+ setFavoriteClass
103
+ );
104
+
105
+ function setFavoriteClass (favorite) {
106
+ $('[data-fw-icon-v2="' + favorite + '"]').addClass('fw-icon-v2-favorite');
107
+ }
108
+ },
109
+
110
+ renderFavorites: function() {
111
+ var $favorites = this.model.frame.$el.find('.fw-icon-v2-icon-favorites');
112
+
113
+ $favorites.empty();
114
+
115
+ $favorites.replaceWith(
116
+ this.model.getFavoritesHtml()
117
+ );
118
+ },
119
+
120
+ onSearch: function (event) {
121
+ var $el = $(event.currentTarget);
122
+
123
+ if (
124
+ this.previousSearch.trim().length === 0
125
+ &&
126
+ $el.val().trim().length === 0
127
+ ) {
128
+ return;
129
+ }
130
+
131
+ if ($el.val().trim().length === 0) {
132
+ this.throttledApplyFilters();
133
+ }
134
+
135
+ if ($el.val().trim().length > 2) {
136
+ this.throttledApplyFilters();
137
+ }
138
+
139
+ this.previousSearch = $el.val();
140
+ }
141
+ }),
142
+
143
+ initialize: function(attributes, settings) {
144
+ fw.Modal.prototype.initialize.call(this, attributes, settings);
145
+ this.set('picker_id', fw.randomMD5());
146
+
147
+ this.currentFavorites = null;
148
+
149
+ this.result = {};
150
+
151
+ jQuery.when(
152
+ this.loadIconsData(),
153
+ this.loadLatestFavorites()
154
+ ).then(
155
+ _.bind(this.setHtml, this)
156
+ );
157
+
158
+ this.attachEvents();
159
+
160
+ this.frame.on('close', _.bind(this.rejectResultAndResetIt, this));
161
+
162
+ this.frame.once('ready', _.bind(function () {
163
+ var modal = this;
164
+ this.frame.$el.find('.fw-options-tabs-wrapper').on('tabsactivate', function (event, ui) {
165
+ /**
166
+ * Every tab change should cause a change on a modal.
167
+ *
168
+ * It may be the case that the user will switch to
169
+ * `Custom Upload` and the value of the option type won't change
170
+ * because of the fact that `change:values` callback will not
171
+ * be executed.
172
+ */
173
+ modal.result.type = ui.newTab.index() === 2 ? 'custom-upload' : 'icon-font';
174
+ });
175
+
176
+ }, this));
177
+
178
+ },
179
+
180
+ resolveResult: function () {
181
+ if (this.promise) {
182
+ this.promise.resolve(this.result);
183
+ }
184
+
185
+ this.promise = null;
186
+ },
187
+
188
+ rejectResultAndResetIt: function() {
189
+ if (this.promise) {
190
+ this.promise.reject(this.result);
191
+ }
192
+
193
+ this.promise = null;
194
+ },
195
+
196
+ initializeFrame: function (settings) {
197
+ fw.OptionsModal.prototype.initializeFrame.call(this, settings);
198
+ },
199
+
200
+ setAttachment: function (data) {
201
+ if (data.$element.attr('data-fw-icon-v2-id') !== this.get('picker_id')) {
202
+ return;
203
+ }
204
+
205
+ this.result.attachment = data.attachment;
206
+
207
+ if (data.attachment) {
208
+ this.result['attachment-id'] = data.attachment.get('id');
209
+ this.result['url'] = data.attachment.get('url');
210
+ } else {
211
+ this.result['attachment-id'] = "";
212
+ this.result['url'] = "";
213
+ }
214
+ },
215
+
216
+ attachEvents: function() {
217
+ fwEvents.on('fw:option-type:upload:change', this.setAttachment, this);
218
+ fwEvents.on('fw:option-type:upload:clear', this.setAttachment, this);
219
+ },
220
+
221
+ setHtml: function() {
222
+ this.set('html', this.getTabsHtml());
223
+ },
224
+
225
+ open: function(values) {
226
+ this.promise = jQuery.Deferred();
227
+
228
+ this.get('controls_ready') && this.set(
229
+ 'controls_ready',
230
+ !! this.frame.state()
231
+ );
232
+
233
+ values = values || {
234
+ type: 'icon-font',
235
+ 'icon-class': ''
236
+ }
237
+
238
+ this.set('current_state', values);
239
+ this.setResultBasedOnCurrentState();
240
+
241
+ if (this.frame.state()) {
242
+ this.prepareForPick();
243
+ }
244
+
245
+ this.frame.open();
246
+
247
+ /**
248
+ * On first open, modal is prepared here.
249
+ */
250
+ if (! this.get('controls_ready')) {
251
+ setTimeout(_.bind(this.prepareForPick, this), 0);
252
+ this.setupControls();
253
+ }
254
+
255
+ return this.promise;
256
+ },
257
+
258
+ close: function () {
259
+ fw.Modal.prototype.close.call(this);
260
+ },
261
+
262
+ setResultBasedOnCurrentState: function() {
263
+ this.result = this.get('current_state');
264
+ },
265
+
266
+ prepareForPick: function() {
267
+ // use this.get('current_state') in order to populate current
268
+ // active icon or current attachment
269
+ //
270
+ // this.frame.$el.find('.ui-tabs').tabs({active: 2});
271
+
272
+ var $tabs = this.frame.$el.find('.ui-tabs');
273
+
274
+ var currentTab = $tabs.tabs('option', 'active');
275
+
276
+ if (this.get('current_state').type === 'custom-upload') {
277
+ if (currentTab !== 2) {
278
+ $tabs.tabs({active: 2});
279
+ }
280
+
281
+ this.content.refreshAttachment();
282
+ }
283
+
284
+ if (this.get('current_state').type !== 'custom-upload') {
285
+ if (currentTab === 2) {
286
+ $tabs.tabs({active: 0});
287
+ }
288
+
289
+ this.content.refreshSelectedIcon();
290
+
291
+ if (this.result['icon-class']) {
292
+ var el = this.frame.$el.find(
293
+ '[data-fw-icon-v2$="' + this.result['icon-class'] + '"]'
294
+ )[0];
295
+
296
+ if (el.scrollIntoViewIfNeeded) {
297
+ el.scrollIntoViewIfNeeded(true);
298
+ } else if (el.scrollIntoView) {
299
+ el.scrollIntoView();
300
+ }
301
+ }
302
+ }
303
+ },
304
+
305
+ setupControls: function() {
306
+ this.frame.$el.find('.fw-icon-v2-toolbar select').selectize({
307
+ onChange: _.bind(this.applyFilters, this)
308
+ });
309
+
310
+ this.content.refreshFavorites();
311
+ this.content.computeModalHeight();
312
+
313
+ this.frame.$el.find('.fw-option-type-upload').attr(
314
+ 'data-fw-icon-v2-id', this.get('picker_id')
315
+ );
316
+ },
317
+
318
+ applyFilters: function() {
319
+ var pack = this.frame.$el.find(
320
+ '.fw-icon-v2-icons-library .fw-icon-v2-toolbar select'
321
+ )[0].value;
322
+
323
+ var search = this.frame.$el.find(
324
+ '.fw-icon-v2-icons-library .fw-icon-v2-toolbar input'
325
+ ).val().trim();
326
+
327
+ var packs = this.getFilteredPacks({
328
+ pack: pack,
329
+ search: search
330
+ });
331
+
332
+ this.frame.$el.find(
333
+ '.fw-icon-v2-library-packs-wrapper'
334
+ ).html(
335
+ wp.template('fw-icon-v2-packs')({
336
+ packs: packs,
337
+ current_state: this.result,
338
+ favorites: this.currentFavorites
339
+ })
340
+ );
341
+ },
342
+
343
+ getFilteredPacks: function(filters) {
344
+ var self = this;
345
+
346
+ filters = _.extend({}, {
347
+ search: '',
348
+ pack: 'all'
349
+ }, filters);
350
+
351
+ var packs = [];
352
+
353
+ if (filters.pack.trim() === '' || filters.pack === 'all') {
354
+ packs = _.values(this.getIconsData());
355
+ } else {
356
+ packs = [ this.getIconsData()[filters.pack] ];
357
+ }
358
+
359
+ packs = _.map(packs, function (pack) {
360
+ var newPack = _.extend({}, pack);
361
+
362
+ newPack.icons = _.filter(pack.icons, function (icon) {
363
+ return self.fuzzyConsecutive(filters.search, icon);
364
+ });
365
+
366
+ return newPack;
367
+ });
368
+
369
+ return _.reject(packs, _.isEmpty);
370
+ },
371
+
372
+ loadIconsData: function () {
373
+ if (this.iconsDataPromise) { return this.iconsDataPromise; }
374
+
375
+ this.iconsDataPromise = jQuery.post(ajaxurl, {action: 'fw_icon_v2_get_icons'});
376
+ this.iconsDataPromise.then(_.bind(this.preloadFonts, this));
377
+ return this.iconsDataPromise;
378
+ },
379
+
380
+ getIconsData: function () {
381
+ this.loadIconsData();
382
+
383
+ if (this.iconsDataPromise.state() === 'resolved') {
384
+ if (this.iconsDataPromise.responseJSON.success) {
385
+ return this.iconsDataPromise.responseJSON.data;
386
+ }
387
+ }
388
+
389
+ return null;
390
+ },
391
+
392
+ loadLatestFavorites: function () {
393
+ if (this.favoritesPromise) { return this.favoritesPromise; }
394
+
395
+ this.favoritesPromise = jQuery.post(ajaxurl, {
396
+ action: 'fw_icon_v2_get_favorites'
397
+ });
398
+
399
+ this.favoritesPromise.then(_.bind(this.getFavoritesData, this));
400
+
401
+ return this.favoritesPromise;
402
+ },
403
+
404
+ getFavoritesData: function () {
405
+ this.loadLatestFavorites();
406
+
407
+ if (this.favoritesPromise.state() === 'resolved') {
408
+ this.currentFavorites = _.uniq(this.favoritesPromise.responseJSON);
409
+ }
410
+
411
+ return null;
412
+ },
413
+
414
+ setFavorites: function () {
415
+ var data = {
416
+ action: 'fw_icon_v2_update_favorites',
417
+ favorites: JSON.stringify(_.uniq(this.currentFavorites))
418
+ };
419
+
420
+ jQuery.post(
421
+ ajaxurl,
422
+ data,
423
+ function(data) { }
424
+ );
425
+ },
426
+
427
+ markAsFavorite: function(icon) {
428
+ icon = icon.trim();
429
+
430
+ var isFavorite = _.contains(this.currentFavorites, icon);
431
+
432
+ if (isFavorite) {
433
+ this.currentFavorites = _.uniq(_.reject(this.currentFavorites, function (favorite) {
434
+ return favorite == icon;
435
+ }));
436
+ } else {
437
+ this.currentFavorites.push(icon);
438
+ }
439
+
440
+ this.setFavorites();
441
+ },
442
+
443
+ preloadFonts: function () {
444
+ _.map(this.getIconsData(), preloadFont);
445
+
446
+ function preloadFont (pack) {
447
+ var $el = jQuery(
448
+ '<i class="' + pack.css_class_prefix + " " + pack.icons[0] +
449
+ '" style="opacity: 0;">'
450
+ );
451
+
452
+ jQuery('body').append(
453
+ $el
454
+ );
455
+
456
+ setTimeout(function () { $el.remove(); }, 200);
457
+ }
458
+ },
459
+
460
+ getTabsHtml: function () {
461
+ return wp.template('fw-icon-v2-tabs')({
462
+ icons_library_html: this.getLibraryHtml(),
463
+ favorites_list_html: this.getFavoritesHtml(),
464
+ current_state: this.result,
465
+ favorites: this.currentFavorites
466
+ });
467
+ },
468
+
469
+ getLibraryHtml: function() {
470
+
471
+ return wp.template('fw-icon-v2-library')({
472
+ packs: _.values(this.getIconsData()),
473
+ current_state: this.result,
474
+ favorites: this.currentFavorites
475
+ })
476
+
477
+ },
478
+
479
+ getFavoritesHtml: function() {
480
+
481
+ return wp.template('fw-icon-v2-favorites')({
482
+ favorites: this.currentFavorites,
483
+ current_state: this.result
484
+ })
485
+
486
+ },
487
+
488
+ fuzzyConsecutive: function fuzzyConsecutive (query, search) {
489
+ if (query.trim() === '') return true;
490
+ return search.toLowerCase().trim().indexOf(query.toLowerCase()) > -1;
491
+ }
492
+ });
493
+
494
+ fwOptionTypeIconV2Instance = new fwOptionTypeIconV2Picker();
495
+
496
+ })(jQuery);
framework/includes/option-types/icon-v2/static/js/icon-picker.js DELETED
@@ -1,466 +0,0 @@
1
- window.fwOptionTypeIconV2Picker = (function ($) {
2
- var modal = null,
3
- currentValues = null,
4
- callback = null,
5
- uniqueId = null;
6
-
7
- var currentFavorites = [];
8
- $(window).on('resize', computeModalHeight);
9
-
10
- $(document).on('click', '.fw-icon-v2-library-icon', markIconAsSelected);
11
- $(document).on('click', '.fw-icon-v2-library-icon a', markIconAsFavorite);
12
-
13
- $(document).on(
14
- 'input',
15
- '.fw-icon-v2-icons-library .fw-icon-v2-toolbar input',
16
- handleInput
17
- );
18
-
19
- var throttledApplyFilters = _.throttle(applyFilters, 200);
20
-
21
- var previousSearch = '';
22
-
23
- function handleInput () {
24
- console.log(previousSearch);
25
-
26
- if (
27
- previousSearch.trim().length === 0
28
- &&
29
- $(this).val().trim().length === 0
30
- ) return;
31
-
32
- if ( $(this).val().trim().length === 0 ) {
33
- throttledApplyFilters();
34
- }
35
-
36
- if ($(this).val().trim().length > 2)
37
- throttledApplyFilters();
38
-
39
- previousSearch = $(this).val();
40
- }
41
-
42
- return {
43
- pick: pick
44
- };
45
-
46
- function pick (values, id, fn, modalSize) {
47
- currentValues = values;
48
- callback = fn;
49
- uniqueId = id;
50
-
51
- createModal(modalSize);
52
-
53
- modal.open();
54
- }
55
-
56
- function createModal (modalSize) {
57
- if (modal) {
58
- modal.set('size', modalSize);
59
- return;
60
- }
61
-
62
- modal = new fw.OptionsModal({
63
- modalCustomClass: 'fw-icon-v2-picker-modal',
64
- disableLazyTabs: true,
65
- title: '',
66
- size: modalSize,
67
- options: [
68
- {
69
- 'icon-fonts': {
70
- type: 'tab',
71
- title: fw_icon_v2_data.icon_fonts_label,
72
- options: {
73
- 'icon-font': {
74
- type: 'html-full',
75
- attr: {
76
- class: 'fw-icon-v2-icons-library'
77
- },
78
- label: false,
79
- html: iconLibraryHTML()
80
- }
81
- }
82
- }
83
- },
84
-
85
- {
86
- 'favorites': {
87
- type: 'tab',
88
- title: fw_icon_v2_data.favorites_label,
89
- attr: {
90
- class: '.fw-icon-v2-favorites'
91
- },
92
- options: {
93
- 'icon-font-favorites': {
94
- type: 'html-full',
95
- label: false,
96
- html: '<div class="fw-icon-v2-icon-favorites"></div>'
97
- }
98
- }
99
- }
100
- },
101
-
102
- {
103
- 'custom-upload': {
104
- type: 'tab',
105
- title: fw_icon_v2_data.custom_upload_label,
106
- options: {
107
- 'custom-upload': {
108
- label: 'Upload Icon',
109
- type: 'upload'
110
- }
111
- }
112
- }
113
- }
114
- ]
115
- });
116
-
117
- modal.on('change:values', function(modal, values) {
118
- // run callback here
119
- // get values based on current tab
120
-
121
- var type = modal.frame.$el.find('.fw-options-tabs-wrapper')
122
- .tabs('instance').active.index() === 2 ? 'custom-upload' : 'icon-font';
123
-
124
- if (type == "icon-font") {
125
- callback({
126
- type: 'icon-font',
127
- 'icon-class': values['icon-font']
128
- });
129
- }
130
-
131
- if (type === 'custom-upload') {
132
- if (values['custom-upload'] === '') {
133
- values['custom-upload'] = {
134
- attachment_id: '',
135
- url: ''
136
- };
137
- }
138
-
139
- callback({
140
- type: 'custom-upload',
141
- 'attachment-id': values['custom-upload']['attachment_id'],
142
- 'url': values['custom-upload']['url']
143
- });
144
- }
145
- });
146
-
147
- modal.on('render', function () {
148
- /**
149
- * Every icon picker change should trigger a new callback chain
150
- * execution.
151
- */
152
- modal.set(
153
- 'values',
154
- _.extend({}, modal.get('values'), {
155
- current_picker: uniqueId
156
- }),
157
- {silent: true}
158
- );
159
-
160
- // select correct tab here, based on currentValues
161
- // also render icon sets here, if needed
162
- var $select = modal.frame.$el.find('.fw-icon-v2-toolbar select');
163
-
164
- if (! $select[0].selectize) {
165
- $select.selectize({
166
- onChange: applyFilters
167
- });
168
- }
169
-
170
- if (modal.frame.$el.find('.fw-icon-v2-icons-library ul').length === 0) {
171
- renderIconsLibrary({
172
- search: '',
173
- packs: _.values(fw_icon_v2_data.icons)
174
- });
175
-
176
- setTimeout(computeModalHeight, 100);
177
- }
178
-
179
- getLatestFavorites(refreshFavoritesClasses);
180
-
181
- /**
182
- * Set initial values for modal. They're based on the
183
- * current values from current picker.
184
- */
185
- if (currentValues.type === 'icon-font') {
186
- modal.frame.$el.find(
187
- '.fw-icon-v2-icons-library > input[type="hidden"]'
188
- ).val(
189
- currentValues['icon-class']
190
- );
191
- }
192
-
193
- refreshSelectedIcon();
194
-
195
- if (currentValues.type === 'custom-upload') {
196
- var currentCustomUpload = '';
197
-
198
- if (currentValues.url.trim() !== '') {
199
- currentCustomUpload = {
200
- url: currentValues['url'],
201
- attachment_id: currentValues['attachment-id']
202
- };
203
- }
204
-
205
- modal.set(
206
- 'values',
207
- _.extend({}, modal.get('values'), {
208
- 'custom-upload': currentCustomUpload
209
- })
210
- );
211
-
212
- modal.updateHtml();
213
- }
214
-
215
- modal.frame.$el.find('.fw-options-tabs-wrapper').on('tabsactivate', function (event, ui) {
216
- /**
217
- * Every tab change should cause a change on a modal.
218
- *
219
- * It may be the case that the user will switch to
220
- * `Custom Upload` and the value of the option type won't change
221
- * because of the fact that `change:values` callback will not
222
- * be executed.
223
- */
224
- modal.set(
225
- 'values',
226
- _.extend({}, modal.get('values'), {
227
- current_tab: ui.newTab.index()
228
- }),
229
- {silent: true}
230
- );
231
- });
232
-
233
- modal.frame.$el.find('.fw-options-tabs-wrapper').tabs({
234
- active: currentValues.type == 'custom-upload' ? 2 : 0
235
- });
236
- });
237
-
238
- modal.on('open', function () {
239
- });
240
-
241
- modal.on('close', function () {
242
- });
243
- }
244
-
245
- function iconLibraryHTML () {
246
- var searchInput = '<input type="text" placeholder="' +
247
- fw_icon_v2_data.search_label +
248
- '" class="fw-option fw-option-type-text">';
249
- var selectPack = [
250
- '<select class="fw-selectize">',
251
- '<option value="all">' + fw_icon_v2_data.all_packs_label + '</option>'
252
- ].concat(
253
-
254
- _.map(
255
- _.values(fw_icon_v2_data.icons),
256
- function (e) {return '<option value="' + e.name + '">' + e.title + '</option>';}
257
- )
258
-
259
- ).concat(
260
- '</select>'
261
- ).join('');
262
-
263
- var toolbarContainer = [
264
- '<div class="fw-icon-v2-toolbar">',
265
- searchInput,
266
- selectPack,
267
- '</div>'
268
- ].join('');
269
-
270
- var packsContainer = '<div class="fw-icon-v2-library-packs-wrapper"></div>';
271
-
272
- return toolbarContainer + packsContainer;
273
- }
274
-
275
- /**
276
- * options.search - search string
277
- * options.packs - packs to render
278
- */
279
- function renderIconsLibrary (options) {
280
- options = _.extend({}, {
281
- search: '',
282
- packs: []
283
- }, options);
284
-
285
- $('.fw-icon-v2-library-packs-wrapper').html(
286
-
287
- _.map(
288
- options.packs,
289
- renderPack
290
- ).join('')
291
-
292
- );
293
-
294
- refreshSelectedIcon();
295
-
296
- function renderPack (pack) {
297
- filteredIcons = _.filter(pack.icons, function (icon) {
298
- return fuzzyConsecutive(options.search, icon);
299
- });
300
-
301
- if (filteredIcons.length === 0) return '';
302
-
303
- var packHeader = '<h2><span>' + pack.title + '</span></h2>';
304
-
305
- return packHeader + renderIconsCollection(pack, filteredIcons);
306
- }
307
- }
308
-
309
- function renderIconsCollection (pack, icons, favorites) {
310
-
311
- return '<ul class="fw-icon-v2-library-pack">' + _.map(
312
- icons,
313
- renderSingleIcon
314
- ).join('') + '</ul>';
315
-
316
- function renderSingleIcon (icon) {
317
- var iconClass = favorites ? icon : pack.css_class_prefix + ' ' + icon;
318
-
319
- var liClass = 'fw-icon-v2-library-icon';
320
-
321
- if (currentValues.type === 'icon-font' && currentValues['icon-class'] === iconClass) {
322
- liClass += ' selected';
323
- }
324
-
325
- return [
326
- '<li data-fw-icon-v2="' + iconClass + '" class="' + liClass + '">',
327
- '<i class="' + iconClass + '"></i>',
328
- '<a title="Add to Favorites" class="fw-icon-v2-favorite"><i class="dashicons dashicons-star-filled"></i></a>',
329
- '</li>'
330
- ].join('');
331
- }
332
- }
333
-
334
- function markIconAsSelected (event) {
335
- event.preventDefault();
336
-
337
- modal.frame.$el.find('.fw-icon-v2-icons-library').find('> input[type="hidden"]').val(
338
- $(this).attr('data-fw-icon-v2')
339
- );
340
-
341
- refreshSelectedIcon();
342
- }
343
-
344
- function markIconAsFavorite (event) {
345
- event.preventDefault();
346
- event.stopPropagation();
347
-
348
- var icon = $(this).closest('.fw-icon-v2-library-icon').attr(
349
- 'data-fw-icon-v2'
350
- );
351
-
352
- var isFavorite = _.contains(currentFavorites, icon);
353
-
354
- if (isFavorite) {
355
- currentFavorites = _.reject(currentFavorites, function (favorite) {
356
- return favorite == icon;
357
- });
358
- } else {
359
- currentFavorites.push(icon);
360
- }
361
-
362
- var data = {
363
- action: 'fw_icon_v2_update_favorites',
364
- favorites: JSON.stringify(currentFavorites)
365
- };
366
-
367
- refreshFavoritesClasses(currentFavorites);
368
-
369
- jQuery.post(
370
- ajaxurl,
371
- data,
372
- function(data) {
373
- }
374
- );
375
- }
376
-
377
- function refreshSelectedIcon () {
378
- var currentValue = modal.frame.$el.find(
379
- '.fw-icon-v2-icons-library > input[type="hidden"]'
380
- ).val();
381
-
382
- modal.frame.$el
383
- .find('.fw-icon-v2-library-icon.selected')
384
- .removeClass('selected');
385
-
386
- modal.frame.$el.find('[data-fw-icon-v2="' + currentValue + '"]')
387
- .addClass('selected');
388
- }
389
-
390
- function applyFilters () {
391
- var search = modal.frame.$el.find(
392
- '.fw-icon-v2-icons-library .fw-icon-v2-toolbar input'
393
- ).val().trim();
394
-
395
- var packs = modal.frame.$el.find(
396
- '.fw-icon-v2-icons-library .fw-icon-v2-toolbar select'
397
- )[0].value;
398
-
399
- if (packs.trim() === '' || packs === 'all') {
400
- packs = _.values(fw_icon_v2_data.icons);
401
- } else {
402
- packs = [ fw_icon_v2_data.icons[packs] ];
403
- }
404
-
405
- renderIconsLibrary({
406
- search: search,
407
- packs: packs
408
- });
409
-
410
- refreshFavoritesClasses(currentFavorites);
411
- }
412
-
413
- function fuzzyConsecutive (query, search) {
414
- if (query.trim() === '') return true;
415
- return search.toLowerCase().trim().indexOf(query.toLowerCase()) > -1;
416
- };
417
-
418
- function getLatestFavorites (callback) {
419
- var data = {
420
- action: 'fw_icon_v2_get_favorites'
421
- };
422
-
423
- jQuery.post(ajaxurl, data, function(data) {
424
- currentFavorites = data;
425
- callback(data);
426
- });
427
- }
428
-
429
- function refreshFavoritesClasses (favorites) {
430
- $('.fw-icon-v2-favorite').removeClass('fw-icon-v2-favorite');
431
-
432
- _.map(
433
- favorites,
434
- setFavoriteClass
435
- );
436
-
437
- renderFavorites();
438
-
439
- function setFavoriteClass (favorite) {
440
- $('[data-fw-icon-v2="' + favorite + '"]').addClass('fw-icon-v2-favorite');
441
- }
442
- }
443
-
444
- function renderFavorites () {
445
- var $favorites = modal.frame.$el.find('.fw-icon-v2-icon-favorites');
446
-
447
- $favorites.html(
448
- _.isEmpty(currentFavorites)
449
- ? fw_icon_v2_data.favorites_empty_label
450
- : renderIconsCollection(null, currentFavorites, true)
451
- );
452
- }
453
-
454
- function computeModalHeight () {
455
- if (! modal) { return; }
456
- var $icons = modal.frame.$el.find('.fw-icon-v2-library-packs-wrapper');
457
- var toolbarHeight = modal.frame.$el.find('.fw-icon-v2-toolbar').height();
458
-
459
- $icons.height(
460
- modal.frame.$el.find(
461
- '.fw-options-tabs-contents.metabox-holder'
462
- ).height() - toolbarHeight - 50
463
- );
464
- }
465
- })(jQuery);
466
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
framework/includes/option-types/icon-v2/static/js/render-icon-previews.js CHANGED
@@ -42,6 +42,17 @@
42
  $root.data('unique-id', fw.randomMD5());
43
  }
44
 
 
 
 
 
 
 
 
 
 
 
 
45
  fwOptionTypeIconV2Picker.pick(
46
  getDataForRoot($root),
47
  $root.data('unique-id'),
@@ -53,6 +64,7 @@
53
  },
54
  modalSize
55
  );
 
56
  }
57
 
58
  function removeIcon (event) {
@@ -189,10 +201,14 @@
189
 
190
  $root.find('input').val(
191
  JSON.stringify(
192
- _.extend(
193
- {},
194
- currentData,
195
- data
 
 
 
 
196
  )
197
  )
198
  ).trigger('change');
42
  $root.data('unique-id', fw.randomMD5());
43
  }
44
 
45
+ fwOptionTypeIconV2Instance.set('size', modalSize);
46
+
47
+ fwOptionTypeIconV2Instance.open(getDataForRoot($root))
48
+ .then(function (data) {
49
+ setDataForRoot($root, data);
50
+ })
51
+ .fail(function () {
52
+ // modal closed without save
53
+ });
54
+
55
+ /*
56
  fwOptionTypeIconV2Picker.pick(
57
  getDataForRoot($root),
58
  $root.data('unique-id'),
64
  },
65
  modalSize
66
  );
67
+ */
68
  }
69
 
70
  function removeIcon (event) {
201
 
202
  $root.find('input').val(
203
  JSON.stringify(
204
+ _.omit(
205
+ _.extend(
206
+ {},
207
+ currentData,
208
+ data
209
+ ),
210
+
211
+ 'attachment'
212
  )
213
  )
214
  ).trigger('change');
framework/includes/option-types/icon-v2/views/templates.php ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $tabs = fw()->backend->render_options(
4
+ array(
5
+ 'icon-fonts' => array(
6
+ 'type' => 'tab',
7
+ 'title' => __('Icons', 'fw'),
8
+ 'lazy_tabs' => false,
9
+ 'options' => array(
10
+ 'icon-font' => array(
11
+ 'type' => 'html-full',
12
+ 'attr' => array('class' => 'fw-icon-v2-icons-library'),
13
+ 'label' => false,
14
+ 'html' => '{{{data.icons_library_html}}}',
15
+ )
16
+ )
17
+ ),
18
+
19
+ 'favorites' => array(
20
+ 'type' => 'tab',
21
+ 'attr' => array('class' => '.fw-icon-v2-favorites'),
22
+ 'title' => __('Favorites', 'fw'),
23
+ 'lazy_tabs' => false,
24
+ 'options' => array(
25
+ 'icon-font-favorites' => array(
26
+ 'type' => 'html-full',
27
+ 'label' => false,
28
+ 'html' => '{{{data.favorites_list_html}}}'
29
+ )
30
+ )
31
+ ),
32
+
33
+ 'custom-upload' => array(
34
+ 'type' => 'tab',
35
+ 'lazy_tabs' => false,
36
+ 'title' => __('Upload', 'fw'),
37
+ 'options' => array(
38
+ 'custom-upload' => array(
39
+ 'type' => 'upload',
40
+ 'label' => __('Upload Icon', 'fw')
41
+ )
42
+ )
43
+ )
44
+ ),
45
+
46
+ /** $values */
47
+ array(),
48
+
49
+ array(
50
+ 'id_prefix' => 'fw-option-type-iconv2-',
51
+ 'name_prefix' => 'fw_option_type_iconv2'
52
+ )
53
+ );
54
+
55
+ ?>
56
+
57
+ <script type="text/html" id="tmpl-fw-icon-v2-tabs">
58
+
59
+ <?php echo $tabs; ?>
60
+
61
+ </script>
62
+
63
+ <script type="text/html" id="tmpl-fw-icon-v2-library">
64
+
65
+ <div class="fw-icon-v2-toolbar">
66
+ <input
67
+ type="text"
68
+ placeholder="<?php echo __('Search Icon', 'fw'); ?>"
69
+ class="fw-option fw-option-type-text">
70
+
71
+ <select class="fw-selectize">
72
+ <option selected value="all">
73
+ <?php echo __('All Packs', 'fw'); ?>
74
+ </option>
75
+
76
+ <# _.each(data.packs, function (pack) { #>
77
+ <option value="{{pack.name}}">{{pack.title}}</option>
78
+ <# }) #>
79
+ </select>
80
+ </div>
81
+
82
+ <div class="fw-icon-v2-library-packs-wrapper">
83
+ <# if (data.packs.length > 0) { #>
84
+ <# var template = wp.template('fw-icon-v2-packs'); #>
85
+
86
+ {{{ template(data) }}}
87
+ <# } #>
88
+ </div>
89
+
90
+ </script>
91
+
92
+ <script type="text/html" id="tmpl-fw-icon-v2-packs">
93
+ <# _.each(data.packs, function (pack) { #>
94
+ <# if (pack.icons.length === 0) { return; } #>
95
+
96
+ <h2>
97
+ <span>{{pack.title}}</span>
98
+ </h2>
99
+
100
+ {{{
101
+ wp.template('fw-icon-v2-icons-collection')(
102
+ _.extend({}, pack, {
103
+ current_state: data.current_state,
104
+ favorites: data.favorites
105
+ })
106
+ )
107
+ }}}
108
+ <# }) #>
109
+ </script>
110
+
111
+ <script type="text/html" id="tmpl-fw-icon-v2-favorites">
112
+
113
+ <div class="fw-icon-v2-icon-favorites">
114
+ <# if (data.favorites.length === 0) { #>
115
+
116
+ <h4>You have no favorite icons yet.</h4>
117
+ <p>
118
+ To add icons here, simply click on the star
119
+ (<i class="fw-icon-v2-info dashicons dashicons-star-filled"></i>)
120
+ button that's on top of each icon.
121
+ </p>
122
+
123
+ <# } else { #>
124
+
125
+ {{{
126
+ wp.template('fw-icon-v2-icons-collection')(
127
+ _.extend({}, {icons: data.favorites, current_state: data.current_state})
128
+ )
129
+ }}}
130
+
131
+ <# } #>
132
+ </div>
133
+
134
+ </script>
135
+
136
+ <script type="text/html" id="tmpl-fw-icon-v2-icons-collection">
137
+
138
+ <# if (data.icons.length > 0) { #>
139
+ <ul class="fw-icon-v2-library-pack">
140
+
141
+ <# _.each(data.icons, function (icon) { #>
142
+ <# var iconClass = data.css_class_prefix ? data.css_class_prefix + ' ' + icon : icon; #>
143
+ <# var selectedClass = data.current_state['icon-class'] === iconClass ? 'selected' : ''; #>
144
+ <# var favoriteClass = _.contains(data.favorites, iconClass) ? 'fw-icon-v2-favorite' : '' #>
145
+
146
+ <li
147
+ data-fw-icon-v2="{{data.css_class_prefix}} {{icon}}"
148
+ class="fw-icon-v2-library-icon {{selectedClass}} {{favoriteClass}}">
149
+
150
+ <i class="{{iconClass}}"></i>
151
+
152
+ <a
153
+ title="<?php echo __('Add to Favorites', 'fw') ?>"
154
+ class="fw-icon-v2-favorite">
155
+
156
+ <i class="dashicons dashicons-star-filled"></i>
157
+ </a>
158
+ </li>
159
+
160
+ <# }) #>
161
+ </ul>
162
+ <# } #>
163
+
164
+ </script>
165
+
166
+ <?php
167
+
168
+ /* <li class="fw-icon-v2-library-icon" data-fw-icon-v2="{{icon}}"> */
169
+ /* <i class="{{icon}}"> */
170
+ /* <a title="<?php __('Add To Favorites', 'fw'); ?>" */
171
+ /* class="fw-icon-v2-favorite"> */
172
+ /* <i class="dashicons dashicons-star-filled"></i> */
173
+ /* </a> */
174
+ /* </li> */
175
+
176
+ ?>
framework/includes/option-types/icon-v2/{view.php → views/view.php} RENAMED
@@ -26,3 +26,4 @@ unset($option['attr']['class'], $option['attr']['id']);
26
  <div <?php echo fw_attr_to_html($wrapper_attr) ?>>
27
  <input <?php echo fw_attr_to_html($option['attr']) ?> type="hidden" />
28
  </div>
 
26
  <div <?php echo fw_attr_to_html($wrapper_attr) ?>>
27
  <input <?php echo fw_attr_to_html($option['attr']) ?> type="hidden" />
28
  </div>
29
+
framework/includes/option-types/image-picker/class-fw-option-type-image-picker.php CHANGED
@@ -104,7 +104,7 @@ class Fw_Option_Type_Image_Picker extends FW_Option_Type
104
  {
105
  $html .= '<select ' . fw_attr_to_html($option['attr']) . '>';
106
 
107
- if (!empty($option['blank']) and $option['blank'] === true) {
108
  $html .= '<option value=""></option>';
109
  }
110
 
@@ -172,13 +172,16 @@ class Fw_Option_Type_Image_Picker extends FW_Option_Type
172
  */
173
  protected function _get_value_from_input($option, $input_value)
174
  {
175
- if (is_null($input_value)) {
176
  return $option['value'];
177
  }
178
 
179
  if (!isset($option['choices'][$input_value])) {
180
- if (
181
- empty($option['choices']) ||
 
 
 
182
  isset($option['choices'][ $option['value'] ])
183
  ) {
184
  $input_value = $option['value'];
104
  {
105
  $html .= '<select ' . fw_attr_to_html($option['attr']) . '>';
106
 
107
+ if ($option['blank'] === true) {
108
  $html .= '<option value=""></option>';
109
  }
110
 
172
  */
173
  protected function _get_value_from_input($option, $input_value)
174
  {
175
+ if (!is_string($input_value)) {
176
  return $option['value'];
177
  }
178
 
179
  if (!isset($option['choices'][$input_value])) {
180
+ if ($option['blank']) {
181
+ $input_value = '';
182
+ } elseif (
183
+ ! empty($option['choices'])
184
+ &&
185
  isset($option['choices'][ $option['value'] ])
186
  ) {
187
  $input_value = $option['value'];
framework/includes/option-types/multi-picker/class-fw-option-type-multi-picker.php CHANGED
@@ -38,21 +38,27 @@ class FW_Option_Type_Multi_Picker extends FW_Option_Type
38
  */
39
  protected function _enqueue_static($id, $option, $data)
40
  {
 
41
  $uri = fw_get_framework_directory_uri('/includes/option-types/' . $this->get_type());
42
 
43
- wp_enqueue_style(
44
- 'fw-option-type-' . $this->get_type(),
45
- $uri . '/static/css/multi-picker.css',
46
- array(),
47
- fw()->manifest->get_version()
48
- );
49
- wp_enqueue_script(
50
- 'fw-option-type-' . $this->get_type(),
51
- $uri . '/static/js/multi-picker.js',
52
- array('jquery', 'fw-events'),
53
- fw()->manifest->get_version(),
54
- true
55
- );
 
 
 
 
 
56
 
57
  fw()->backend->enqueue_options_static($this->prepare_option($id, $option));
58
 
38
  */
39
  protected function _enqueue_static($id, $option, $data)
40
  {
41
+ static $enqueue = true;
42
  $uri = fw_get_framework_directory_uri('/includes/option-types/' . $this->get_type());
43
 
44
+ if ($enqueue) {
45
+ wp_enqueue_style(
46
+ 'fw-option-type-' . $this->get_type(),
47
+ $uri . '/static/css/multi-picker.css',
48
+ array(),
49
+ fw()->manifest->get_version()
50
+ );
51
+
52
+ wp_enqueue_script(
53
+ 'fw-option-type-' . $this->get_type(),
54
+ $uri . '/static/js/multi-picker.js',
55
+ array('jquery', 'fw-events'),
56
+ fw()->manifest->get_version(),
57
+ true
58
+ );
59
+
60
+ $enqueue = false;
61
+ }
62
 
63
  fw()->backend->enqueue_options_static($this->prepare_option($id, $option));
64
 
framework/includes/option-types/multi/class-fw-option-type-multi.php CHANGED
@@ -16,12 +16,18 @@ class FW_Option_Type_Multi extends FW_Option_Type
16
  */
17
  protected function _enqueue_static($id, $option, $data)
18
  {
19
- wp_enqueue_style(
20
- 'fw-option-'. $this->get_type(),
21
- fw_get_framework_directory_uri('/includes/option-types/'. $this->get_type() .'/static/css/styles.css'),
22
- array(),
23
- fw()->manifest->get_version()
24
- );
 
 
 
 
 
 
25
 
26
  fw()->backend->enqueue_options_static($option['inner-options']);
27
 
16
  */
17
  protected function _enqueue_static($id, $option, $data)
18
  {
19
+ static $enqueue = true;
20
+
21
+ if ($enqueue) {
22
+ wp_enqueue_style(
23
+ 'fw-option-'. $this->get_type(),
24
+ fw_get_framework_directory_uri('/includes/option-types/'. $this->get_type() .'/static/css/styles.css'),
25
+ array(),
26
+ fw()->manifest->get_version()
27
+ );
28
+
29
+ $enqueue = false;
30
+ }
31
 
32
  fw()->backend->enqueue_options_static($option['inner-options']);
33
 
framework/includes/option-types/multi/static/css/styles.css CHANGED
@@ -6,6 +6,10 @@
6
  border-bottom-width: 0;
7
  }
8
 
 
 
 
 
9
  /* show options separator borders */
10
 
11
  .fw-option-type-multi.fw-option-type-multi-show-borders > .fw-backend-option {
6
  border-bottom-width: 0;
7
  }
8
 
9
+ .fw-option-type-multi > .fw-backend-option.fw-backend-option-type-multi + .fw-backend-option.fw-backend-option-type-multi {
10
+ border-top-width: 1px;
11
+ }
12
+
13
  /* show options separator borders */
14
 
15
  .fw-option-type-multi.fw-option-type-multi-show-borders > .fw-backend-option {
framework/includes/option-types/oembed/view.php CHANGED
@@ -23,16 +23,19 @@ $input_attr['placeholder'] = $option['attr']['placeholder'];
23
  </div>
24
  <div class="fw-oembed-preview">
25
  <?php
26
- $iframe = empty( $option['preview']['keep_ratio'] ) ? fw_oembed_get( $data['value'], array(
27
- 'height' => $option['preview']['height'],
28
- 'width' => $option['preview']['width']
29
- ) ) :
30
- wp_oembed_get( $data['value'], array(
31
  'height' => $option['preview']['height'],
32
  'width' => $option['preview']['width']
33
- ) );
 
 
 
 
34
 
35
- echo $iframe;
 
36
  ?>
37
  </div>
38
  </div>
23
  </div>
24
  <div class="fw-oembed-preview">
25
  <?php
26
+ $value = fw_akg('value', $data);
27
+ if ( filter_var( $value, FILTER_VALIDATE_URL ) ) {
28
+ $iframe = empty( $option['preview']['keep_ratio'] ) ? fw_oembed_get( $value, array(
 
 
29
  'height' => $option['preview']['height'],
30
  'width' => $option['preview']['width']
31
+ ) ) :
32
+ wp_oembed_get( $value, array(
33
+ 'height' => $option['preview']['height'],
34
+ 'width' => $option['preview']['width']
35
+ ) );
36
 
37
+ echo $iframe;
38
+ }
39
  ?>
40
  </div>
41
  </div>
framework/includes/option-types/popup/class-fw-option-type-popup.php CHANGED
@@ -17,19 +17,25 @@ class FW_Option_Type_Popup extends FW_Option_Type {
17
  * {@inheritdoc}
18
  */
19
  protected function _enqueue_static( $id, $option, $data ) {
20
- wp_enqueue_style(
21
- 'fw-option-' . $this->get_type(),
22
- fw_get_framework_directory_uri( '/includes/option-types/' . $this->get_type() . '/static/css/styles.css' ),
23
- array( 'fw' )
24
- );
25
-
26
- wp_enqueue_script(
27
- 'fw-option-' . $this->get_type(),
28
- fw_get_framework_directory_uri( '/includes/option-types/' . $this->get_type() . '/static/js/' . $this->get_type() . '.js' ),
29
- array( 'underscore', 'fw-events', 'jquery-ui-sortable', 'fw' ),
30
- false,
31
- true
32
- );
 
 
 
 
 
 
33
 
34
  fw()->backend->enqueue_options_static( $option['popup-options'] );
35
 
@@ -116,6 +122,11 @@ class FW_Option_Type_Popup extends FW_Option_Type {
116
  return array();
117
  }
118
 
 
 
 
 
 
119
  $popup_options = array();
120
  foreach (fw_extract_only_options($option['popup-options']) as $popup_option_id => $popup_option) {
121
  if (isset($option['value'][$popup_option_id])) {
@@ -129,9 +140,9 @@ class FW_Option_Type_Popup extends FW_Option_Type {
129
  /**
130
  * Don't decode if we have already an array
131
  */
132
- $values = $input_value;
133
  } else {
134
- $values = json_decode( $input_value, true );
135
  }
136
 
137
  return $values;
17
  * {@inheritdoc}
18
  */
19
  protected function _enqueue_static( $id, $option, $data ) {
20
+ static $enqueue = true;
21
+
22
+ if ($enqueue) {
23
+ wp_enqueue_style(
24
+ 'fw-option-' . $this->get_type(),
25
+ fw_get_framework_directory_uri( '/includes/option-types/' . $this->get_type() . '/static/css/styles.css' ),
26
+ array( 'fw' )
27
+ );
28
+
29
+ wp_enqueue_script(
30
+ 'fw-option-' . $this->get_type(),
31
+ fw_get_framework_directory_uri( '/includes/option-types/' . $this->get_type() . '/static/js/' . $this->get_type() . '.js' ),
32
+ array( 'underscore', 'fw-events', 'jquery-ui-sortable', 'fw' ),
33
+ false,
34
+ true
35
+ );
36
+
37
+ $enqueue = false;
38
+ }
39
 
40
  fw()->backend->enqueue_options_static( $option['popup-options'] );
41
 
122
  return array();
123
  }
124
 
125
+ /**
126
+ * $option['value'] has DB format (not $input_value HTML format)
127
+ * so it can't be used as second parameter in fw_get_options_values_from_input()
128
+ * thus we need to move each option value in option array default values
129
+ */
130
  $popup_options = array();
131
  foreach (fw_extract_only_options($option['popup-options']) as $popup_option_id => $popup_option) {
132
  if (isset($option['value'][$popup_option_id])) {
140
  /**
141
  * Don't decode if we have already an array
142
  */
143
+ $values = fw_get_options_values_from_input($option['popup-options'], $input_value);
144
  } else {
145
+ $values = fw_get_options_values_from_input($option['popup-options'], json_decode( $input_value, true ));
146
  }
147
 
148
  return $values;
framework/includes/option-types/upload/static/js/any-files.js CHANGED
@@ -21,7 +21,7 @@
21
  var parsedFilesDetails = JSON.parse(elements.$container.attr('data-files-details'));
22
  }
23
 
24
- var createFrame = function() {
25
  var frameOpts = haveFilesDetails ?
26
  {
27
  library: {
@@ -31,7 +31,7 @@
31
 
32
  frame = wp.media(frameOpts);
33
 
34
- if(haveFilesDetails) {
35
  frame.on('content:render', function () {
36
  var $view = this.first().frame.views.get('.media-frame-uploader')[0];
37
 
@@ -65,6 +65,7 @@
65
  attachment = wp.media.attachment(attatchmentId);
66
 
67
  frame.reset();
 
68
  if (attachment.id) {
69
  selection.add(attachment);
70
  }
@@ -72,42 +73,70 @@
72
 
73
  frame.on('select', function() {
74
  var attachment = frame.state().get('selection').first();
75
-
76
- elements.$textField.text(attachment.get('filename'));
77
- elements.$uploadButton.text(l10n.buttonEdit);
78
- elements.$input.val(attachment.id).trigger('change');
79
- elements.$container.removeClass('empty');
80
-
81
- fwe.trigger('fw:option-type:upload:change', {
82
- $element: elements.$container,
83
- attachment: attachment
84
- });
85
- elements.$container.trigger('fw:option-type:upload:change', {
86
- attachment: attachment
87
- });
88
  });
89
  };
90
 
91
  elements.$uploadButton.on('click', function(e) {
92
  e.preventDefault();
93
 
94
- if (!frame) {
95
  createFrame();
96
  }
 
97
  frame.open();
98
  });
99
 
100
  elements.$deleteButton.on('click', function(e) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  elements.$textField.text('');
102
  elements.$uploadButton.text(l10n.buttonAdd);
103
- elements.$input.val('').trigger('change');
104
  elements.$container.addClass('empty');
105
 
106
  fwe.trigger('fw:option-type:upload:clear', {$element: elements.$container});
107
  elements.$container.trigger('fw:option-type:upload:clear');
 
108
 
109
- e.preventDefault();
110
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  };
112
 
113
  fwe.on('fw:options:init', function(data) {
@@ -116,4 +145,4 @@
116
  .addClass('fw-option-initialized');
117
  });
118
 
119
- })(jQuery, fwEvents);
21
  var parsedFilesDetails = JSON.parse(elements.$container.attr('data-files-details'));
22
  }
23
 
24
+ var createFrame = function() {
25
  var frameOpts = haveFilesDetails ?
26
  {
27
  library: {
31
 
32
  frame = wp.media(frameOpts);
33
 
34
+ if (haveFilesDetails) {
35
  frame.on('content:render', function () {
36
  var $view = this.first().frame.views.get('.media-frame-uploader')[0];
37
 
65
  attachment = wp.media.attachment(attatchmentId);
66
 
67
  frame.reset();
68
+
69
  if (attachment.id) {
70
  selection.add(attachment);
71
  }
73
 
74
  frame.on('select', function() {
75
  var attachment = frame.state().get('selection').first();
76
+ elements.$input.val(attachment.id);
77
+ performSelection(attachment);
 
 
 
 
 
 
 
 
 
 
 
78
  });
79
  };
80
 
81
  elements.$uploadButton.on('click', function(e) {
82
  e.preventDefault();
83
 
84
+ if (! frame) {
85
  createFrame();
86
  }
87
+
88
  frame.open();
89
  });
90
 
91
  elements.$deleteButton.on('click', function(e) {
92
+ clearAttachment();
93
+ elements.$input.val('');
94
+ e.preventDefault();
95
+ });
96
+
97
+ elements.$input.on('change', function () {
98
+ if (! $(this).val()) {
99
+ clearAttachment();
100
+ return;
101
+ }
102
+
103
+ var attachment = wp.media.attachment($(this).val());
104
+
105
+ if (! attachment.get('url')) {
106
+ attachment.fetch().then(function (data) {
107
+ performSelection(attachment);
108
+ });
109
+
110
+ return;
111
+ }
112
+
113
+ performSelection(attachment);
114
+ })
115
+
116
+ function clearAttachment () {
117
  elements.$textField.text('');
118
  elements.$uploadButton.text(l10n.buttonAdd);
 
119
  elements.$container.addClass('empty');
120
 
121
  fwe.trigger('fw:option-type:upload:clear', {$element: elements.$container});
122
  elements.$container.trigger('fw:option-type:upload:clear');
123
+ }
124
 
125
+ function performSelection (attachment) {
126
+ elements.$textField.text(attachment.get('filename'));
127
+ elements.$uploadButton.text(l10n.buttonEdit);
128
+
129
+ elements.$container.removeClass('empty');
130
+
131
+ fwe.trigger('fw:option-type:upload:change', {
132
+ $element: elements.$container,
133
+ attachment: attachment
134
+ });
135
+
136
+ elements.$container.trigger('fw:option-type:upload:change', {
137
+ attachment: attachment
138
+ });
139
+ }
140
  };
141
 
142
  fwe.on('fw:options:init', function(data) {
145
  .addClass('fw-option-initialized');
146
  });
147
 
148
+ })(jQuery, fwEvents);
framework/includes/option-types/upload/static/js/images-only.js CHANGED
@@ -29,20 +29,20 @@
29
  }
30
 
31
  var createFrame = function() {
32
- frame = wp.media({
33
- library: {
34
- type: haveFilesDetails ? parsedFilesDetails.mime_types : 'image'
35
- },
36
- states: new wp.media.controller.Library({
37
- library: wp.media.query( { type: 'image' } ),
38
- multiple: false,
39
- title: l10n.modalTitle,
40
- filterable: 'uploaded',
41
- priority: 20
42
- })
43
- });
44
-
45
- if(haveFilesDetails) {
46
  frame.on('content:render', function () {
47
  var $view = this.first().frame.views.get('.media-frame-uploader')[0];
48
 
@@ -65,67 +65,37 @@
65
  });
66
  }
67
 
68
- frame.on('ready', function() {
69
- frame.modal.$el.addClass('fw-option-type-upload');
70
- });
71
 
72
- // opens the modal with the correct attachment selected
73
- frame.on('open', function() {
74
- var selection = frame.state().get('selection'),
75
- attatchmentId = elements.$input.val(),
76
- attachment = wp.media.attachment(attatchmentId);
77
 
78
- frame.reset();
79
- if (attachment.id) {
80
- selection.add(attachment);
81
- }
82
- });
83
 
84
- frame.on('select', function() {
85
- var attachment = frame.state().get('selection').first(),
86
- url, filename, compiled;
 
87
 
88
- if (attachment.get('sizes')) {
89
- url = attachment.get('sizes').thumbnail
90
- ? attachment.get('sizes').thumbnail.url
91
- : attachment.get('sizes').full.url;
92
- } else {
93
- url = attachment.get('url');
94
- }
95
- filename = attachment.get('filename');
96
- compiled = _.template(
97
- templates.thumb.notEmpty,
98
- undefined,
99
- {variable: 'data'}
100
- )({src: url, alt: filename});
101
-
102
- elements.$uploadButton.text(l10n.buttonEdit);
103
- elements.$thumb
104
- .html(compiled)
105
- .attr({
106
- 'data-attid': attachment.id,
107
- 'data-origsrc': attachment.get('url')
108
- });
109
- elements.$urlInput.val(attachment.get('url'));
110
- elements.$input.val(attachment.id).trigger('change');
111
- elements.$container.removeClass('empty');
112
-
113
- fwe.trigger('fw:option-type:upload:change', {
114
- $element: elements.$container,
115
- attachment: attachment
116
- });
117
- elements.$container.trigger('fw:option-type:upload:change', {
118
- attachment: attachment
119
- });
120
- });
121
- };
122
 
123
  elements.$uploadButton.on('click', function(e) {
124
  e.preventDefault();
125
 
126
- if (!frame) {
127
  createFrame();
128
  }
 
129
  frame.open();
130
  });
131
 
@@ -134,18 +104,83 @@
134
  });
135
 
136
  elements.$thumb.on('click', '.clear-uploads-thumb', function(e) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  elements.$uploadButton.text(l10n.buttonAdd);
138
  elements.$thumb
139
  .html(templates.thumb.empty)
140
  .removeAttr('data-attid data-origsrc');
141
- elements.$input.val('').trigger('change');
142
  elements.$container.addClass('empty');
143
 
144
  fwe.trigger('fw:option-type:upload:clear', {$element: elements.$container});
145
  elements.$container.trigger('fw:option-type:upload:clear');
 
146
 
147
- e.preventDefault();
148
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  };
150
 
151
  fwe.on('fw:options:init', function(data) {
29
  }
30
 
31
  var createFrame = function() {
32
+ frame = wp.media({
33
+ library: {
34
+ type: haveFilesDetails ? parsedFilesDetails.mime_types : 'image'
35
+ },
36
+ states: new wp.media.controller.Library({
37
+ library: wp.media.query( { type: 'image' } ),
38
+ multiple: false,
39
+ title: l10n.modalTitle,
40
+ filterable: 'uploaded',
41
+ priority: 20
42
+ })
43
+ });
44
+
45
+ if (haveFilesDetails) {
46
  frame.on('content:render', function () {
47
  var $view = this.first().frame.views.get('.media-frame-uploader')[0];
48
 
65
  });
66
  }
67
 
68
+ frame.on('ready', function() {
69
+ frame.modal.$el.addClass('fw-option-type-upload');
70
+ });
71
 
72
+ // opens the modal with the correct attachment selected
73
+ frame.on('open', function() {
74
+ var selection = frame.state().get('selection'),
75
+ attatchmentId = elements.$input.val(),
76
+ attachment = wp.media.attachment(attatchmentId);
77
 
78
+ frame.reset();
 
 
 
 
79
 
80
+ if (attachment.id) {
81
+ selection.add(attachment);
82
+ }
83
+ });
84
 
85
+ frame.on('select', function() {
86
+ var attachment = frame.state().get('selection').first();
87
+ elements.$input.val(attachment.id);
88
+ performSelection(attachment);
89
+ });
90
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
  elements.$uploadButton.on('click', function(e) {
93
  e.preventDefault();
94
 
95
+ if (! frame) {
96
  createFrame();
97
  }
98
+
99
  frame.open();
100
  });
101
 
104
  });
105
 
106
  elements.$thumb.on('click', '.clear-uploads-thumb', function(e) {
107
+ clearAttachment();
108
+
109
+ elements.$input.val('');
110
+
111
+ e.preventDefault();
112
+ });
113
+
114
+ elements.$input.on('change', function () {
115
+ if (! $(this).val()) {
116
+ clearAttachment();
117
+ return;
118
+ }
119
+
120
+ var attachment = wp.media.attachment($(this).val());
121
+
122
+ if (! attachment.get('url')) {
123
+ attachment.fetch().then(function (data) {
124
+ performSelection(attachment);
125
+ });
126
+
127
+ return;
128
+ }
129
+
130
+ performSelection(attachment);
131
+ });
132
+
133
+ function clearAttachment () {
134
  elements.$uploadButton.text(l10n.buttonAdd);
135
  elements.$thumb
136
  .html(templates.thumb.empty)
137
  .removeAttr('data-attid data-origsrc');
 
138
  elements.$container.addClass('empty');
139
 
140
  fwe.trigger('fw:option-type:upload:clear', {$element: elements.$container});
141
  elements.$container.trigger('fw:option-type:upload:clear');
142
+ }
143
 
144
+ function performSelection (attachment) {
145
+ var url, filename, compiled;
146
+
147
+ if (attachment.get('sizes')) {
148
+ url = attachment.get('sizes').thumbnail
149
+ ? attachment.get('sizes').thumbnail.url
150
+ : attachment.get('sizes').full.url;
151
+ } else {
152
+ url = attachment.get('url');
153
+ }
154
+
155
+ filename = attachment.get('filename');
156
+
157
+ compiled = _.template(
158
+ templates.thumb.notEmpty,
159
+ undefined,
160
+ {variable: 'data'}
161
+ )({src: url, alt: filename});
162
+
163
+ elements.$uploadButton.text(l10n.buttonEdit);
164
+
165
+ elements.$thumb
166
+ .html(compiled)
167
+ .attr({
168
+ 'data-attid': attachment.id,
169
+ 'data-origsrc': attachment.get('url')
170
+ });
171
+
172
+ elements.$urlInput.val(attachment.get('url'));
173
+ elements.$container.removeClass('empty');
174
+
175
+ fwe.trigger('fw:option-type:upload:change', {
176
+ $element: elements.$container,
177
+ attachment: attachment
178
+ });
179
+
180
+ elements.$container.trigger('fw:option-type:upload:change', {
181
+ attachment: attachment
182
+ });
183
+ }
184
  };
185
 
186
  fwe.on('fw:options:init', function(data) {
framework/manifest.php CHANGED
@@ -4,4 +4,4 @@ $manifest = array();
4
 
5
  $manifest['name'] = __('Unyson', 'fw');
6
 
7
- $manifest['version'] = '2.6.1';
4
 
5
  $manifest['name'] = __('Unyson', 'fw');
6
 
7
+ $manifest['version'] = '2.6.2';
framework/static/css/backend-options.css CHANGED
@@ -878,6 +878,7 @@ body.rtl .fw-postbox .handlediv:before {
878
  .fw-backend-option-design-default {
879
  position: relative;
880
  padding: 24px 27px 21px;
 
881
  border-bottom: 1px solid #eeeeee;
882
  }
883
 
878
  .fw-backend-option-design-default {
879
  position: relative;
880
  padding: 24px 27px 21px;
881
+ border: 0px solid #eeeeee;
882
  border-bottom: 1px solid #eeeeee;
883
  }
884
 
framework/static/css/option-types.css CHANGED
@@ -103,10 +103,10 @@ body.rtl .fw-option-type-radio.fw-option-type-radio-inline > div:not(:last-child
103
 
104
  /* modal fixes */
105
 
106
- .fw-modal .media-frame input[type=email],
107
- .fw-modal .media-frame input[type=number],
108
  .fw-modal .media-frame input[type=password],
 
109
  .fw-modal .media-frame input[type=search],
 
110
  .fw-modal .media-frame input[type=text],
111
  .fw-modal .media-frame input[type=url],
112
  .fw-modal .media-frame select,
@@ -125,9 +125,14 @@ body.rtl .fw-option-type-radio.fw-option-type-radio-inline > div:not(:last-child
125
  height: auto;
126
  }
127
 
128
- .fw-modal .media-frame input[type=text],
129
  .fw-modal .media-frame input[type=password],
 
 
 
 
 
130
  .fw-modal .media-frame textarea {
 
131
  padding: 3px 5px;
132
  }
133
 
103
 
104
  /* modal fixes */
105
 
 
 
106
  .fw-modal .media-frame input[type=password],
107
+ .fw-modal .media-frame input[type=number],
108
  .fw-modal .media-frame input[type=search],
109
+ .fw-modal .media-frame input[type=email],
110
  .fw-modal .media-frame input[type=text],
111
  .fw-modal .media-frame input[type=url],
112
  .fw-modal .media-frame select,
125
  height: auto;
126
  }
127
 
 
128
  .fw-modal .media-frame input[type=password],
129
+ .fw-modal .media-frame input[type=number],
130
+ .fw-modal .media-frame input[type=search],
131
+ .fw-modal .media-frame input[type=email],
132
+ .fw-modal .media-frame input[type=text],
133
+ .fw-modal .media-frame input[type=url],
134
  .fw-modal .media-frame textarea {
135
+ height: 28px;
136
  padding: 3px 5px;
137
  }
138
 
framework/static/js/backend-options.js CHANGED
@@ -129,8 +129,10 @@ jQuery(document).ready(function($){
129
  .closest('form')
130
  .off('submit.fw-tabs')
131
  .on('submit.fw-tabs', function () {
132
- // All options needs to be present in html to be sent in POST on submit
133
- initAllTabs($(this));
 
 
134
  });
135
  } else {
136
  $tabs.tabs();
129
  .closest('form')
130
  .off('submit.fw-tabs')
131
  .on('submit.fw-tabs', function () {
132
+ if (!$(this).hasClass('prevent-all-tabs-init')) {
133
+ // All options needs to be present in html to be sent in POST on submit
134
+ initAllTabs($(this));
135
+ }
136
  });
137
  } else {
138
  $tabs.tabs();
framework/static/js/fw-form-helpers.js CHANGED
@@ -31,6 +31,7 @@ var fwForm = {
31
  );
32
  }
33
  },
 
34
  onErrors: function (elements, data) {
35
  if (isAdmin) {
36
  fwForm.backend.showFlashMessages(
@@ -125,41 +126,58 @@ var fwForm = {
125
 
126
  opts.hideErrors(elements);
127
 
128
- /**
129
- * If you want to submit your ajaxified Theme Settings form without
130
- * any notification for the user add class fw-silent-submit to
131
- * the form element itself. This class will be removed
132
- * automatically after this particular submit, so that popup will
133
- * show when the user will press Submit button next time.
134
- */
135
- opts.loading(elements, ! $form.hasClass('fw-silent-submit'));
 
 
 
 
 
 
 
136
  $form.removeClass('fw-silent-submit');
137
 
138
  isBusy = true;
139
 
140
- jQuery.ajax({
141
- type: "POST",
142
- url: opts.ajaxUrl,
143
- data: $form.serialize() + ($submitButton.length ? '&'+ $submitButton.attr('name') +'='+ $submitButton.attr('value') : ''),
144
- dataType: 'json'
145
- }).done(function(r){
146
- isBusy = false;
147
- opts.loading(elements, false);
148
-
149
- if (r.success) {
150
- opts.onSuccess(elements, r.data);
151
- } else {
152
- opts.onErrors(elements, r.data);
153
  }
154
- }).fail(function(jqXHR, textStatus, errorThrown){
155
- isBusy = false;
156
- opts.loading(elements, false);
157
- opts.onAjaxError(elements, {
158
- jqXHR: jqXHR,
159
- textStatus: textStatus,
160
- errorThrown: errorThrown
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  });
162
- });
163
  });
164
  },
165
  backend: {
31
  );
32
  }
33
  },
34
+ afterSubmitDelay: function(elements){},
35
  onErrors: function (elements, data) {
36
  if (isAdmin) {
37
  fwForm.backend.showFlashMessages(
126
 
127
  opts.hideErrors(elements);
128
 
129
+ var delaySubmit = parseInt(
130
+ opts.loading(
131
+ elements,
132
+ /**
133
+ * If you want to submit your ajaxified Theme Settings form without
134
+ * any notification for the user add class fw-silent-submit to
135
+ * the form element itself. This class will be removed
136
+ * automatically after this particular submit, so that popup will
137
+ * show when the user will press Submit button next time.
138
+ */
139
+ ! $form.hasClass('fw-silent-submit')
140
+ )
141
+ );
142
+ delaySubmit = (isNaN(delaySubmit) || delaySubmit < 0) ? 0 : delaySubmit;
143
+
144
  $form.removeClass('fw-silent-submit');
145
 
146
  isBusy = true;
147
 
148
+ setTimeout(function(){
149
+ if (delaySubmit) {
150
+ opts.afterSubmitDelay(elements);
 
 
 
 
 
 
 
 
 
 
151
  }
152
+
153
+ jQuery.ajax({
154
+ type: "POST",
155
+ url: opts.ajaxUrl,
156
+ data: $form.serialize() + (
157
+ $submitButton.length
158
+ ? '&'+ $submitButton.attr('name') +'='+ $submitButton.attr('value')
159
+ : ''
160
+ ),
161
+ dataType: 'json'
162
+ }).done(function(r){
163
+ isBusy = false;
164
+ opts.loading(elements, false);
165
+
166
+ if (r.success) {
167
+ opts.onSuccess(elements, r.data);
168
+ } else {
169
+ opts.onErrors(elements, r.data);
170
+ }
171
+ }).fail(function(jqXHR, textStatus, errorThrown){
172
+ isBusy = false;
173
+ opts.loading(elements, false);
174
+ opts.onAjaxError(elements, {
175
+ jqXHR: jqXHR,
176
+ textStatus: textStatus,
177
+ errorThrown: errorThrown
178
+ });
179
  });
180
+ }, delaySubmit);
181
  });
182
  },
183
  backend: {
framework/static/js/fw.js CHANGED
@@ -624,6 +624,7 @@ fw.getQueryString = function(name) {
624
  */
625
  html: '',
626
  modalCustomClass: '',
 
627
  disableLazyTabs: false,
628
  size: 'small' // small, medium, large
629
  },
@@ -754,6 +755,8 @@ fw.getQueryString = function(name) {
754
  $modalWrapper.addClass('fw-modal-' + modal.defaults.size);
755
  }
756
 
 
 
757
  if (stackSize) {
758
  $modal.css({
759
  border: (stackSize * 30) +'px solid transparent'
@@ -875,7 +878,9 @@ fw.getQueryString = function(name) {
875
  * clear html
876
  * to prevent same ids in html when another modal with same options will be opened
877
  */
878
- modal.set('html', '');
 
 
879
 
880
  modal.frame.modal.$el.removeClass('fw-modal-open');
881
 
@@ -1130,6 +1135,10 @@ fw.getValuesFromServer = function (data) {
1130
  }
1131
  }),
1132
  defaults: _.extend(
 
 
 
 
1133
  fw.Modal.prototype.defaults,
1134
  {
1135
  /**
@@ -1150,7 +1159,9 @@ fw.getValuesFromServer = function (data) {
1150
  * Values of the options {'option-id': 'option value'}
1151
  * also used in fw()->backend->render_options()
1152
  */
1153
- values: {}
 
 
1154
  }
1155
  ),
1156
  initializeFrame: function(settings) {
@@ -1229,7 +1240,6 @@ fw.getValuesFromServer = function (data) {
1229
 
1230
  return this;
1231
  },
1232
-
1233
  /**
1234
  * @param {String} [actualValues] A string containing correctly serialized
1235
  * data that will be sent to the server.
@@ -1253,7 +1263,6 @@ fw.getValuesFromServer = function (data) {
1253
  actualValues: actualValues
1254
  });
1255
  },
1256
-
1257
  /**
1258
  * @returns {Promise} jQuery promise
1259
  *
@@ -1263,7 +1272,6 @@ fw.getValuesFromServer = function (data) {
1263
  getActualValues: function () {
1264
  return this.getValuesFromServer(this.content.$el.serialize());
1265
  },
1266
-
1267
  getHtmlCacheId: function(values) {
1268
  return fw.md5(
1269
  JSON.stringify(this.get('options')) +
@@ -1308,6 +1316,15 @@ fw.getValuesFromServer = function (data) {
1308
 
1309
  htmlCache[cacheId] = response.data.html;
1310
 
 
 
 
 
 
 
 
 
 
1311
  modal.set('html', response.data.html);
1312
  },
1313
  error: function (xhr, status, error) {
624
  */
625
  html: '',
626
  modalCustomClass: '',
627
+ emptyHtmlOnClose: true,
628
  disableLazyTabs: false,
629
  size: 'small' // small, medium, large
630
  },
755
  $modalWrapper.addClass('fw-modal-' + modal.defaults.size);
756
  }
757
 
758
+ $modalWrapper.addClass('fw-modal-level-'+ stackSize);
759
+
760
  if (stackSize) {
761
  $modal.css({
762
  border: (stackSize * 30) +'px solid transparent'
878
  * clear html
879
  * to prevent same ids in html when another modal with same options will be opened
880
  */
881
+ if (modal.get('emptyHtmlOnClose')) {
882
+ modal.set('html', '');
883
+ }
884
 
885
  modal.frame.modal.$el.removeClass('fw-modal-open');
886
 
1135
  }
1136
  }),
1137
  defaults: _.extend(
1138
+ /**
1139
+ * Don't mutate original one!!!
1140
+ */
1141
+ {},
1142
  fw.Modal.prototype.defaults,
1143
  {
1144
  /**
1159
  * Values of the options {'option-id': 'option value'}
1160
  * also used in fw()->backend->render_options()
1161
  */
1162
+ values: {},
1163
+
1164
+ silentReceiveOfDefaultValues: false
1165
  }
1166
  ),
1167
  initializeFrame: function(settings) {
1240
 
1241
  return this;
1242
  },
 
1243
  /**
1244
  * @param {String} [actualValues] A string containing correctly serialized
1245
  * data that will be sent to the server.
1263
  actualValues: actualValues
1264
  });
1265
  },
 
1266
  /**
1267
  * @returns {Promise} jQuery promise
1268
  *
1272
  getActualValues: function () {
1273
  return this.getValuesFromServer(this.content.$el.serialize());
1274
  },
 
1275
  getHtmlCacheId: function(values) {
1276
  return fw.md5(
1277
  JSON.stringify(this.get('options')) +
1316
 
1317
  htmlCache[cacheId] = response.data.html;
1318
 
1319
+ if (_.isEmpty(modal.get('values'))) {
1320
+ // fixes https://github.com/ThemeFuse/Unyson/issues/1042#issuecomment-244364121
1321
+ modal.set(
1322
+ 'values',
1323
+ response.data.default_values,
1324
+ {silent: modal.get('silentReceiveOfDefaultValues')}
1325
+ );
1326
+ }
1327
+
1328
  modal.set('html', response.data.html);
1329
  },
1330
  error: function (xhr, status, error) {
framework/static/libs/font-awesome/fonts/FontAwesome.otf CHANGED
Binary file
framework/static/libs/font-awesome/fonts/fontawesome-webfont.eot CHANGED
Binary file
framework/static/libs/font-awesome/fonts/fontawesome-webfont.svg CHANGED
@@ -363,7 +363,7 @@
363
  <glyph unicode="&#xf16a;" horiz-adv-x="1792" d="M1280 640q0 37 -30 54l-512 320q-31 20 -65 2q-33 -18 -33 -56v-640q0 -38 33 -56q16 -8 31 -8q20 0 34 10l512 320q30 17 30 54zM1792 640q0 -96 -1 -150t-8.5 -136.5t-22.5 -147.5q-16 -73 -69 -123t-124 -58q-222 -25 -671 -25t-671 25q-71 8 -124.5 58t-69.5 123 q-14 65 -21.5 147.5t-8.5 136.5t-1 150t1 150t8.5 136.5t22.5 147.5q16 73 69 123t124 58q222 25 671 25t671 -25q71 -8 124.5 -58t69.5 -123q14 -65 21.5 -147.5t8.5 -136.5t1 -150z" />
364
  <glyph unicode="&#xf16b;" horiz-adv-x="1792" d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" />
365
  <glyph unicode="&#xf16c;" d="M1289 -96h-1118v480h-160v-640h1438v640h-160v-480zM347 428l33 157l783 -165l-33 -156zM450 802l67 146l725 -339l-67 -145zM651 1158l102 123l614 -513l-102 -123zM1048 1536l477 -641l-128 -96l-477 641zM330 65v159h800v-159h-800z" />
366
- <glyph unicode="&#xf16d;" d="M1362 110v648h-135q20 -63 20 -131q0 -126 -64 -232.5t-174 -168.5t-240 -62q-197 0 -337 135.5t-140 327.5q0 68 20 131h-141v-648q0 -26 17.5 -43.5t43.5 -17.5h1069q25 0 43 17.5t18 43.5zM1078 643q0 124 -90.5 211.5t-218.5 87.5q-127 0 -217.5 -87.5t-90.5 -211.5 t90.5 -211.5t217.5 -87.5q128 0 218.5 87.5t90.5 211.5zM1362 1003v165q0 28 -20 48.5t-49 20.5h-174q-29 0 -49 -20.5t-20 -48.5v-165q0 -29 20 -49t49 -20h174q29 0 49 20t20 49zM1536 1211v-1142q0 -81 -58 -139t-139 -58h-1142q-81 0 -139 58t-58 139v1142q0 81 58 139 t139 58h1142q81 0 139 -58t58 -139z" />
367
  <glyph unicode="&#xf16e;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150 t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" />
368
  <glyph unicode="&#xf170;" d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
369
  <glyph unicode="&#xf171;" horiz-adv-x="1408" d="M815 677q8 -63 -50.5 -101t-111.5 -6q-39 17 -53.5 58t-0.5 82t52 58q36 18 72.5 12t64 -35.5t27.5 -67.5zM926 698q-14 107 -113 164t-197 13q-63 -28 -100.5 -88.5t-34.5 -129.5q4 -91 77.5 -155t165.5 -56q91 8 152 84t50 168zM1165 1240q-20 27 -56 44.5t-58 22 t-71 12.5q-291 47 -566 -2q-43 -7 -66 -12t-55 -22t-50 -43q30 -28 76 -45.5t73.5 -22t87.5 -11.5q228 -29 448 -1q63 8 89.5 12t72.5 21.5t75 46.5zM1222 205q-8 -26 -15.5 -76.5t-14 -84t-28.5 -70t-58 -56.5q-86 -48 -189.5 -71.5t-202 -22t-201.5 18.5q-46 8 -81.5 18 t-76.5 27t-73 43.5t-52 61.5q-25 96 -57 292l6 16l18 9q223 -148 506.5 -148t507.5 148q21 -6 24 -23t-5 -45t-8 -37zM1403 1166q-26 -167 -111 -655q-5 -30 -27 -56t-43.5 -40t-54.5 -31q-252 -126 -610 -88q-248 27 -394 139q-15 12 -25.5 26.5t-17 35t-9 34t-6 39.5 t-5.5 35q-9 50 -26.5 150t-28 161.5t-23.5 147.5t-22 158q3 26 17.5 48.5t31.5 37.5t45 30t46 22.5t48 18.5q125 46 313 64q379 37 676 -50q155 -46 215 -122q16 -20 16.5 -51t-5.5 -54z" />
@@ -626,7 +626,7 @@
626
  <glyph unicode="&#xf283;" horiz-adv-x="2304" d="M0 32v608h2304v-608q0 -66 -47 -113t-113 -47h-1984q-66 0 -113 47t-47 113zM640 256v-128h384v128h-384zM256 256v-128h256v128h-256zM2144 1408q66 0 113 -47t47 -113v-224h-2304v224q0 66 47 113t113 47h1984z" />
627
  <glyph unicode="&#xf284;" horiz-adv-x="1792" d="M1549 857q55 0 85.5 -28.5t30.5 -83.5t-34 -82t-91 -27h-136v-177h-25v398h170zM1710 267l-4 -11l-5 -10q-113 -230 -330.5 -366t-474.5 -136q-182 0 -348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71q244 0 454.5 -124t329.5 -338l2 -4l8 -16 q-30 -15 -136.5 -68.5t-163.5 -84.5q-6 -3 -479 -268q384 -183 799 -366zM896 -234q250 0 462.5 132.5t322.5 357.5l-287 129q-72 -140 -206 -222t-292 -82q-151 0 -280 75t-204 204t-75 280t75 280t204 204t280 75t280 -73.5t204 -204.5l280 143q-116 208 -321 329 t-443 121q-119 0 -232.5 -31.5t-209 -87.5t-176.5 -137t-137 -176.5t-87.5 -209t-31.5 -232.5t31.5 -232.5t87.5 -209t137 -176.5t176.5 -137t209 -87.5t232.5 -31.5z" />
628
  <glyph unicode="&#xf285;" horiz-adv-x="1792" d="M1427 827l-614 386l92 151h855zM405 562l-184 116v858l1183 -743zM1424 697l147 -95v-858l-532 335zM1387 718l-500 -802h-855l356 571z" />
629
- <glyph unicode="&#xf286;" horiz-adv-x="1792" d="M640 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1152 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1664 496v-752h-640v320q0 80 -56 136t-136 56t-136 -56t-56 -136v-320h-640v752q0 16 16 16h96 q16 0 16 -16v-112h128v624q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h16v393q-32 19 -32 55q0 26 19 45t45 19t45 -19t19 -45q0 -36 -32 -55v-9h272q16 0 16 -16v-224q0 -16 -16 -16h-272v-128h16q16 0 16 -16v-112h128 v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-624h128v112q0 16 16 16h96q16 0 16 -16z" />
630
  <glyph unicode="&#xf287;" horiz-adv-x="2304" d="M2288 731q16 -8 16 -27t-16 -27l-320 -192q-8 -5 -16 -5q-9 0 -16 4q-16 10 -16 28v128h-858q37 -58 83 -165q16 -37 24.5 -55t24 -49t27 -47t27 -34t31.5 -26t33 -8h96v96q0 14 9 23t23 9h320q14 0 23 -9t9 -23v-320q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v96h-96 q-32 0 -61 10t-51 23.5t-45 40.5t-37 46t-33.5 57t-28.5 57.5t-28 60.5q-23 53 -37 81.5t-36 65t-44.5 53.5t-46.5 17h-360q-22 -84 -91 -138t-157 -54q-106 0 -181 75t-75 181t75 181t181 75q88 0 157 -54t91 -138h104q24 0 46.5 17t44.5 53.5t36 65t37 81.5q19 41 28 60.5 t28.5 57.5t33.5 57t37 46t45 40.5t51 23.5t61 10h107q21 57 70 92.5t111 35.5q80 0 136 -56t56 -136t-56 -136t-136 -56q-62 0 -111 35.5t-70 92.5h-107q-17 0 -33 -8t-31.5 -26t-27 -34t-27 -47t-24 -49t-24.5 -55q-46 -107 -83 -165h1114v128q0 18 16 28t32 -1z" />
631
  <glyph unicode="&#xf288;" horiz-adv-x="1792" d="M1150 774q0 -56 -39.5 -95t-95.5 -39h-253v269h253q56 0 95.5 -39.5t39.5 -95.5zM1329 774q0 130 -91.5 222t-222.5 92h-433v-896h180v269h253q130 0 222 91.5t92 221.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348 t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
632
  <glyph unicode="&#xf289;" horiz-adv-x="2304" d="M1645 438q0 59 -34 106.5t-87 68.5q-7 -45 -23 -92q-7 -24 -27.5 -38t-44.5 -14q-12 0 -24 3q-31 10 -45 38.5t-4 58.5q23 71 23 143q0 123 -61 227.5t-166 165.5t-228 61q-134 0 -247 -73t-167 -194q108 -28 188 -106q22 -23 22 -55t-22 -54t-54 -22t-55 22 q-75 75 -180 75q-106 0 -181 -74.5t-75 -180.5t75 -180.5t181 -74.5h1046q79 0 134.5 55.5t55.5 133.5zM1798 438q0 -142 -100.5 -242t-242.5 -100h-1046q-169 0 -289 119.5t-120 288.5q0 153 100 267t249 136q62 184 221 298t354 114q235 0 408.5 -158.5t196.5 -389.5 q116 -25 192.5 -118.5t76.5 -214.5zM2048 438q0 -175 -97 -319q-23 -33 -64 -33q-24 0 -43 13q-26 17 -32 48.5t12 57.5q71 104 71 233t-71 233q-18 26 -12 57t32 49t57.5 11.5t49.5 -32.5q97 -142 97 -318zM2304 438q0 -244 -134 -443q-23 -34 -64 -34q-23 0 -42 13 q-26 18 -32.5 49t11.5 57q108 164 108 358q0 195 -108 357q-18 26 -11.5 57.5t32.5 48.5q26 18 57 12t49 -33q134 -198 134 -442z" />
@@ -664,12 +664,12 @@
664
  <glyph unicode="&#xf2ab;" d="M1279 388q0 22 -22 27q-67 15 -118 59t-80 108q-7 19 -7 25q0 15 19.5 26t43 17t43 20.5t19.5 36.5q0 19 -18.5 31.5t-38.5 12.5q-12 0 -32 -8t-31 -8q-4 0 -12 2q5 95 5 114q0 79 -17 114q-36 78 -103 121.5t-152 43.5q-199 0 -275 -165q-17 -35 -17 -114q0 -19 5 -114 q-4 -2 -14 -2q-12 0 -32 7.5t-30 7.5q-21 0 -38.5 -12t-17.5 -32q0 -21 19.5 -35.5t43 -20.5t43 -17t19.5 -26q0 -6 -7 -25q-64 -138 -198 -167q-22 -5 -22 -27q0 -46 137 -68q2 -5 6 -26t11.5 -30.5t23.5 -9.5q12 0 37.5 4.5t39.5 4.5q35 0 67 -15t54 -32.5t57.5 -32.5 t76.5 -15q43 0 79 15t57.5 32.5t53.5 32.5t67 15q14 0 39.5 -4t38.5 -4q16 0 23 10t11 30t6 25q137 22 137 68zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" />
665
  <glyph unicode="&#xf2ac;" horiz-adv-x="1664" d="M848 1408q134 1 240.5 -68.5t163.5 -192.5q27 -58 27 -179q0 -47 -9 -191q14 -7 28 -7q18 0 51 13.5t51 13.5q29 0 56 -18t27 -46q0 -32 -31.5 -54t-69 -31.5t-69 -29t-31.5 -47.5q0 -15 12 -43q37 -82 102.5 -150t144.5 -101q28 -12 80 -23q28 -6 28 -35 q0 -70 -219 -103q-7 -11 -11 -39t-14 -46.5t-33 -18.5q-20 0 -62 6.5t-64 6.5q-37 0 -62 -5q-32 -5 -63 -22.5t-58 -38t-58 -40.5t-76 -33.5t-99 -13.5q-52 0 -96.5 13.5t-75 33.5t-57.5 40.5t-58 38t-62 22.5q-26 5 -63 5q-24 0 -65.5 -7.5t-58.5 -7.5q-25 0 -35 18.5 t-14 47.5t-11 40q-219 33 -219 103q0 29 28 35q52 11 80 23q78 32 144.5 101t102.5 150q12 28 12 43q0 28 -31.5 47.5t-69.5 29.5t-69.5 31.5t-31.5 52.5q0 27 26 45.5t55 18.5q15 0 48 -13t53 -13q18 0 32 7q-9 142 -9 190q0 122 27 180q64 137 172 198t264 63z" />
666
  <glyph unicode="&#xf2ad;" d="M1280 388q0 22 -22 27q-67 14 -118 58t-80 109q-7 14 -7 25q0 15 19.5 26t42.5 17t42.5 20.5t19.5 36.5q0 19 -18.5 31.5t-38.5 12.5q-11 0 -31 -8t-32 -8q-4 0 -12 2q5 63 5 115q0 78 -17 114q-36 78 -102.5 121.5t-152.5 43.5q-198 0 -275 -165q-18 -38 -18 -115 q0 -38 6 -114q-10 -2 -15 -2q-11 0 -31.5 8t-30.5 8q-20 0 -37.5 -12.5t-17.5 -32.5q0 -21 19.5 -35.5t42.5 -20.5t42.5 -17t19.5 -26q0 -11 -7 -25q-64 -138 -198 -167q-22 -5 -22 -27q0 -47 138 -69q2 -5 6 -26t11 -30.5t23 -9.5q13 0 38.5 5t38.5 5q35 0 67.5 -15 t54.5 -32.5t57.5 -32.5t76.5 -15q43 0 79 15t57.5 32.5t54 32.5t67.5 15q13 0 39 -4.5t39 -4.5q15 0 22.5 9.5t11.5 31t5 24.5q138 22 138 69zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960 q119 0 203.5 -84.5t84.5 -203.5z" />
667
- <glyph unicode="&#xf2ae;" horiz-adv-x="1792" />
668
- <glyph unicode="&#xf2b0;" horiz-adv-x="1792" />
669
- <glyph unicode="&#xf2b1;" horiz-adv-x="1792" />
670
- <glyph unicode="&#xf2b2;" horiz-adv-x="1792" />
671
- <glyph unicode="&#xf2b3;" horiz-adv-x="1792" />
672
- <glyph unicode="&#xf2b4;" horiz-adv-x="1792" />
673
  <glyph unicode="&#xf2b5;" horiz-adv-x="1792" />
674
  <glyph unicode="&#xf2b6;" horiz-adv-x="1792" />
675
  <glyph unicode="&#xf2b7;" horiz-adv-x="1792" />
363
  <glyph unicode="&#xf16a;" horiz-adv-x="1792" d="M1280 640q0 37 -30 54l-512 320q-31 20 -65 2q-33 -18 -33 -56v-640q0 -38 33 -56q16 -8 31 -8q20 0 34 10l512 320q30 17 30 54zM1792 640q0 -96 -1 -150t-8.5 -136.5t-22.5 -147.5q-16 -73 -69 -123t-124 -58q-222 -25 -671 -25t-671 25q-71 8 -124.5 58t-69.5 123 q-14 65 -21.5 147.5t-8.5 136.5t-1 150t1 150t8.5 136.5t22.5 147.5q16 73 69 123t124 58q222 25 671 25t671 -25q71 -8 124.5 -58t69.5 -123q14 -65 21.5 -147.5t8.5 -136.5t1 -150z" />
364
  <glyph unicode="&#xf16b;" horiz-adv-x="1792" d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" />
365
  <glyph unicode="&#xf16c;" d="M1289 -96h-1118v480h-160v-640h1438v640h-160v-480zM347 428l33 157l783 -165l-33 -156zM450 802l67 146l725 -339l-67 -145zM651 1158l102 123l614 -513l-102 -123zM1048 1536l477 -641l-128 -96l-477 641zM330 65v159h800v-159h-800z" />
366
+ <glyph unicode="&#xf16d;" d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1162 640q0 -164 -115 -279t-279 -115t-279 115t-115 279t115 279t279 115t279 -115t115 -279zM1270 1050q0 -38 -27 -65t-65 -27t-65 27t-27 65t27 65t65 27t65 -27t27 -65zM768 1270 q-7 0 -76.5 0.5t-105.5 0t-96.5 -3t-103 -10t-71.5 -18.5q-50 -20 -88 -58t-58 -88q-11 -29 -18.5 -71.5t-10 -103t-3 -96.5t0 -105.5t0.5 -76.5t-0.5 -76.5t0 -105.5t3 -96.5t10 -103t18.5 -71.5q20 -50 58 -88t88 -58q29 -11 71.5 -18.5t103 -10t96.5 -3t105.5 0t76.5 0.5 t76.5 -0.5t105.5 0t96.5 3t103 10t71.5 18.5q50 20 88 58t58 88q11 29 18.5 71.5t10 103t3 96.5t0 105.5t-0.5 76.5t0.5 76.5t0 105.5t-3 96.5t-10 103t-18.5 71.5q-20 50 -58 88t-88 58q-29 11 -71.5 18.5t-103 10t-96.5 3t-105.5 0t-76.5 -0.5zM1536 640q0 -229 -5 -317 q-10 -208 -124 -322t-322 -124q-88 -5 -317 -5t-317 5q-208 10 -322 124t-124 322q-5 88 -5 317t5 317q10 208 124 322t322 124q88 5 317 5t317 -5q208 -10 322 -124t124 -322q5 -88 5 -317z" />
367
  <glyph unicode="&#xf16e;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150 t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" />
368
  <glyph unicode="&#xf170;" d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
369
  <glyph unicode="&#xf171;" horiz-adv-x="1408" d="M815 677q8 -63 -50.5 -101t-111.5 -6q-39 17 -53.5 58t-0.5 82t52 58q36 18 72.5 12t64 -35.5t27.5 -67.5zM926 698q-14 107 -113 164t-197 13q-63 -28 -100.5 -88.5t-34.5 -129.5q4 -91 77.5 -155t165.5 -56q91 8 152 84t50 168zM1165 1240q-20 27 -56 44.5t-58 22 t-71 12.5q-291 47 -566 -2q-43 -7 -66 -12t-55 -22t-50 -43q30 -28 76 -45.5t73.5 -22t87.5 -11.5q228 -29 448 -1q63 8 89.5 12t72.5 21.5t75 46.5zM1222 205q-8 -26 -15.5 -76.5t-14 -84t-28.5 -70t-58 -56.5q-86 -48 -189.5 -71.5t-202 -22t-201.5 18.5q-46 8 -81.5 18 t-76.5 27t-73 43.5t-52 61.5q-25 96 -57 292l6 16l18 9q223 -148 506.5 -148t507.5 148q21 -6 24 -23t-5 -45t-8 -37zM1403 1166q-26 -167 -111 -655q-5 -30 -27 -56t-43.5 -40t-54.5 -31q-252 -126 -610 -88q-248 27 -394 139q-15 12 -25.5 26.5t-17 35t-9 34t-6 39.5 t-5.5 35q-9 50 -26.5 150t-28 161.5t-23.5 147.5t-22 158q3 26 17.5 48.5t31.5 37.5t45 30t46 22.5t48 18.5q125 46 313 64q379 37 676 -50q155 -46 215 -122q16 -20 16.5 -51t-5.5 -54z" />
626
  <glyph unicode="&#xf283;" horiz-adv-x="2304" d="M0 32v608h2304v-608q0 -66 -47 -113t-113 -47h-1984q-66 0 -113 47t-47 113zM640 256v-128h384v128h-384zM256 256v-128h256v128h-256zM2144 1408q66 0 113 -47t47 -113v-224h-2304v224q0 66 47 113t113 47h1984z" />
627
  <glyph unicode="&#xf284;" horiz-adv-x="1792" d="M1549 857q55 0 85.5 -28.5t30.5 -83.5t-34 -82t-91 -27h-136v-177h-25v398h170zM1710 267l-4 -11l-5 -10q-113 -230 -330.5 -366t-474.5 -136q-182 0 -348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71q244 0 454.5 -124t329.5 -338l2 -4l8 -16 q-30 -15 -136.5 -68.5t-163.5 -84.5q-6 -3 -479 -268q384 -183 799 -366zM896 -234q250 0 462.5 132.5t322.5 357.5l-287 129q-72 -140 -206 -222t-292 -82q-151 0 -280 75t-204 204t-75 280t75 280t204 204t280 75t280 -73.5t204 -204.5l280 143q-116 208 -321 329 t-443 121q-119 0 -232.5 -31.5t-209 -87.5t-176.5 -137t-137 -176.5t-87.5 -209t-31.5 -232.5t31.5 -232.5t87.5 -209t137 -176.5t176.5 -137t209 -87.5t232.5 -31.5z" />
628
  <glyph unicode="&#xf285;" horiz-adv-x="1792" d="M1427 827l-614 386l92 151h855zM405 562l-184 116v858l1183 -743zM1424 697l147 -95v-858l-532 335zM1387 718l-500 -802h-855l356 571z" />
629
+ <glyph unicode="&#xf286;" horiz-adv-x="1792" d="M640 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1152 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1664 496v-752h-640v320q0 80 -56 136t-136 56t-136 -56t-56 -136v-320h-640v752q0 16 16 16h96 q16 0 16 -16v-112h128v624q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 6 2.5 9.5t8.5 5t9.5 2t11.5 0t9 -0.5v391q-32 15 -32 50q0 23 16.5 39t38.5 16t38.5 -16t16.5 -39q0 -35 -32 -50v-17q45 10 83 10q21 0 59.5 -7.5t54.5 -7.5 q17 0 47 7.5t37 7.5q16 0 16 -16v-210q0 -15 -35 -21.5t-62 -6.5q-18 0 -54.5 7.5t-55.5 7.5q-40 0 -90 -12v-133q1 0 9 0.5t11.5 0t9.5 -2t8.5 -5t2.5 -9.5v-112h128v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-624h128v112q0 16 16 16h96 q16 0 16 -16z" />
630
  <glyph unicode="&#xf287;" horiz-adv-x="2304" d="M2288 731q16 -8 16 -27t-16 -27l-320 -192q-8 -5 -16 -5q-9 0 -16 4q-16 10 -16 28v128h-858q37 -58 83 -165q16 -37 24.5 -55t24 -49t27 -47t27 -34t31.5 -26t33 -8h96v96q0 14 9 23t23 9h320q14 0 23 -9t9 -23v-320q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v96h-96 q-32 0 -61 10t-51 23.5t-45 40.5t-37 46t-33.5 57t-28.5 57.5t-28 60.5q-23 53 -37 81.5t-36 65t-44.5 53.5t-46.5 17h-360q-22 -84 -91 -138t-157 -54q-106 0 -181 75t-75 181t75 181t181 75q88 0 157 -54t91 -138h104q24 0 46.5 17t44.5 53.5t36 65t37 81.5q19 41 28 60.5 t28.5 57.5t33.5 57t37 46t45 40.5t51 23.5t61 10h107q21 57 70 92.5t111 35.5q80 0 136 -56t56 -136t-56 -136t-136 -56q-62 0 -111 35.5t-70 92.5h-107q-17 0 -33 -8t-31.5 -26t-27 -34t-27 -47t-24 -49t-24.5 -55q-46 -107 -83 -165h1114v128q0 18 16 28t32 -1z" />
631
  <glyph unicode="&#xf288;" horiz-adv-x="1792" d="M1150 774q0 -56 -39.5 -95t-95.5 -39h-253v269h253q56 0 95.5 -39.5t39.5 -95.5zM1329 774q0 130 -91.5 222t-222.5 92h-433v-896h180v269h253q130 0 222 91.5t92 221.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348 t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
632
  <glyph unicode="&#xf289;" horiz-adv-x="2304" d="M1645 438q0 59 -34 106.5t-87 68.5q-7 -45 -23 -92q-7 -24 -27.5 -38t-44.5 -14q-12 0 -24 3q-31 10 -45 38.5t-4 58.5q23 71 23 143q0 123 -61 227.5t-166 165.5t-228 61q-134 0 -247 -73t-167 -194q108 -28 188 -106q22 -23 22 -55t-22 -54t-54 -22t-55 22 q-75 75 -180 75q-106 0 -181 -74.5t-75 -180.5t75 -180.5t181 -74.5h1046q79 0 134.5 55.5t55.5 133.5zM1798 438q0 -142 -100.5 -242t-242.5 -100h-1046q-169 0 -289 119.5t-120 288.5q0 153 100 267t249 136q62 184 221 298t354 114q235 0 408.5 -158.5t196.5 -389.5 q116 -25 192.5 -118.5t76.5 -214.5zM2048 438q0 -175 -97 -319q-23 -33 -64 -33q-24 0 -43 13q-26 17 -32 48.5t12 57.5q71 104 71 233t-71 233q-18 26 -12 57t32 49t57.5 11.5t49.5 -32.5q97 -142 97 -318zM2304 438q0 -244 -134 -443q-23 -34 -64 -34q-23 0 -42 13 q-26 18 -32.5 49t11.5 57q108 164 108 358q0 195 -108 357q-18 26 -11.5 57.5t32.5 48.5q26 18 57 12t49 -33q134 -198 134 -442z" />
664
  <glyph unicode="&#xf2ab;" d="M1279 388q0 22 -22 27q-67 15 -118 59t-80 108q-7 19 -7 25q0 15 19.5 26t43 17t43 20.5t19.5 36.5q0 19 -18.5 31.5t-38.5 12.5q-12 0 -32 -8t-31 -8q-4 0 -12 2q5 95 5 114q0 79 -17 114q-36 78 -103 121.5t-152 43.5q-199 0 -275 -165q-17 -35 -17 -114q0 -19 5 -114 q-4 -2 -14 -2q-12 0 -32 7.5t-30 7.5q-21 0 -38.5 -12t-17.5 -32q0 -21 19.5 -35.5t43 -20.5t43 -17t19.5 -26q0 -6 -7 -25q-64 -138 -198 -167q-22 -5 -22 -27q0 -46 137 -68q2 -5 6 -26t11.5 -30.5t23.5 -9.5q12 0 37.5 4.5t39.5 4.5q35 0 67 -15t54 -32.5t57.5 -32.5 t76.5 -15q43 0 79 15t57.5 32.5t53.5 32.5t67 15q14 0 39.5 -4t38.5 -4q16 0 23 10t11 30t6 25q137 22 137 68zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" />
665
  <glyph unicode="&#xf2ac;" horiz-adv-x="1664" d="M848 1408q134 1 240.5 -68.5t163.5 -192.5q27 -58 27 -179q0 -47 -9 -191q14 -7 28 -7q18 0 51 13.5t51 13.5q29 0 56 -18t27 -46q0 -32 -31.5 -54t-69 -31.5t-69 -29t-31.5 -47.5q0 -15 12 -43q37 -82 102.5 -150t144.5 -101q28 -12 80 -23q28 -6 28 -35 q0 -70 -219 -103q-7 -11 -11 -39t-14 -46.5t-33 -18.5q-20 0 -62 6.5t-64 6.5q-37 0 -62 -5q-32 -5 -63 -22.5t-58 -38t-58 -40.5t-76 -33.5t-99 -13.5q-52 0 -96.5 13.5t-75 33.5t-57.5 40.5t-58 38t-62 22.5q-26 5 -63 5q-24 0 -65.5 -7.5t-58.5 -7.5q-25 0 -35 18.5 t-14 47.5t-11 40q-219 33 -219 103q0 29 28 35q52 11 80 23q78 32 144.5 101t102.5 150q12 28 12 43q0 28 -31.5 47.5t-69.5 29.5t-69.5 31.5t-31.5 52.5q0 27 26 45.5t55 18.5q15 0 48 -13t53 -13q18 0 32 7q-9 142 -9 190q0 122 27 180q64 137 172 198t264 63z" />
666
  <glyph unicode="&#xf2ad;" d="M1280 388q0 22 -22 27q-67 14 -118 58t-80 109q-7 14 -7 25q0 15 19.5 26t42.5 17t42.5 20.5t19.5 36.5q0 19 -18.5 31.5t-38.5 12.5q-11 0 -31 -8t-32 -8q-4 0 -12 2q5 63 5 115q0 78 -17 114q-36 78 -102.5 121.5t-152.5 43.5q-198 0 -275 -165q-18 -38 -18 -115 q0 -38 6 -114q-10 -2 -15 -2q-11 0 -31.5 8t-30.5 8q-20 0 -37.5 -12.5t-17.5 -32.5q0 -21 19.5 -35.5t42.5 -20.5t42.5 -17t19.5 -26q0 -11 -7 -25q-64 -138 -198 -167q-22 -5 -22 -27q0 -47 138 -69q2 -5 6 -26t11 -30.5t23 -9.5q13 0 38.5 5t38.5 5q35 0 67.5 -15 t54.5 -32.5t57.5 -32.5t76.5 -15q43 0 79 15t57.5 32.5t54 32.5t67.5 15q13 0 39 -4.5t39 -4.5q15 0 22.5 9.5t11.5 31t5 24.5q138 22 138 69zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960 q119 0 203.5 -84.5t84.5 -203.5z" />
667
+ <glyph unicode="&#xf2ae;" horiz-adv-x="2304" d="M2304 1536q-69 -46 -125 -92t-89 -81t-59.5 -71.5t-37.5 -57.5t-22 -44.5t-14 -29.5q-10 -18 -35.5 -136.5t-48.5 -164.5q-15 -29 -50 -60.5t-67.5 -50.5t-72.5 -41t-48 -28q-47 -31 -151 -231q-341 14 -630 -158q-92 -53 -303 -179q47 16 86 31t55 22l15 7 q71 27 163 64.5t133.5 53.5t108 34.5t142.5 31.5q186 31 465 -7q1 0 10 -3q11 -6 14 -17t-3 -22l-194 -345q-15 -29 -47 -22q-128 24 -354 24q-146 0 -402 -44.5t-392 -46.5q-82 -1 -149 13t-107 37t-61 40t-33 34l-1 1v2q0 6 6 6q138 0 371 55q192 366 374.5 524t383.5 158 q5 0 14.5 -0.5t38 -5t55 -12t61.5 -24.5t63 -39.5t54 -59t40 -82.5l102 177q2 4 21 42.5t44.5 86.5t61 109.5t84 133.5t100.5 137q66 82 128 141.5t121.5 96.5t92.5 53.5t88 39.5z" />
668
+ <glyph unicode="&#xf2b0;" d="M1322 640q0 -45 -5 -76l-236 14l224 -78q-19 -73 -58 -141l-214 103l177 -158q-44 -61 -107 -108l-157 178l103 -215q-61 -37 -140 -59l-79 228l14 -240q-38 -6 -76 -6t-76 6l14 238l-78 -226q-74 19 -140 59l103 215l-157 -178q-59 43 -108 108l178 158l-214 -104 q-39 69 -58 141l224 79l-237 -14q-5 42 -5 76q0 35 5 77l238 -14l-225 79q19 73 58 140l214 -104l-177 159q46 61 107 108l158 -178l-103 215q67 39 140 58l77 -224l-13 236q36 6 75 6q38 0 76 -6l-14 -237l78 225q74 -19 140 -59l-103 -214l158 178q61 -47 107 -108 l-177 -159l213 104q37 -62 58 -141l-224 -78l237 14q5 -31 5 -77zM1352 640q0 160 -78.5 295.5t-213 214t-292.5 78.5q-119 0 -227 -46.5t-186.5 -125t-124.5 -187.5t-46 -229q0 -119 46 -228t124.5 -187.5t186.5 -125t227 -46.5q158 0 292.5 78.5t213 214t78.5 294.5z M1425 1023v-766l-657 -383l-657 383v766l657 383zM768 -183l708 412v823l-708 411l-708 -411v-823zM1536 1088v-896l-768 -448l-768 448v896l768 448z" />
669
+ <glyph unicode="&#xf2b1;" horiz-adv-x="1664" d="M339 1318h691l-26 -72h-665q-110 0 -188.5 -79t-78.5 -189v-771q0 -95 60.5 -169.5t153.5 -93.5q23 -5 98 -5v-72h-45q-140 0 -239.5 100t-99.5 240v771q0 140 99.5 240t239.5 100zM1190 1536h247l-482 -1294q-23 -61 -40.5 -103.5t-45 -98t-54 -93.5t-64.5 -78.5 t-79.5 -65t-95.5 -41t-116 -18.5v195q163 26 220 182q20 52 20 105q0 54 -20 106l-285 733h228l187 -585zM1664 978v-1111h-795q37 55 45 73h678v1038q0 85 -49.5 155t-129.5 99l25 67q101 -34 163.5 -123.5t62.5 -197.5z" />
670
+ <glyph unicode="&#xf2b2;" horiz-adv-x="1792" d="M852 1227q0 -29 -17 -52.5t-45 -23.5t-45 23.5t-17 52.5t17 52.5t45 23.5t45 -23.5t17 -52.5zM688 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50 -21.5t-20 -51.5v-114q0 -30 20.5 -52t49.5 -22q30 0 50.5 22t20.5 52zM860 -149v114q0 30 -20 51.5t-50 21.5t-50.5 -21.5 t-20.5 -51.5v-114q0 -30 20.5 -52t50.5 -22q29 0 49.5 22t20.5 52zM1034 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50.5 -21.5t-20.5 -51.5v-114q0 -30 20.5 -52t50.5 -22t50.5 22t20.5 52zM1208 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50.5 -21.5t-20.5 -51.5v-114 q0 -30 20.5 -52t50.5 -22t50.5 22t20.5 52zM1476 535q-84 -160 -232 -259.5t-323 -99.5q-123 0 -229.5 51.5t-178.5 137t-113 197.5t-41 232q0 88 21 174q-104 -175 -104 -390q0 -162 65 -312t185 -251q30 57 91 57q56 0 86 -50q32 50 87 50q56 0 86 -50q32 50 87 50t87 -50 q30 50 86 50q28 0 52.5 -15.5t37.5 -40.5q112 94 177 231.5t73 287.5zM1326 564q0 75 -72 75q-17 0 -47 -6q-95 -19 -149 -19q-226 0 -226 243q0 86 30 204q-83 -127 -83 -275q0 -150 89 -260.5t235 -110.5q111 0 210 70q13 48 13 79zM884 1223q0 50 -32 89.5t-81 39.5 t-81 -39.5t-32 -89.5q0 -51 31.5 -90.5t81.5 -39.5t81.5 39.5t31.5 90.5zM1513 884q0 96 -37.5 179t-113 137t-173.5 54q-77 0 -149 -35t-127 -94q-48 -159 -48 -268q0 -104 45.5 -157t147.5 -53q53 0 142 19q36 6 53 6q51 0 77.5 -28t26.5 -80q0 -26 -4 -46 q75 68 117.5 165.5t42.5 200.5zM1792 667q0 -111 -33.5 -249.5t-93.5 -204.5q-58 -64 -195 -142.5t-228 -104.5l-4 -1v-114q0 -43 -29.5 -75t-72.5 -32q-56 0 -86 50q-32 -50 -87 -50t-87 50q-30 -50 -86 -50q-55 0 -87 50q-30 -50 -86 -50q-47 0 -75 33.5t-28 81.5 q-90 -68 -198 -68q-118 0 -211 80q54 1 106 20q-113 31 -182 127q32 -7 71 -7q89 0 164 46q-192 192 -240 306q-24 56 -24 160q0 57 9 125.5t31.5 146.5t55 141t86.5 105t120 42q59 0 81 -52q19 29 42 54q2 3 12 13t13 16q10 15 23 38t25 42t28 39q87 111 211.5 177 t260.5 66q35 0 62 -4q59 64 146 64q83 0 140 -57q5 -5 5 -12q0 -5 -6 -13.5t-12.5 -16t-16 -17l-10.5 -10.5q17 -6 36 -18t19 -24q0 -6 -16 -25q157 -138 197 -378q25 30 60 30q45 0 100 -49q90 -80 90 -279z" />
671
+ <glyph unicode="&#xf2b3;" d="M917 631q0 33 -6 64h-362v-132h217q-12 -76 -74.5 -120.5t-142.5 -44.5q-99 0 -169 71.5t-70 170.5t70 170.5t169 71.5q93 0 153 -59l104 101q-108 100 -257 100q-160 0 -272 -112.5t-112 -271.5t112 -271.5t272 -112.5q165 0 266.5 105t101.5 270zM1262 585h109v110 h-109v110h-110v-110h-110v-110h110v-110h110v110zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
672
+ <glyph unicode="&#xf2b4;" d="M1536 1024v-839q0 -48 -49 -62q-174 -52 -338 -52q-73 0 -215.5 29.5t-227.5 29.5q-164 0 -370 -48v-338h-160v1368q-63 25 -101 81t-38 124q0 91 64 155t155 64t155 -64t64 -155q0 -68 -38 -124t-101 -81v-68q190 44 343 44q99 0 198 -15q14 -2 111.5 -22.5t149.5 -20.5 q77 0 165 18q11 2 80 21t89 19q26 0 45 -19t19 -45z" />
673
  <glyph unicode="&#xf2b5;" horiz-adv-x="1792" />
674
  <glyph unicode="&#xf2b6;" horiz-adv-x="1792" />
675
  <glyph unicode="&#xf2b7;" horiz-adv-x="1792" />
framework/static/libs/font-awesome/fonts/fontawesome-webfont.ttf CHANGED
Binary file
framework/static/libs/font-awesome/fonts/fontawesome-webfont.woff CHANGED
Binary file
framework/static/libs/font-awesome/fonts/fontawesome-webfont.woff2 CHANGED
Binary file
framework/views/backend-settings-form.php CHANGED
@@ -192,6 +192,8 @@ $texts = apply_filters('fw_settings_form_texts', array(
192
  var formSelector = 'form[data-fw-form-id="fw_settings"]',
193
  loadingExtraMessage = $('#fw-settings-form-ajax-save-extra-message').attr('data-html');
194
 
 
 
195
  fwForm.initAjaxSubmit({
196
  selector: formSelector,
197
  loading: function(elements, show) {
@@ -224,10 +226,15 @@ $texts = apply_filters('fw_settings_form_texts', array(
224
  allowClose: false
225
  }
226
  );
 
 
227
  } else {
228
  // fw.soleModal.hide('fw-options-ajax-save-loading'); // we need to show loading until the form reset ajax will finish
229
  }
230
  },
 
 
 
231
  onErrors: function() {
232
  fw.soleModal.hide('fw-options-ajax-save-loading');
233
  },
192
  var formSelector = 'form[data-fw-form-id="fw_settings"]',
193
  loadingExtraMessage = $('#fw-settings-form-ajax-save-extra-message').attr('data-html');
194
 
195
+ $(formSelector).addClass('prevent-all-tabs-init'); // fixes https://github.com/ThemeFuse/Unyson/issues/1491
196
+
197
  fwForm.initAjaxSubmit({
198
  selector: formSelector,
199
  loading: function(elements, show) {
226
  allowClose: false
227
  }
228
  );
229
+
230
+ return 500; // fixes https://github.com/ThemeFuse/Unyson/issues/1491
231
  } else {
232
  // fw.soleModal.hide('fw-options-ajax-save-loading'); // we need to show loading until the form reset ajax will finish
233
  }
234
  },
235
+ afterSubmitDelay: function (elements) {
236
+ fwEvents.trigger('fw:options:init:tabs', {$elements: elements.$form});
237
+ },
238
  onErrors: function() {
239
  fw.soleModal.hide('fw-options-ajax-save-loading');
240
  },
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: unyson
3
  Tags: page builder, grid, layout, responsive, back up, backup, db backup, dump, migrate, schedule, search engine optimization, seo, media, slideshow, shortcode, slide, slideshare, slideshow, google sitemaps, sitemaps, analytics, google analytics, calendar, event, events, google maps, learning, lessons, sidebars, breadcrumbs, review, portfolio, framework
4
  Requires at least: 4.4
5
  Tested up to: 4.6
6
- Stable tag: 2.6.1
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -83,6 +83,11 @@ Yes; Unyson will work with any theme.
83
 
84
  == Changelog ==
85
 
 
 
 
 
 
86
  = 2.6.1 =
87
  * Hotfix in File Cache [#1968](https://github.com/ThemeFuse/Unyson/issues/1968)
88
 
3
  Tags: page builder, grid, layout, responsive, back up, backup, db backup, dump, migrate, schedule, search engine optimization, seo, media, slideshow, shortcode, slide, slideshare, slideshow, google sitemaps, sitemaps, analytics, google analytics, calendar, event, events, google maps, learning, lessons, sidebars, breadcrumbs, review, portfolio, framework
4
  Requires at least: 4.4
5
  Tested up to: 4.6
6
+ Stable tag: 2.6.2
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
83
 
84
  == Changelog ==
85
 
86
+ = 2.6.2 =
87
+ * Option-types must be loaded on `fw_option_types_init` [action](http://manual.unyson.io/en/latest/options/create-option-type.html?#create-option-type) [#1827](https://github.com/ThemeFuse/Unyson/issues/1827)
88
+ * Option-type `icon-v2` refactor
89
+ * Fixed [#1491](https://github.com/ThemeFuse/Unyson/issues/1491), [#1979](https://github.com/ThemeFuse/Unyson/issues/1979), [#1970](https://github.com/ThemeFuse/Unyson/issues/1970), [#1954](https://github.com/ThemeFuse/Unyson/issues/1954)
90
+
91
  = 2.6.1 =
92
  * Hotfix in File Cache [#1968](https://github.com/ThemeFuse/Unyson/issues/1968)
93
 
unyson.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Unyson
4
  * Plugin URI: http://unyson.io/
5
  * Description: A free drag & drop framework that comes with a bunch of built in extensions that will help you develop premium themes fast & easy.
6
- * Version: 2.6.1
7
  * Author: ThemeFuse
8
  * Author URI: http://themefuse.com
9
  * License: GPL2+
3
  * Plugin Name: Unyson
4
  * Plugin URI: http://unyson.io/
5
  * Description: A free drag & drop framework that comes with a bunch of built in extensions that will help you develop premium themes fast & easy.
6
+ * Version: 2.6.2
7
  * Author: ThemeFuse
8
  * Author URI: http://themefuse.com
9
  * License: GPL2+