Meta Box - Version 4.5.4

Version Description

  • Improvement: Add "Select All|None" for select, select_advanced, post fields
  • Improvement: Add max_clone parameter which limits number of clones
  • Improvement: Add sort_clone parameter which allows users to sort (drag and drop) cloned inputs
  • Improvement: Add Polish language. Thank Michael
  • Fix: Prevent warning when post type doesn't exist (post field)
Download this release

Release Info

Developer rilwis
Plugin Icon 128x128 Meta Box
Version 4.5.4
Comparing to
See all releases

Code changes from version 4.5.3 to 4.5.4

css/select-advanced.css CHANGED
@@ -1,4 +1,8 @@
1
  #post-body .rwmb-select-advanced {
2
  height: auto;
3
  min-width: 200px;
 
 
 
 
4
  }
1
  #post-body .rwmb-select-advanced {
2
  height: auto;
3
  min-width: 200px;
4
+ }
5
+
6
+ #post-body .rwmb-select-all {
7
+ margin-top: 5px;
8
  }
css/select.css CHANGED
@@ -1,4 +1,8 @@
1
  #post-body .rwmb-select {
2
  height: auto;
3
  min-width: 200px;
 
 
 
 
4
  }
1
  #post-body .rwmb-select {
2
  height: auto;
3
  min-width: 200px;
4
+ }
5
+
6
+ #post-body .rwmb-select-all {
7
+ margin-top: 5px;
8
  }
css/style.css CHANGED
@@ -36,6 +36,7 @@
36
  min-height: 24px;
37
  margin-bottom: 5px;
38
  position: relative;
 
39
  }
40
  .rwmb-clone > input[type='radio'],
41
  .rwmb-clone > input[type='checkbox'] {
@@ -49,6 +50,13 @@
49
  top: 0;
50
  right: 0;
51
  }
 
 
 
 
 
 
 
52
 
53
  /* Fix empty block below admin footer (issue #24) */
54
  #ui-datepicker-div {
@@ -74,4 +82,4 @@ select.error {
74
  #side-sortables .rwmb-label,
75
  #side-sortables .rwmb-input {
76
  width: 100%;
77
- }
36
  min-height: 24px;
37
  margin-bottom: 5px;
38
  position: relative;
39
+ clear: both;
40
  }
41
  .rwmb-clone > input[type='radio'],
42
  .rwmb-clone > input[type='checkbox'] {
50
  top: 0;
51
  right: 0;
52
  }
53
+ .rwmb-clone-icon {
54
+ cursor: move;
55
+ background: url(../img/drag_icon.gif) no-repeat;
56
+ height: 23px;
57
+ width: 15px;
58
+ float: left;
59
+ }
60
 
61
  /* Fix empty block below admin footer (issue #24) */
62
  #ui-datepicker-div {
82
  #side-sortables .rwmb-label,
83
  #side-sortables .rwmb-input {
84
  width: 100%;
85
+ }
img/drag_icon.gif ADDED
Binary file
inc/field.php CHANGED
@@ -87,6 +87,10 @@ if ( ! class_exists( 'RWMB_Field ' ) )
87
  // Wrap field HTML in a div with class="rwmb-clone" if needed
88
  $input_html = '<div class="rwmb-clone">';
89
 
 
 
 
 
90
  // Call separated methods for displaying each type of field
91
  $input_html .= call_user_func( array( $field_class, 'html' ), $sub_meta, $sub_field );
92
 
@@ -185,17 +189,28 @@ if ( ! class_exists( 'RWMB_Field ' ) )
185
  */
186
  static function begin_html( $meta, $field )
187
  {
188
- if ( empty( $field['name'] ) )
189
- return '<div class="rwmb-input">';
190
-
191
- return sprintf(
192
- '<div class="rwmb-label">
193
- <label for="%s">%s</label>
194
- </div>
195
- <div class="rwmb-input">',
196
- $field['id'],
197
- $field['name']
 
 
 
 
 
 
 
 
 
198
  );
 
 
199
  }
200
 
201
  /**
87
  // Wrap field HTML in a div with class="rwmb-clone" if needed
88
  $input_html = '<div class="rwmb-clone">';
89
 
90
+ // Drag clone icon
91
+ if ( $field['sort_clone'] )
92
+ $input_html .= "<a href='javascript:;' class='rwmb-clone-icon'></a>";
93
+
94
  // Call separated methods for displaying each type of field
95
  $input_html .= call_user_func( array( $field_class, 'html' ), $sub_meta, $sub_field );
96
 
189
  */
190
  static function begin_html( $meta, $field )
191
  {
192
+ $field_label = '';
193
+ if ( $field['name'] )
194
+ {
195
+ $field_label = sprintf(
196
+ '<div class="rwmb-label"><label for="%s">%s</label></div>',
197
+ $field['id'],
198
+ $field['name']
199
+ );
200
+ }
201
+
202
+ $data_max_clone = '';
203
+ if ( is_numeric( $field['max_clone'] ) && $field['max_clone'] > 1 )
204
+ {
205
+ $data_max_clone .= ' data-max-clone=' . $field['max_clone'];
206
+ }
207
+
208
+ $input_open = sprintf(
209
+ '<div class="rwmb-input"%s>',
210
+ $data_max_clone
211
  );
212
+
213
+ return $field_label . $input_open;
214
  }
215
 
216
  /**
inc/fields/post.php CHANGED
@@ -9,6 +9,17 @@ if ( ! class_exists( 'RWMB_Post_Field' ) )
9
  {
10
  class RWMB_Post_Field extends RWMB_Select_Advanced_Field
11
  {
 
 
 
 
 
 
 
 
 
 
 
12
  /**
13
  * Get field HTML
14
  *
@@ -54,7 +65,7 @@ if ( ! class_exists( 'RWMB_Post_Field' ) )
54
  if ( empty( $field['placeholder'] ) )
55
  {
56
  $label = __( 'Select a post', 'meta-box' );
57
- if ( is_string( $field['post_type'] ) )
58
  {
59
  $post_type_object = get_post_type_object( $field['post_type'] );
60
  $label = sprintf( __( 'Select a %s', 'meta-box' ), $post_type_object->labels->singular_name );
9
  {
10
  class RWMB_Post_Field extends RWMB_Select_Advanced_Field
11
  {
12
+ /**
13
+ * Enqueue scripts and styles
14
+ *
15
+ * @return void
16
+ */
17
+ static function admin_enqueue_scripts()
18
+ {
19
+ RWMB_Select_Field::admin_enqueue_scripts();
20
+ RWMB_Select_Advanced_Field::admin_enqueue_scripts();
21
+ }
22
+
23
  /**
24
  * Get field HTML
25
  *
65
  if ( empty( $field['placeholder'] ) )
66
  {
67
  $label = __( 'Select a post', 'meta-box' );
68
+ if ( is_string( $field['post_type'] ) && post_type_exists( $field['post_type'] ) )
69
  {
70
  $post_type_object = get_post_type_object( $field['post_type'] );
71
  $label = sprintf( __( 'Select a %s', 'meta-box' ), $post_type_object->labels->singular_name );
inc/fields/select-advanced.php CHANGED
@@ -46,6 +46,8 @@ if ( ! class_exists( 'RWMB_Select_Advanced_Field' ) )
46
 
47
  $html .= '</select>';
48
 
 
 
49
  return $html;
50
  }
51
 
46
 
47
  $html .= '</select>';
48
 
49
+ $html .= self::get_select_all_html( $field['multiple'] );
50
+
51
  return $html;
52
  }
53
 
inc/fields/select.php CHANGED
@@ -14,6 +14,7 @@ if ( ! class_exists( 'RWMB_Select_Field' ) )
14
  static function admin_enqueue_scripts()
15
  {
16
  wp_enqueue_style( 'rwmb-select', RWMB_CSS_URL . 'select.css', array(), RWMB_VER );
 
17
  }
18
 
19
  /**
@@ -38,6 +39,8 @@ if ( ! class_exists( 'RWMB_Select_Field' ) )
38
 
39
  $html .= '</select>';
40
 
 
 
41
  return $html;
42
  }
43
 
@@ -78,10 +81,7 @@ if ( ! class_exists( 'RWMB_Select_Field' ) )
78
  static function normalize_field( $field )
79
  {
80
  $field = wp_parse_args( $field, array(
81
- 'desc' => '',
82
- 'name' => $field['id'],
83
- 'size' => $field['multiple'] ? 5 : 0,
84
- 'placeholder' => '',
85
  ) );
86
  if ( ! $field['clone'] && $field['multiple'] )
87
  $field['field_name'] .= '[]';
@@ -191,5 +191,23 @@ if ( ! class_exists( 'RWMB_Select_Field' ) )
191
  {
192
  $value = $field['options'][$value];
193
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  }
195
  }
14
  static function admin_enqueue_scripts()
15
  {
16
  wp_enqueue_style( 'rwmb-select', RWMB_CSS_URL . 'select.css', array(), RWMB_VER );
17
+ wp_enqueue_script( 'rwmb-select', RWMB_JS_URL . 'select.js', array(), RWMB_VER, true );
18
  }
19
 
20
  /**
39
 
40
  $html .= '</select>';
41
 
42
+ $html .= self::get_select_all_html( $field['multiple'] );
43
+
44
  return $html;
45
  }
46
 
81
  static function normalize_field( $field )
82
  {
83
  $field = wp_parse_args( $field, array(
84
+ 'size' => $field['multiple'] ? 5 : 0,
 
 
 
85
  ) );
86
  if ( ! $field['clone'] && $field['multiple'] )
87
  $field['field_name'] .= '[]';
191
  {
192
  $value = $field['options'][$value];
193
  }
194
+
195
+ /**
196
+ * Get html for select all|none for multiple select
197
+ *
198
+ * @param $multiple
199
+ *
200
+ * @return string
201
+ */
202
+ static function get_select_all_html( $multiple )
203
+ {
204
+ if ( $multiple === true )
205
+ {
206
+ return '<div class="rwmb-select-all-none">
207
+ ' . __( 'Select', 'meta-box' ) . ': <a data-type="all" href="#">' . __( 'All', 'meta-box' ) . '</a> | <a data-type="none" href="#">' . __( 'None', 'meta-box' ) . '</a>
208
+ </div>';
209
+ }
210
+ return '';
211
+ }
212
  }
213
  }
inc/fields/wysiwyg.php CHANGED
@@ -114,7 +114,7 @@ if ( ! class_exists( 'RWMB_Wysiwyg_Field' ) )
114
 
115
  static function footer_scripts()
116
  {
117
- echo '<script> var rwmb_cloneable_editors = ' . wp_json_encode( self::$cloneable_editors ) . ';</script>';
118
  }
119
  }
120
  }
114
 
115
  static function footer_scripts()
116
  {
117
+ echo '<script> var rwmb_cloneable_editors = ' , wp_json_encode( self::$cloneable_editors ) , ';</script>';
118
  }
119
  }
120
  }
inc/meta-box.php CHANGED
@@ -241,13 +241,13 @@ if ( ! class_exists( 'RW_Meta_Box' ) )
241
  if ( typeof rwmb == "undefined" )
242
  {
243
  var rwmb = {
244
- validationOptions : jQuery.parseJSON( \'' . json_encode( $this->validation ) . '\' ),
245
- summaryMessage : "' . esc_js( __( 'Please correct the errors highlighted below and try again.', 'meta-box' ) ) . '"
246
  };
247
  }
248
  else
249
  {
250
- var tempOptions = jQuery.parseJSON( \'' . json_encode( $this->validation ) . '\' );
251
  jQuery.extend( true, rwmb.validationOptions, tempOptions );
252
  }
253
  </script>
@@ -387,8 +387,8 @@ if ( ! class_exists( 'RW_Meta_Box' ) )
387
  {
388
  $field = wp_parse_args( $field, array(
389
  'id' => '',
 
390
  'multiple' => false,
391
- 'clone' => false,
392
  'std' => '',
393
  'desc' => '',
394
  'format' => '',
@@ -397,6 +397,10 @@ if ( ! class_exists( 'RW_Meta_Box' ) )
397
  'field_name' => isset( $field['id'] ) ? $field['id'] : '',
398
  'required' => false,
399
  'placeholder' => '',
 
 
 
 
400
  ) );
401
 
402
  $class = self::get_class_name( $field );
241
  if ( typeof rwmb == "undefined" )
242
  {
243
  var rwmb = {
244
+ validationOptions : jQuery.parseJSON( \'' , json_encode( $this->validation ) , '\' ),
245
+ summaryMessage : "' , esc_js( __( 'Please correct the errors highlighted below and try again.', 'meta-box' ) ) , '"
246
  };
247
  }
248
  else
249
  {
250
+ var tempOptions = jQuery.parseJSON( \'' , json_encode( $this->validation ) . '\' );
251
  jQuery.extend( true, rwmb.validationOptions, tempOptions );
252
  }
253
  </script>
387
  {
388
  $field = wp_parse_args( $field, array(
389
  'id' => '',
390
+ 'name' => '',
391
  'multiple' => false,
 
392
  'std' => '',
393
  'desc' => '',
394
  'format' => '',
397
  'field_name' => isset( $field['id'] ) ? $field['id'] : '',
398
  'required' => false,
399
  'placeholder' => '',
400
+
401
+ 'clone' => false,
402
+ 'max_clone' => 0,
403
+ 'sort_clone' => false,
404
  ) );
405
 
406
  $class = self::get_class_name( $field );
js/clone.js CHANGED
@@ -119,6 +119,30 @@ jQuery( function ( $ )
119
  } );
120
  }
121
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  /**
123
  * Clone WYSIWYG field
124
  * @param $container
@@ -214,7 +238,6 @@ jQuery( function ( $ )
214
 
215
  }
216
 
217
-
218
  // Add more clones
219
  $( '#poststuff' ).on( 'click', '.add-clone', function ( e )
220
  {
@@ -232,27 +255,31 @@ jQuery( function ( $ )
232
  }
233
 
234
  toggleRemoveButtons( $input );
235
- } );
236
-
237
  // Remove clones
238
- $( '.rwmb-input' ).on( 'click', '.remove-clone', function ( e )
239
  {
240
  e.preventDefault();
241
 
242
  var $this = $( this ),
243
  $input = $this.closest( '.rwmb-input' );
244
 
245
- // Remove clone only if there're 2 or more of them
246
- if ( $input.find( '.rwmb-clone' ).length <= 1 )
247
  {
248
  return;
249
  }
250
 
251
  $this.parent().remove();
252
 
253
- // Toggle remove buttons
254
  toggleRemoveButtons( $input );
 
255
  } );
256
 
257
  toggleRemoveButtons();
 
 
 
 
258
  } );
119
  } );
120
  }
121
 
122
+ /**
123
+ * Toggle add button
124
+ * Used with [data-max-clone] attribute. When max clone is reached, the add button is hid and vice versa
125
+ *
126
+ * @param $input jQuery element of input div
127
+ *
128
+ * @return void
129
+ */
130
+ function toggleAddButton( $input )
131
+ {
132
+ var $button = $input.find( '.add-clone' ),
133
+ maxClone = parseInt( $input.data( 'max-clone' ) ),
134
+ numClone = $input.find( '.rwmb-clone' ).length;
135
+
136
+ if ( numClone == maxClone )
137
+ {
138
+ $button.hide();
139
+ }
140
+ else
141
+ {
142
+ $button.show();
143
+ }
144
+ }
145
+
146
  /**
147
  * Clone WYSIWYG field
148
  * @param $container
238
 
239
  }
240
 
 
241
  // Add more clones
242
  $( '#poststuff' ).on( 'click', '.add-clone', function ( e )
243
  {
255
  }
256
 
257
  toggleRemoveButtons( $input );
258
+ toggleAddButton( $input );
259
+ } )
260
  // Remove clones
261
+ .on( 'click', '.remove-clone', function ( e )
262
  {
263
  e.preventDefault();
264
 
265
  var $this = $( this ),
266
  $input = $this.closest( '.rwmb-input' );
267
 
268
+ // Remove clone only if there are 2 or more of them
269
+ if ( $input.find( '.rwmb-clone' ).length < 2 )
270
  {
271
  return;
272
  }
273
 
274
  $this.parent().remove();
275
 
 
276
  toggleRemoveButtons( $input );
277
+ toggleAddButton( $input )
278
  } );
279
 
280
  toggleRemoveButtons();
281
+
282
+ $( '.rwmb-input' ).sortable( {
283
+ handle: '.rwmb-clone-icon'
284
+ } );
285
  } );
js/select-advanced.js CHANGED
@@ -14,6 +14,8 @@ jQuery( function ( $ )
14
  options = $this.data( 'options' );
15
  $this.siblings( '.select2-container' ).remove();
16
  $this.show().select2( options );
 
 
17
  }
18
 
19
  $( ':input.rwmb-select-advanced' ).each( update );
14
  options = $this.data( 'options' );
15
  $this.siblings( '.select2-container' ).remove();
16
  $this.show().select2( options );
17
+
18
+ rwmbSelect.bindEvents( $this );
19
  }
20
 
21
  $( ':input.rwmb-select-advanced' ).each( update );
js/select.js ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery( function ( $ )
2
+ {
3
+ 'use strict';
4
+
5
+ /**
6
+ * Object stores all necessary methods for select All/None actions
7
+ * Assign to global variable so we can access to this object from select advanced field
8
+ */
9
+ var select = window.rwmbSelect = {
10
+ /**
11
+ * Select all/none for select tag
12
+ *
13
+ * @param $input jQuery selector for input wrapper
14
+ *
15
+ * @return void
16
+ */
17
+ selectAllNone: function ( $input )
18
+ {
19
+ var $element = $input.find( 'select' );
20
+
21
+ $input.on( 'click', '.rwmb-select-all-none a', function ( e )
22
+ {
23
+ e.preventDefault();
24
+ if ( 'all' == $( this ).data( 'type' ) )
25
+ {
26
+ var selected = [];
27
+ $element.find( 'option' ).each( function ( i, e )
28
+ {
29
+ var $value = $( e ).attr( 'value' );
30
+
31
+ if ( $value != '' )
32
+ {
33
+ selected.push( $value );
34
+ }
35
+ } );
36
+ $element.val( selected ).trigger( 'change' );
37
+ }
38
+ else
39
+ {
40
+ $element.val( '' );
41
+ }
42
+ } );
43
+ },
44
+
45
+ /**
46
+ * Add event listener for select all/none links when click
47
+ *
48
+ * @param $el jQuery element
49
+ *
50
+ * @return void
51
+ */
52
+ bindEvents: function ( $el )
53
+ {
54
+ var $input = $el.closest( '.rwmb-input' ),
55
+ $clone = $input.find( '.rwmb-clone' );
56
+
57
+ if ( $clone.length )
58
+ {
59
+ $clone.each( function ()
60
+ {
61
+ select.selectAllNone( $( this ) );
62
+ } );
63
+ }
64
+ else
65
+ {
66
+ select.selectAllNone( $input );
67
+ }
68
+ }
69
+ };
70
+
71
+ /**
72
+ * Update select field when clicking clone button
73
+ *
74
+ * @return void
75
+ */
76
+ function update()
77
+ {
78
+ select.bindEvents( $( this ) );
79
+ }
80
+
81
+ // Run for select field
82
+ $( ':input.rwmb-select' ).each( update );
83
+ $( '.rwmb-input' ).on( 'clone', ':input.rwmb-select', update );
84
+ } );
lang/pl_PL.mo ADDED
Binary file
meta-box.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Meta Box
4
  Plugin URI: http://metabox.io
5
  Description: Create meta box for editing pages in WordPress. Compatible with custom post types since WP 3.0
6
- Version: 4.5.3
7
  Author: Rilwis
8
  Author URI: http://www.deluxeblogtips.com
9
  License: GPL2+
@@ -13,7 +13,7 @@ License: GPL2+
13
  defined( 'ABSPATH' ) || exit;
14
 
15
  // Script version, used to add version for scripts and styles
16
- define( 'RWMB_VER', '4.5.3' );
17
 
18
  // Define plugin URLs, for fast enqueuing scripts and styles
19
  if ( ! defined( 'RWMB_URL' ) )
3
  Plugin Name: Meta Box
4
  Plugin URI: http://metabox.io
5
  Description: Create meta box for editing pages in WordPress. Compatible with custom post types since WP 3.0
6
+ Version: 4.5.4
7
  Author: Rilwis
8
  Author URI: http://www.deluxeblogtips.com
9
  License: GPL2+
13
  defined( 'ABSPATH' ) || exit;
14
 
15
  // Script version, used to add version for scripts and styles
16
+ define( 'RWMB_VER', '4.5.4' );
17
 
18
  // Define plugin URLs, for fast enqueuing scripts and styles
19
  if ( ! defined( 'RWMB_URL' ) )
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: http://www.deluxeblogtips.com/donate
4
  Tags: meta-box, custom-fields, custom-field, meta, meta-boxes
5
  Requires at least: 3.5
6
  Tested up to: 4.2.2
7
- Stable tag: 4.5.3
8
  License: GPLv2 or later
9
 
10
  Meta Box plugin is a complete tool to create meta box and custom fields in WordPress: lightweight, powerful and easy-to-use.
@@ -69,6 +69,13 @@ To getting started with the plugin API, please read [this tutorial](http://metab
69
 
70
  == Changelog ==
71
 
 
 
 
 
 
 
 
72
  = 4.5.3 =
73
  * Improvement: Use `wp_json_encode` instead of `json_encode`. Thank Sam Ford.
74
  * Fix: Escape value for cloneable fields
4
  Tags: meta-box, custom-fields, custom-field, meta, meta-boxes
5
  Requires at least: 3.5
6
  Tested up to: 4.2.2
7
+ Stable tag: 4.5.4
8
  License: GPLv2 or later
9
 
10
  Meta Box plugin is a complete tool to create meta box and custom fields in WordPress: lightweight, powerful and easy-to-use.
69
 
70
  == Changelog ==
71
 
72
+ = 4.5.4 =
73
+ * Improvement: Add "Select All|None" for `select`, `select_advanced`, `post` fields
74
+ * Improvement: Add `max_clone` parameter which limits number of clones
75
+ * Improvement: Add `sort_clone` parameter which allows users to sort (drag and drop) cloned inputs
76
+ * Improvement: Add Polish language. Thank Michael
77
+ * Fix: Prevent warning when post type doesn't exist (`post` field)
78
+
79
  = 4.5.3 =
80
  * Improvement: Use `wp_json_encode` instead of `json_encode`. Thank Sam Ford.
81
  * Fix: Escape value for cloneable fields