Meta Box - Version 4.8.4

Version Description

  • Improvement: Refactor code for plupload_image. Introduces file_upload and image_upload field which acts the same as plupload_image but for files and images.
  • Improvement: Do not show "Embed is not available" if fields don't have any value
  • Improvement: Refactor date/time related fields. 'timestamp' now works for date field as well.
  • Improvement: Add 'inline' mode for date/datetime fields.
  • Improvement: Add option 'select_all_none' for select/select2 with default
Download this release

Release Info

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

Code changes from version 4.8.3 to 4.8.4

Files changed (51) hide show
  1. css/datepicker.css +15 -0
  2. css/image-advanced.css +43 -0
  3. css/input-list.css +7 -0
  4. css/media.css +0 -44
  5. css/{object-choice.css → select-tree.css} +1 -9
  6. css/style.css +0 -5
  7. css/upload.css +31 -0
  8. inc/fields/checkbox-list.php +3 -47
  9. inc/fields/choice.php +170 -0
  10. inc/fields/date.php +10 -81
  11. inc/fields/datetime.php +99 -40
  12. inc/fields/file-advanced.php +1 -0
  13. inc/fields/file-upload.php +39 -0
  14. inc/fields/image-advanced.php +33 -0
  15. inc/fields/image-upload.php +30 -0
  16. inc/fields/input-list.php +91 -0
  17. inc/fields/media.php +33 -92
  18. inc/fields/object-choice.php +27 -121
  19. inc/fields/oembed.php +29 -9
  20. inc/fields/plupload-image.php +1 -158
  21. inc/fields/post.php +22 -25
  22. inc/fields/radio.php +6 -56
  23. inc/fields/select-advanced.php +18 -12
  24. inc/fields/select-tree.php +63 -0
  25. inc/fields/select.php +26 -124
  26. inc/fields/taxonomy.php +6 -24
  27. inc/fields/thickbox-image.php +27 -7
  28. inc/fields/time.php +8 -74
  29. inc/fields/user.php +6 -11
  30. inc/functions.php +4 -6
  31. inc/helper.php +23 -9
  32. inc/loader.php +15 -21
  33. inc/meta-box.php +4 -6
  34. inc/templates/image-advanced.php +31 -0
  35. inc/templates/media.php +47 -0
  36. inc/templates/upload.php +7 -0
  37. inc/walkers/{choice-list-walker.php → input-list-walker.php} +3 -3
  38. js/clone.js +1 -1
  39. js/date.js +40 -3
  40. js/datetime.js +39 -3
  41. js/file-upload.js +199 -0
  42. js/image-advanced.js +36 -0
  43. js/image-upload.js +31 -0
  44. js/input-list.js +25 -0
  45. js/media.js +55 -55
  46. js/object-choice.js +0 -45
  47. js/plupload-image.js +0 -139
  48. js/select-tree.js +22 -0
  49. js/time.js +18 -2
  50. meta-box.php +1 -1
  51. readme.txt +19 -2
css/datepicker.css CHANGED
@@ -1,3 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  /* Date Picker Default Styles */
2
  .ui-datepicker {
3
  padding: 0;
1
+ /* Fix empty block below admin footer (issue #24) */
2
+ #ui-datepicker-div {
3
+ display: none;
4
+ z-index: 9 !important;
5
+ }
6
+
7
+ /* Style for multiple months */
8
+ .ui-datepicker-multi .ui-datepicker-group {
9
+ padding: 0 .5%;
10
+ box-sizing: border-box;
11
+ }
12
+ .ui-datepicker-multi .ui-datepicker-group .ui-datepicker-calendar {
13
+ width: 100%;
14
+ }
15
+
16
  /* Date Picker Default Styles */
17
  .ui-datepicker {
18
  padding: 0;
css/image-advanced.css ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Image */
2
+ .rwmb-image-item {
3
+ position: relative;
4
+ float: left;
5
+ padding: 0;
6
+ margin: 0 5px 5px 0;
7
+ box-sizing: border-box;
8
+ width: 150px;
9
+ }
10
+ .rwmb-image-item .rwmb-media-preview {
11
+ width: 150px;
12
+ }
13
+ .rwmb-image-item .dashicons {
14
+ font-size: 20px;
15
+ width: 20px;
16
+ height: 20px;
17
+ }
18
+ .rwmb-media-bar {
19
+ position: absolute;
20
+ z-index: 10;
21
+ display: none;
22
+ right: 5px;
23
+ top: 5px;
24
+ color: #fff;
25
+ }
26
+ .rwmb-media-bar a {
27
+ text-decoration: none;
28
+ color: inherit;
29
+ }
30
+ .rwmb-overlay {
31
+ position: absolute;
32
+ top: 0;
33
+ bottom: 0;
34
+ left: 0;
35
+ right: 0;
36
+ background: rgba(0, 0, 0, .6);
37
+ display: none;
38
+ }
39
+ .rwmb-image-item:hover .rwmb-media-bar,
40
+ .rwmb-image-item:hover .rwmb-overlay {
41
+ display: block;
42
+ cursor: move;
43
+ }
css/input-list.css ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ .rwmb-input-list li{
2
+ line-height: 22px;
3
+ }
4
+
5
+ li .rwmb-input-list {
6
+ margin-left: 15px;
7
+ }
css/media.css CHANGED
@@ -79,47 +79,3 @@
79
  line-height: 26px;
80
  height: 28px;
81
  }
82
-
83
- /* Image */
84
- .rwmb-image-item {
85
- position: relative;
86
- float: left;
87
- padding: 0;
88
- margin: 0 5px 5px 0;
89
- box-sizing: border-box;
90
- width: 150px;
91
- }
92
- .rwmb-image-item .rwmb-media-preview {
93
- width: 150px;
94
- }
95
- .rwmb-image-item .dashicons {
96
- font-size: 20px;
97
- width: 20px;
98
- height: 20px;
99
- }
100
- .rwmb-media-bar {
101
- position: absolute;
102
- z-index: 10;
103
- display: none;
104
- right: 5px;
105
- top: 5px;
106
- color: #fff;
107
- }
108
- .rwmb-media-bar a {
109
- text-decoration: none;
110
- color: inherit;
111
- }
112
- .rwmb-overlay {
113
- position: absolute;
114
- top: 0;
115
- bottom: 0;
116
- left: 0;
117
- right: 0;
118
- background: rgba(0, 0, 0, .6);
119
- display: none;
120
- }
121
- .rwmb-image-item:hover .rwmb-media-bar,
122
- .rwmb-image-item:hover .rwmb-overlay {
123
- display: block;
124
- cursor: move;
125
- }
79
  line-height: 26px;
80
  height: 28px;
81
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
css/{object-choice.css → select-tree.css} RENAMED
@@ -1,15 +1,7 @@
1
- .rwmb-choice-list li{
2
- line-height: 22px;
3
- }
4
-
5
- li .rwmb-choice-list {
6
- margin-left: 15px;
7
- }
8
-
9
  .rwmb-select-tree {
10
  display: inline-block;
11
  }
12
 
13
  .rwmb-select-tree.hidden {
14
  display: none;
15
- }
 
 
 
 
 
 
 
 
1
  .rwmb-select-tree {
2
  display: inline-block;
3
  }
4
 
5
  .rwmb-select-tree.hidden {
6
  display: none;
7
+ }
css/style.css CHANGED
@@ -91,11 +91,6 @@
91
  padding-left: 15px;
92
  }
93
 
94
- /* Fix empty block below admin footer (issue #24) */
95
- #ui-datepicker-div {
96
- display: none;
97
- }
98
-
99
  /* jQuery validation */
100
  label.error {
101
  padding-left: 3px;
91
  padding-left: 15px;
92
  }
93
 
 
 
 
 
 
94
  /* jQuery validation */
95
  label.error {
96
  padding-left: 3px;
css/upload.css ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .rwmb-upload-area {
2
+ position: relative;
3
+ padding-top: 0;
4
+ margin-top: 0;
5
+ height: 200px;
6
+ border: 4px dashed #ddd;
7
+ }
8
+
9
+ .rwmb-upload-inside {
10
+ text-align: center;
11
+ position: absolute;
12
+ left: 0;
13
+ right:0;
14
+ top: 50%;
15
+ transform: translateY(-50%);
16
+ -webkit-transform: translateY(-50%);
17
+ -moz-transform: translateY(-50%);
18
+ -ms-transform: translateY(-50%);
19
+ margin-top:
20
+ }
21
+
22
+ .rwmb-upload-inside p, .rwmb-upload-inside h3 {
23
+ text-align: center;
24
+ }
25
+
26
+ .rwmb-upload-inside h3 {
27
+ font-size: 20px;
28
+ line-height: 28px;
29
+ font-weight: 400;
30
+ margin: 0;
31
+ }
inc/fields/checkbox-list.php CHANGED
@@ -2,36 +2,8 @@
2
  /**
3
  * Checkbox list field class.
4
  */
5
- class RWMB_Checkbox_List_Field extends RWMB_Multiple_Values_Field
6
  {
7
- /**
8
- * Get field HTML
9
- *
10
- * @param mixed $meta
11
- * @param array $field
12
- *
13
- * @return string
14
- */
15
- static function html( $meta, $field )
16
- {
17
- $meta = (array) $meta;
18
- $html = array();
19
- $tpl = '<label><input %s %s> %s</label>';
20
-
21
- foreach ( $field['options'] as $value => $label )
22
- {
23
- $attributes = self::get_attributes( $field, $value );
24
- $html[] = sprintf(
25
- $tpl,
26
- self::render_attributes( $attributes ),
27
- checked( in_array( (string) $value, $meta, true ), 1, false ),
28
- $label
29
- );
30
- }
31
-
32
- return implode( '<br>', $html );
33
- }
34
-
35
  /**
36
  * Normalize parameters for field
37
  * @param array $field
@@ -39,25 +11,9 @@ class RWMB_Checkbox_List_Field extends RWMB_Multiple_Values_Field
39
  */
40
  static function normalize( $field )
41
  {
42
- $field = parent::normalize( $field );
43
- $field = RWMB_Checkbox_Field::normalize( $field );
44
 
45
  return $field;
46
  }
47
-
48
- /**
49
- * Get the attributes for field
50
- *
51
- * @param array $field
52
- * @param mixed $value
53
- *
54
- * @return array
55
- */
56
- static function get_attributes( $field, $value = null )
57
- {
58
- $attributes = RWMB_Checkbox_Field::get_attributes( $field, $value );
59
- $attributes['id'] = false;
60
-
61
- return $attributes;
62
- }
63
  }
2
  /**
3
  * Checkbox list field class.
4
  */
5
+ class RWMB_Checkbox_List_Field extends RWMB_Input_List_Field
6
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  /**
8
  * Normalize parameters for field
9
  * @param array $field
11
  */
12
  static function normalize( $field )
13
  {
14
+ $field['multiple'] = true;
15
+ $field = parent::normalize( $field );
16
 
17
  return $field;
18
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  }
inc/fields/choice.php ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ abstract class RWMB_Choice_Field extends RWMB_Field
4
+ {
5
+ /**
6
+ * Walk options
7
+ *
8
+ * @param mixed $meta
9
+ * @param array $field
10
+ * @param mixed $options
11
+ * @param mixed $db_fields
12
+ *
13
+ * @return string
14
+ */
15
+ static function walk( $options, $db_fields, $meta, $field )
16
+ {
17
+ return '';
18
+ }
19
+
20
+ /**
21
+ * Get field HTML
22
+ *
23
+ * @param mixed $meta
24
+ * @param array $field
25
+ *
26
+ * @return string
27
+ */
28
+ static function html( $meta, $field )
29
+ {
30
+ $field_class = RW_Meta_Box::get_class_name( $field );
31
+ $meta = (array) $meta;
32
+ $options = call_user_func( array( $field_class, 'get_options' ), $field );
33
+ $db_fields = call_user_func( array( $field_class, 'get_db_fields' ), $field );
34
+
35
+ return call_user_func( array( $field_class, 'walk' ), $options, $db_fields, $meta, $field );
36
+ }
37
+
38
+ /**
39
+ * Normalize parameters for field
40
+ *
41
+ * @param array $field
42
+ *
43
+ * @return array
44
+ */
45
+ static function normalize( $field )
46
+ {
47
+ $field = parent::normalize( $field );
48
+ $field = wp_parse_args( $field, array(
49
+ 'flatten' => true,
50
+ 'options' => array(),
51
+ ) );
52
+
53
+ $options = array();
54
+ foreach( (array) $field['options'] as $value => $label )
55
+ {
56
+ $option = is_array( $label ) ? $label : array( 'label' => (string) $label, 'value' => (string) $value );
57
+ if( isset( $option['label'] ) && isset( $option['value'] ) )
58
+ $options[ $option['value'] ] = $option;
59
+ }
60
+
61
+ $field['options'] = $options;
62
+
63
+ return $field;
64
+ }
65
+
66
+ /**
67
+ * Get field names of object to be used by walker
68
+ *
69
+ * @return array
70
+ */
71
+ static function get_db_fields()
72
+ {
73
+ return array(
74
+ 'parent' => 'parent',
75
+ 'id' => 'value',
76
+ 'label' => 'label',
77
+ );
78
+ }
79
+
80
+ /**
81
+ * Get options for walker
82
+ *
83
+ * @param array $field
84
+ *
85
+ * @return array
86
+ */
87
+ static function get_options( $field )
88
+ {
89
+ $options = array();
90
+ foreach( $field['options'] as $option )
91
+ {
92
+ $options[] = (object) $option;
93
+ }
94
+ return $options;
95
+ }
96
+
97
+ /**
98
+ * Output the field value
99
+ * Display unordered list of option labels, not option values
100
+ *
101
+ * @param array $field Field parameters
102
+ * @param array $args Additional arguments. Not used for these fields.
103
+ * @param int|null $post_id Post ID. null for current post. Optional.
104
+ *
105
+ * @return string Link(s) to post
106
+ */
107
+ static function the_value( $field, $args = array(), $post_id = null )
108
+ {
109
+ $field_class = RW_Meta_Box::get_class_name( $field );
110
+ $value = call_user_func( array( $field_class, 'get_value' ), $field, $args, $post_id );
111
+
112
+ if ( ! $value )
113
+ return '';
114
+
115
+ if ( $field['clone'] && $field['multiple'] )
116
+ {
117
+ $output = '<ul>';
118
+ foreach ( $value as $subvalue )
119
+ {
120
+ $output .= '<li>';
121
+ $output .= call_user_func( array( $field_class, 'list_option_labels' ), $subvalue, $field );
122
+ $output .= '</li>';
123
+ }
124
+ $output .= '</ul>';
125
+ }
126
+ elseif ( $field['clone'] || $field['multiple'] )
127
+ {
128
+ $output = call_user_func( array( $field_class, 'list_option_labels' ), $value, $field );
129
+ }
130
+ else
131
+ {
132
+ $output = $field['options'][$value]['label'];
133
+ }
134
+ return $output;
135
+ }
136
+
137
+ /**
138
+ * List option labels
139
+ *
140
+ * @param string $value Option value
141
+ * @param array $field Field parameter
142
+ *
143
+ * @return string
144
+ */
145
+ static function list_option_labels( $meta, $field )
146
+ {
147
+ $field_class = RW_Meta_Box::get_class_name( $field );
148
+ $output = '<ul>';
149
+ foreach( $meta as $m )
150
+ {
151
+ $output .= sprintf( '<li>%s</li>', call_user_func( array( $field_class, 'get_option_label' ), $m, $field ) );
152
+ }
153
+
154
+ return $output . '</ul>';
155
+ }
156
+
157
+ /**
158
+ * Get option label
159
+ *
160
+ * @param string $value Option value
161
+ * @param array $field Field parameter
162
+ *
163
+ * @return string
164
+ */
165
+ static function get_option_label( $meta, $field )
166
+ {
167
+ return $field['options'][$meta]['label'];
168
+ }
169
+
170
+ }
inc/fields/date.php CHANGED
@@ -2,101 +2,30 @@
2
  /**
3
  * Date field class.
4
  */
5
- class RWMB_Date_Field extends RWMB_Text_Field
6
  {
7
- /**
8
- * Get field HTML
9
- *
10
- * @param mixed $meta
11
- * @param array $field
12
- *
13
- * @return string
14
- */
15
- static function html( $meta, $field )
16
- {
17
- $output = parent::html( $meta, $field );
18
- if( $field['inline'] )
19
- {
20
- $output .= '<div class="rwmb-date-inline"></div>';
21
- }
22
- return $output;
23
- }
24
-
25
  /**
26
  * Enqueue scripts and styles
27
  *
28
  * @return void
29
  */
30
- static function admin_enqueue_scripts()
31
  {
32
- $url = RWMB_CSS_URL . 'jqueryui';
33
- wp_register_style( 'jquery-ui-core', "{$url}/jquery.ui.core.css", array(), '1.8.17' );
34
- wp_register_style( 'jquery-ui-theme', "{$url}/jquery.ui.theme.css", array(), '1.8.17' );
35
- wp_register_style( 'wp-datepicker', RWMB_CSS_URL . 'datepicker.css', array( 'jquery-ui-core', 'jquery-ui-theme' ), '1.8.17' );
36
- wp_enqueue_style( 'jquery-ui-datepicker', "{$url}/jquery.ui.datepicker.css", array( 'wp-datepicker' ), '1.8.17' );
37
-
38
- // Load localized scripts
39
- $locale = str_replace( '_', '-', get_locale() );
40
- $file_paths = array( 'jqueryui/datepicker-i18n/jquery.ui.datepicker-' . $locale . '.js' );
41
- // Also check alternate i18n filename (e.g. jquery.ui.datepicker-de.js instead of jquery.ui.datepicker-de-DE.js)
42
- if ( strlen( $locale ) > 2 )
43
- $file_paths[] = 'jqueryui/datepicker-i18n/jquery.ui.datepicker-' . substr( $locale, 0, 2 ) . '.js';
44
- $deps = array( 'jquery-ui-datepicker' );
45
- foreach ( $file_paths as $file_path )
46
- {
47
- if ( file_exists( RWMB_DIR . 'js/' . $file_path ) )
48
- {
49
- wp_register_script( 'jquery-ui-datepicker-i18n', RWMB_JS_URL . $file_path, $deps, '1.8.17', true );
50
- $deps[] = 'jquery-ui-datepicker-i18n';
51
- break;
52
- }
53
- }
54
-
55
- wp_enqueue_script( 'rwmb-date', RWMB_JS_URL . 'date.js', $deps, RWMB_VER, true );
56
  }
57
 
58
-
59
  /**
60
- * Normalize parameters for field
61
  *
 
62
  * @param array $field
63
  *
64
- * @return array
65
- */
66
- static function normalize( $field )
67
- {
68
- $field = wp_parse_args( $field, array(
69
- 'js_options' => array(),
70
- 'inline' => false,
71
- ) );
72
-
73
- // Deprecate 'format', but keep it for backward compatible
74
- // Use 'js_options' instead
75
- $field['js_options'] = wp_parse_args( $field['js_options'], array(
76
- 'dateFormat' => empty( $field['format'] ) ? 'yy-mm-dd' : $field['format'],
77
- 'showButtonPanel' => true,
78
- ) );
79
-
80
- $field = parent::normalize( $field );
81
-
82
- return $field;
83
- }
84
-
85
- /**
86
- * Get the attributes for a field
87
- *
88
- * @param array $field
89
- * @param mixed $value
90
- *
91
- * @return array
92
  */
93
- static function get_attributes( $field, $value = null )
94
  {
95
- $attributes = parent::get_attributes( $field, $value );
96
- $attributes = wp_parse_args( $attributes, array(
97
- 'data-options' => wp_json_encode( $field['js_options'] ),
98
- ) );
99
-
100
- return $attributes;
101
  }
102
  }
2
  /**
3
  * Date field class.
4
  */
5
+ class RWMB_Date_Field extends RWMB_Datetime_Field
6
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  /**
8
  * Enqueue scripts and styles
9
  *
10
  * @return void
11
  */
12
+ public static function admin_enqueue_scripts()
13
  {
14
+ parent::admin_register_scripts();
15
+ wp_enqueue_style( 'jquery-ui-datepicker' );
16
+ wp_enqueue_script( 'rwmb-date' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  }
18
 
 
19
  /**
20
+ * Returns a date() compatible format string from the JavaScript format
21
  *
22
+ * @link http://www.php.net/manual/en/function.date.php
23
  * @param array $field
24
  *
25
+ * @return string
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  */
27
+ public static function translate_format( $field )
28
  {
29
+ return strtr( $field['js_options']['dateFormat'], self::$date_formats );
 
 
 
 
 
30
  }
31
  }
inc/fields/datetime.php CHANGED
@@ -1,52 +1,52 @@
1
  <?php
 
2
  /**
3
  * Datetime field class.
4
  */
5
- class RWMB_Datetime_Field extends RWMB_Input_Field
6
  {
7
  /**
8
- * Translate date format from jQuery UI datepicker to PHP date()
9
  * It's used to store timestamp value of the field
10
- * Missing: 'o' => '', '!' => '', 'oo' => '', '@' => '', "''" => "'"
11
  * @var array
12
  */
13
- static $date_format_translation = array(
14
  'd' => 'j', 'dd' => 'd', 'oo' => 'z', 'D' => 'D', 'DD' => 'l',
15
- 'm' => 'n', 'mm' => 'm', 'M' => 'M', 'MM' => 'F', 'y' => 'y', 'yy' => 'Y',
16
  );
17
 
18
  /**
19
- * Translate date format from jQuery UI datepicker to PHP date()
20
  * It's used to store timestamp value of the field
21
  * Missing: 't' => '', T' => '', 'm' => '', 's' => ''
22
  * @var array
23
  */
24
- static $time_format_translation = array(
25
  'H' => 'G', 'HH' => 'H', 'h' => 'g', 'hh' => 'h',
26
  'mm' => 'i', 'ss' => 's', 'l' => 'u', 'tt' => 'a', 'TT' => 'A',
27
  );
28
 
29
  /**
30
- * Enqueue scripts and styles
31
- *
32
- * @return void
33
  */
34
- static function admin_enqueue_scripts()
35
  {
36
  $url = RWMB_CSS_URL . 'jqueryui';
37
  wp_register_style( 'jquery-ui-core', "{$url}/jquery.ui.core.css", array(), '1.8.17' );
38
  wp_register_style( 'jquery-ui-theme', "{$url}/jquery.ui.theme.css", array(), '1.8.17' );
39
- wp_register_style( 'jquery-ui-datepicker', "{$url}/jquery.ui.datepicker.css", array( 'jquery-ui-core', 'jquery-ui-theme' ), '1.8.17' );
40
  wp_register_style( 'wp-datepicker', RWMB_CSS_URL . 'datepicker.css', array( 'jquery-ui-core', 'jquery-ui-theme' ), '1.8.17' );
 
41
  wp_register_style( 'jquery-ui-slider', "{$url}/jquery.ui.slider.css", array( 'jquery-ui-core', 'jquery-ui-theme' ), '1.8.17' );
42
- wp_enqueue_style( 'jquery-ui-timepicker', "{$url}/jquery-ui-timepicker-addon.min.css", array( 'jquery-ui-datepicker', 'jquery-ui-slider', 'wp-datepicker' ), '1.5.0' );
43
 
44
  $url = RWMB_JS_URL . 'jqueryui';
45
  wp_register_script( 'jquery-ui-timepicker', "{$url}/jquery-ui-timepicker-addon.min.js", array( 'jquery-ui-datepicker', 'jquery-ui-slider' ), '1.5.0', true );
 
46
 
47
  /**
48
  * Localization
49
- * Use 1 minified JS file for timepicker which contains all languages for simpilicity (in version < 4.4.2 we use separated JS files).
50
  * The language is set in Javascript
51
  *
52
  * Note: we use full locale (de-DE) and fallback to short locale (de)
@@ -54,8 +54,6 @@ class RWMB_Datetime_Field extends RWMB_Input_Field
54
  $locale = str_replace( '_', '-', get_locale() );
55
  $locale_short = substr( $locale, 0, 2 );
56
 
57
- wp_register_script( 'jquery-ui-timepicker-i18n', "{$url}/jquery-ui-timepicker-addon-i18n.min.js", array( 'jquery-ui-timepicker' ), '1.5.0', true );
58
-
59
  $date_paths = array( 'jqueryui/datepicker-i18n/jquery.ui.datepicker-' . $locale . '.js' );
60
  if ( strlen( $locale ) > 2 )
61
  {
@@ -74,11 +72,27 @@ class RWMB_Datetime_Field extends RWMB_Input_Field
74
  }
75
  }
76
 
77
- wp_enqueue_script( 'rwmb-datetime', RWMB_JS_URL . 'datetime.js', $deps, RWMB_VER, true );
 
 
78
  wp_localize_script( 'rwmb-datetime', 'RWMB_Datetimepicker', array(
79
  'locale' => $locale,
80
  'localeShort' => $locale_short,
81
  ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  }
83
 
84
  /**
@@ -89,10 +103,25 @@ class RWMB_Datetime_Field extends RWMB_Input_Field
89
  *
90
  * @return string
91
  */
92
- static function html( $meta, $field )
93
  {
94
- $output = parent::html( $meta, $field );
95
- if( $field['inline'] )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  {
97
  $output .= '<div class="rwmb-datetime-inline"></div>';
98
  }
@@ -111,12 +140,21 @@ class RWMB_Datetime_Field extends RWMB_Input_Field
111
  *
112
  * @return string|int
113
  */
114
- static function value( $new, $old, $post_id, $field )
115
  {
116
  if ( ! $field['timestamp'] )
117
  return $new;
118
- $date = DateTime::createFromFormat( self::translate_format( $field ), $new );
119
- return $date ? $date->getTimestamp() : 0;
 
 
 
 
 
 
 
 
 
120
  }
121
 
122
  /**
@@ -128,19 +166,30 @@ class RWMB_Datetime_Field extends RWMB_Input_Field
128
  *
129
  * @return mixed
130
  */
131
- static function meta( $post_id, $saved, $field )
132
  {
133
  $meta = parent::meta( $post_id, $saved, $field );
 
 
 
 
 
134
  if ( is_array( $meta ) )
135
  {
136
  foreach ( $meta as $key => $value )
137
  {
138
- $meta[$key] = $field['timestamp'] && $value ? date( self::translate_format( $field ), intval( $value ) ) : $value;
 
 
 
139
  }
140
  }
141
  else
142
  {
143
- $meta = $field['timestamp'] && $meta ? date( self::translate_format( $field ), intval( $meta ) ) : $meta;
 
 
 
144
  }
145
  return $meta;
146
  }
@@ -149,25 +198,33 @@ class RWMB_Datetime_Field extends RWMB_Input_Field
149
  * Normalize parameters for field
150
  *
151
  * @param array $field
152
- *
153
  * @return array
154
  */
155
- static function normalize( $field )
156
  {
157
  $field = wp_parse_args( $field, array(
158
  'timestamp' => false,
159
- 'inline' => false,
160
- 'js_options' => array()
161
  ) );
162
 
163
  // Deprecate 'format', but keep it for backward compatible
164
  // Use 'js_options' instead
165
  $field['js_options'] = wp_parse_args( $field['js_options'], array(
166
- 'timeFormat' => 'HH:mm',
167
- 'separator' => ' ',
 
 
168
  ) );
169
 
170
- $field = RWMB_Date_Field::normalize( $field );
 
 
 
 
 
 
 
171
 
172
  return $field;
173
  }
@@ -180,9 +237,12 @@ class RWMB_Datetime_Field extends RWMB_Input_Field
180
  *
181
  * @return array
182
  */
183
- static function get_attributes( $field, $value = null )
184
  {
185
- $attributes = RWMB_Date_Field::get_attributes( $field, $value );
 
 
 
186
 
187
  return $attributes;
188
  }
@@ -190,16 +250,15 @@ class RWMB_Datetime_Field extends RWMB_Input_Field
190
  /**
191
  * Returns a date() compatible format string from the JavaScript format
192
  *
193
- * @see http://www.php.net/manual/en/function.date.php
194
- *
195
  * @param array $field
196
  *
197
  * @return string
198
  */
199
- static function translate_format( $field )
200
  {
201
- return strtr( $field['js_options']['dateFormat'], self::$date_format_translation )
202
  . $field['js_options']['separator']
203
- . strtr( $field['js_options']['timeFormat'], self::$time_format_translation );
204
  }
205
  }
1
  <?php
2
+
3
  /**
4
  * Datetime field class.
5
  */
6
+ class RWMB_Datetime_Field extends RWMB_Text_Field
7
  {
8
  /**
9
+ * Translate date format from jQuery UI date picker to PHP date()
10
  * It's used to store timestamp value of the field
11
+ * Missing: '!' => '', 'oo' => '', '@' => '', "''" => "'"
12
  * @var array
13
  */
14
+ protected static $date_formats = array(
15
  'd' => 'j', 'dd' => 'd', 'oo' => 'z', 'D' => 'D', 'DD' => 'l',
16
+ 'm' => 'n', 'mm' => 'm', 'M' => 'M', 'MM' => 'F', 'y' => 'y', 'yy' => 'Y', 'o' => 'z',
17
  );
18
 
19
  /**
20
+ * Translate time format from jQuery UI time picker to PHP date()
21
  * It's used to store timestamp value of the field
22
  * Missing: 't' => '', T' => '', 'm' => '', 's' => ''
23
  * @var array
24
  */
25
+ protected static $time_formats = array(
26
  'H' => 'G', 'HH' => 'H', 'h' => 'g', 'hh' => 'h',
27
  'mm' => 'i', 'ss' => 's', 'l' => 'u', 'tt' => 'a', 'TT' => 'A',
28
  );
29
 
30
  /**
31
+ * Register scripts and styles
 
 
32
  */
33
+ public static function admin_register_scripts()
34
  {
35
  $url = RWMB_CSS_URL . 'jqueryui';
36
  wp_register_style( 'jquery-ui-core', "{$url}/jquery.ui.core.css", array(), '1.8.17' );
37
  wp_register_style( 'jquery-ui-theme', "{$url}/jquery.ui.theme.css", array(), '1.8.17' );
 
38
  wp_register_style( 'wp-datepicker', RWMB_CSS_URL . 'datepicker.css', array( 'jquery-ui-core', 'jquery-ui-theme' ), '1.8.17' );
39
+ wp_register_style( 'jquery-ui-datepicker', "{$url}/jquery.ui.datepicker.css", array( 'wp-datepicker' ), '1.8.17' );
40
  wp_register_style( 'jquery-ui-slider', "{$url}/jquery.ui.slider.css", array( 'jquery-ui-core', 'jquery-ui-theme' ), '1.8.17' );
41
+ wp_register_style( 'jquery-ui-timepicker', "{$url}/jquery-ui-timepicker-addon.min.css", array( 'jquery-ui-datepicker', 'jquery-ui-slider', 'wp-datepicker' ), '1.5.0' );
42
 
43
  $url = RWMB_JS_URL . 'jqueryui';
44
  wp_register_script( 'jquery-ui-timepicker', "{$url}/jquery-ui-timepicker-addon.min.js", array( 'jquery-ui-datepicker', 'jquery-ui-slider' ), '1.5.0', true );
45
+ wp_register_script( 'jquery-ui-timepicker-i18n', "{$url}/jquery-ui-timepicker-addon-i18n.min.js", array( 'jquery-ui-timepicker' ), '1.5.0', true );
46
 
47
  /**
48
  * Localization
49
+ * Use 1 minified JS file for timepicker which contains all languages for simplicity (in version < 4.4.2 we use separated JS files).
50
  * The language is set in Javascript
51
  *
52
  * Note: we use full locale (de-DE) and fallback to short locale (de)
54
  $locale = str_replace( '_', '-', get_locale() );
55
  $locale_short = substr( $locale, 0, 2 );
56
 
 
 
57
  $date_paths = array( 'jqueryui/datepicker-i18n/jquery.ui.datepicker-' . $locale . '.js' );
58
  if ( strlen( $locale ) > 2 )
59
  {
72
  }
73
  }
74
 
75
+ wp_register_script( 'rwmb-datetime', RWMB_JS_URL . 'datetime.js', $deps, RWMB_VER, true );
76
+ wp_register_script( 'rwmb-date', RWMB_JS_URL . 'date.js', $deps, RWMB_VER, true );
77
+ wp_register_script( 'rwmb-time', RWMB_JS_URL . 'time.js', array( 'jquery-ui-timepicker-i18n' ), RWMB_VER, true );
78
  wp_localize_script( 'rwmb-datetime', 'RWMB_Datetimepicker', array(
79
  'locale' => $locale,
80
  'localeShort' => $locale_short,
81
  ) );
82
+ wp_localize_script( 'rwmb-time', 'RWMB_Timepicker', array(
83
+ 'locale' => $locale,
84
+ 'localeShort' => $locale_short,
85
+ ) );
86
+ }
87
+
88
+ /**
89
+ * Enqueue scripts and styles
90
+ */
91
+ public static function admin_enqueue_scripts()
92
+ {
93
+ self::admin_register_scripts();
94
+ wp_enqueue_style( 'jquery-ui-timepicker' );
95
+ wp_enqueue_script( 'rwmb-datetime' );
96
  }
97
 
98
  /**
103
  *
104
  * @return string
105
  */
106
+ public static function html( $meta, $field )
107
  {
108
+ $output = '';
109
+
110
+ if ( $field['timestamp'] )
111
+ {
112
+ $name = $field['field_name'];
113
+ $field = wp_parse_args( array( 'field_name' => $name . '[formatted]' ), $field );
114
+ $output .= sprintf(
115
+ '<input type="hidden" name="%s" class="rwmb-datetime-timestamp" value="%s">',
116
+ esc_attr( $name . '[timestamp]' ),
117
+ isset( $meta['timestamp'] ) ? intval( $meta['timestamp'] ) : ''
118
+ );
119
+ $meta = isset( $meta['formatted'] ) ? $meta['formatted'] : '';
120
+ }
121
+
122
+ $output .= parent::html( $meta, $field );
123
+
124
+ if ( $field['inline'] )
125
  {
126
  $output .= '<div class="rwmb-datetime-inline"></div>';
127
  }
140
  *
141
  * @return string|int
142
  */
143
+ public static function value( $new, $old, $post_id, $field )
144
  {
145
  if ( ! $field['timestamp'] )
146
  return $new;
147
+
148
+ if ( $field['clone'] )
149
+ {
150
+ foreach ( $new as $key => $value )
151
+ {
152
+ $new[$key] = isset( $value['timestamp'] ) ? $value['timestamp'] : 0;
153
+ }
154
+ return $new;
155
+ }
156
+
157
+ return isset( $new['timestamp'] ) ? $new['timestamp'] : 0;
158
  }
159
 
160
  /**
166
  *
167
  * @return mixed
168
  */
169
+ public static function meta( $post_id, $saved, $field )
170
  {
171
  $meta = parent::meta( $post_id, $saved, $field );
172
+ if ( ! $field['timestamp'] )
173
+ {
174
+ return $meta;
175
+ }
176
+ $method = array( RW_Meta_Box::get_class_name( $field ), 'translate_format' );
177
  if ( is_array( $meta ) )
178
  {
179
  foreach ( $meta as $key => $value )
180
  {
181
+ $meta[$key] = array(
182
+ 'timestamp' => $value,
183
+ 'formatted' => date( call_user_func( $method, $field ), intval( $value ) ),
184
+ );
185
  }
186
  }
187
  else
188
  {
189
+ $meta = array(
190
+ 'timestamp' => $meta,
191
+ 'formatted' => date( call_user_func( $method, $field ), intval( $meta ) ),
192
+ );
193
  }
194
  return $meta;
195
  }
198
  * Normalize parameters for field
199
  *
200
  * @param array $field
 
201
  * @return array
202
  */
203
+ public static function normalize( $field )
204
  {
205
  $field = wp_parse_args( $field, array(
206
  'timestamp' => false,
207
+ 'inline' => false,
208
+ 'js_options' => array(),
209
  ) );
210
 
211
  // Deprecate 'format', but keep it for backward compatible
212
  // Use 'js_options' instead
213
  $field['js_options'] = wp_parse_args( $field['js_options'], array(
214
+ 'timeFormat' => 'HH:mm',
215
+ 'separator' => ' ',
216
+ 'dateFormat' => empty( $field['format'] ) ? 'yy-mm-dd' : $field['format'],
217
+ 'showButtonPanel' => true,
218
  ) );
219
 
220
+ if ( $field['inline'] )
221
+ {
222
+ $field['js_options'] = wp_parse_args( $field['js_options'], array(
223
+ 'altFieldTimeOnly' => false,
224
+ ) );
225
+ }
226
+
227
+ $field = RWMB_Text_Field::normalize( $field );
228
 
229
  return $field;
230
  }
237
  *
238
  * @return array
239
  */
240
+ public static function get_attributes( $field, $value = null )
241
  {
242
+ $attributes = parent::get_attributes( $field, $value );
243
+ $attributes = wp_parse_args( $attributes, array(
244
+ 'data-options' => wp_json_encode( $field['js_options'] ),
245
+ ) );
246
 
247
  return $attributes;
248
  }
250
  /**
251
  * Returns a date() compatible format string from the JavaScript format
252
  *
253
+ * @link http://www.php.net/manual/en/function.date.php
 
254
  * @param array $field
255
  *
256
  * @return string
257
  */
258
+ public static function translate_format( $field )
259
  {
260
+ return strtr( $field['js_options']['dateFormat'], self::$date_formats )
261
  . $field['js_options']['separator']
262
+ . strtr( $field['js_options']['timeFormat'], self::$time_formats );
263
  }
264
  }
inc/fields/file-advanced.php CHANGED
@@ -39,4 +39,5 @@ class RWMB_File_Advanced_Field extends RWMB_Media_Field
39
  {
40
  return RWMB_File_Field::file_info( $file_id, $args );
41
  }
 
42
  }
39
  {
40
  return RWMB_File_Field::file_info( $file_id, $args );
41
  }
42
+
43
  }
inc/fields/file-upload.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * File advanced field class which users WordPress media popup to upload and select files.
4
+ */
5
+ class RWMB_File_Upload_Field extends RWMB_File_Advanced_Field
6
+ {
7
+ /**
8
+ * Add actions
9
+ *
10
+ * @return void
11
+ */
12
+ static function add_actions()
13
+ {
14
+ parent::add_actions();
15
+ // Print attachment templates
16
+ add_action( 'print_media_templates', array( __CLASS__, 'print_templates' ) );
17
+ }
18
+
19
+ /**
20
+ * Enqueue scripts and styles
21
+ *
22
+ * @return void
23
+ */
24
+ static function admin_enqueue_scripts()
25
+ {
26
+ parent::admin_enqueue_scripts();
27
+ wp_enqueue_style( 'rwmb-upload', RWMB_CSS_URL . 'upload.css', array( 'rwmb-media' ), RWMB_VER );
28
+ wp_enqueue_script( 'rwmb-file-upload', RWMB_JS_URL . 'file-upload.js', array( 'rwmb-media' ), RWMB_VER, true );
29
+ }
30
+
31
+ /**
32
+ * Template for media item
33
+ * @return void
34
+ */
35
+ static function print_templates()
36
+ {
37
+ require_once( RWMB_INC_DIR . 'templates/upload.php' );
38
+ }
39
+ }
inc/fields/image-advanced.php CHANGED
@@ -4,6 +4,30 @@
4
  */
5
  class RWMB_Image_Advanced_Field extends RWMB_Media_Field
6
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  /**
8
  * Normalize parameters for field
9
  *
@@ -54,4 +78,13 @@ class RWMB_Image_Advanced_Field extends RWMB_Media_Field
54
  {
55
  return RWMB_Image_Field::file_info( $file_id, $args );
56
  }
 
 
 
 
 
 
 
 
 
57
  }
4
  */
5
  class RWMB_Image_Advanced_Field extends RWMB_Media_Field
6
  {
7
+ /**
8
+ * Enqueue scripts and styles
9
+ *
10
+ * @return void
11
+ */
12
+ static function admin_enqueue_scripts()
13
+ {
14
+ parent::admin_enqueue_scripts();
15
+ wp_enqueue_style( 'rwmb-image-advanced', RWMB_CSS_URL . 'image-advanced.css', array( 'rwmb-media' ), RWMB_VER );
16
+ wp_enqueue_script( 'rwmb-image-advanced', RWMB_JS_URL . 'image-advanced.js', array( 'rwmb-media' ), RWMB_VER, true );
17
+ }
18
+
19
+ /**
20
+ * Add actions
21
+ *
22
+ * @return void
23
+ */
24
+ static function add_actions()
25
+ {
26
+ parent::add_actions();
27
+ // Print attachment templates
28
+ add_action( 'print_media_templates', array( __CLASS__, 'print_templates' ) );
29
+ }
30
+
31
  /**
32
  * Normalize parameters for field
33
  *
78
  {
79
  return RWMB_Image_Field::file_info( $file_id, $args );
80
  }
81
+
82
+ /**
83
+ * Template for media item
84
+ * @return void
85
+ */
86
+ static function print_templates()
87
+ {
88
+ require_once( RWMB_INC_DIR . 'templates/image-advanced.php' );
89
+ }
90
  }
inc/fields/image-upload.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * File advanced field class which users WordPress media popup to upload and select files.
4
+ */
5
+ class RWMB_Image_Upload_Field extends RWMB_Image_Advanced_Field
6
+ {
7
+ /**
8
+ * Add actions
9
+ *
10
+ * @return void
11
+ */
12
+ static function add_actions()
13
+ {
14
+ parent::add_actions();
15
+ // Print attachment templates
16
+ add_action( 'print_media_templates', array( 'RWMB_File_Upload_Field', 'print_templates' ) );
17
+ }
18
+
19
+ /**
20
+ * Enqueue scripts and styles
21
+ *
22
+ * @return void
23
+ */
24
+ static function admin_enqueue_scripts()
25
+ {
26
+ parent::admin_enqueue_scripts();
27
+ RWMB_File_Upload_Field::admin_enqueue_scripts();
28
+ wp_enqueue_script( 'rwmb-image-upload', RWMB_JS_URL . 'image-upload.js', array( 'rwmb-file-upload', 'rwmb-image-advanced' ), RWMB_VER, true );
29
+ }
30
+ }
inc/fields/input-list.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class RWMB_Input_List_Field extends RWMB_Choice_Field
3
+ {
4
+ /**
5
+ * Enqueue scripts and styles
6
+ *
7
+ * @return void
8
+ */
9
+ static function admin_enqueue_scripts()
10
+ {
11
+ wp_enqueue_style( 'rwmb-input-list', RWMB_CSS_URL . 'input-list.css', array(), RWMB_VER );
12
+ wp_enqueue_script( 'rwmb-input-list', RWMB_JS_URL . 'input-list.js', array(), RWMB_VER, true );
13
+ }
14
+
15
+ /**
16
+ * Walk options
17
+ *
18
+ * @param mixed $meta
19
+ * @param array $field
20
+ * @param mixed $options
21
+ * @param mixed $db_fields
22
+ *
23
+ * @return string
24
+ */
25
+ static function walk( $options, $db_fields, $meta, $field )
26
+ {
27
+ $walker = new RWMB_Input_List_Walker( $db_fields, $field, $meta );
28
+ $output = sprintf( '<ul class="rwmb-input-list %s">', $field['collapse'] ? 'collapse' : '' );
29
+ $output .= $walker->walk( $options, $field['flatten'] ? - 1 : 0 );
30
+ $output .= '</ul>';
31
+
32
+ return $output;
33
+ }
34
+
35
+ /**
36
+ * Normalize parameters for field
37
+ *
38
+ * @param array $field
39
+ *
40
+ * @return array
41
+ */
42
+ static function normalize( $field )
43
+ {
44
+ $field = $field['multiple'] ? RWMB_Multiple_Values_Field::normalize( $field ) : $field;
45
+ $field = RWMB_Input_Field::normalize( $field );
46
+ $field = parent::normalize( $field );
47
+ $field = wp_parse_args( $field, array(
48
+ 'collapse' => true,
49
+ ) );
50
+
51
+ $field['flatten'] = $field['multiple'] ? $field['flatten'] : true;
52
+
53
+ return $field;
54
+ }
55
+
56
+ /**
57
+ * Get the attributes for a field
58
+ *
59
+ * @param array $field
60
+ * @param mixed $value
61
+ *
62
+ * @return array
63
+ */
64
+ static function get_attributes( $field, $value = null )
65
+ {
66
+ $attributes = RWMB_Input_Field::get_attributes( $field, $value );
67
+ $attributes['id'] = false;
68
+ $attributes['type'] = $field['multiple'] ? 'checkbox' : 'radio';
69
+ $attributes['value'] = $value;
70
+
71
+ return $attributes;
72
+ }
73
+
74
+ /**
75
+ * Output the field value
76
+ * Display option name instead of option value
77
+ *
78
+ * @use self::meta()
79
+ *
80
+ * @param array $field Field parameters
81
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
82
+ * @param int|null $post_id Post ID. null for current post. Optional.
83
+ *
84
+ * @return mixed Field value
85
+ */
86
+ static function the_value( $field, $args = array(), $post_id = null )
87
+ {
88
+ $value = parent::get_value( $field, $args, $post_id );
89
+ return empty( $value ) ? '' : $field['options'][$value];
90
+ }
91
+ }
inc/fields/media.php CHANGED
@@ -14,6 +14,19 @@ class RWMB_Media_Field extends RWMB_Field
14
  wp_enqueue_media();
15
  wp_enqueue_style( 'rwmb-media', RWMB_CSS_URL . 'media.css', array(), RWMB_VER );
16
  wp_enqueue_script( 'rwmb-media', RWMB_JS_URL . 'media.js', array( 'jquery-ui-sortable', 'underscore', 'backbone' ), RWMB_VER, true );
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  }
18
 
19
  /**
@@ -95,6 +108,25 @@ class RWMB_Media_Field extends RWMB_Field
95
  return $attributes;
96
  }
97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  /**
99
  * Save meta value
100
  *
@@ -115,97 +147,6 @@ class RWMB_Media_Field extends RWMB_Field
115
  */
116
  static function print_templates()
117
  {
118
- $i18n_add = apply_filters( 'rwmb_media_add_string', _x( '+ Add Media', 'media', 'meta-box' ) );
119
- $i18n_remove = apply_filters( 'rwmb_media_remove_string', _x( 'Remove', 'media', 'meta-box' ) );
120
- $i18n_edit = apply_filters( 'rwmb_media_edit_string', _x( 'Edit', 'media', 'meta-box' ) );
121
- $i18n_view = apply_filters( 'rwmb_media_view_string', _x( 'View', 'media', 'meta-box' ) );
122
- $i18n_single_files = apply_filters( 'rwmb_media_single_files_string', _x( ' file', 'media', 'meta-box' ) );
123
- $i18n_multiple_files = apply_filters( 'rwmb_media_multiple_files_string', _x( ' files', 'media', 'meta-box' ) );
124
- $i18n_title = _x( 'No Title', 'media', 'meta-box' );
125
- ?>
126
- <script id="tmpl-rwmb-media-item" type="text/html">
127
- <input type="hidden" name="{{{ data.fieldName }}}" value="{{{ data.id }}}" class="rwmb-media-input">
128
- <div class="rwmb-media-preview">
129
- <div class="rwmb-media-content">
130
- <div class="centered">
131
- <# if ( 'image' === data.type && data.sizes ) { #>
132
- <# if ( data.sizes.thumbnail ) { #>
133
- <img src="{{{ data.sizes.thumbnail.url }}}">
134
- <# } else { #>
135
- <img src="{{{ data.sizes.full.url }}}">
136
- <# } #>
137
- <# } else { #>
138
- <# if ( data.image && data.image.src && data.image.src !== data.icon ) { #>
139
- <img src="{{ data.image.src }}" />
140
- <# } else { #>
141
- <img src="{{ data.icon }}" />
142
- <# } #>
143
- <# } #>
144
- </div>
145
- </div>
146
- </div>
147
- <div class="rwmb-media-info">
148
- <h4>
149
- <a href="{{{ data.url }}}" target="_blank" title="<?php echo esc_attr( $i18n_view ); ?>">
150
- <# if( data.title ) { #> {{{ data.title }}}
151
- <# } else { #> <?php echo esc_attr( $i18n_title ); ?>
152
- <# } #>
153
- </a>
154
- </h4>
155
- <p>{{{ data.mime }}}</p>
156
- <p>
157
- <a class="rwmb-edit-media" title="<?php echo esc_attr( $i18n_edit ); ?>" href="{{{ data.editLink }}}" target="_blank">
158
- <span class="dashicons dashicons-edit"></span><?php echo esc_attr( $i18n_edit ); ?>
159
- </a>
160
- <a href="#" class="rwmb-remove-media" title="<?php echo esc_attr( $i18n_remove ); ?>">
161
- <span class="dashicons dashicons-no-alt"></span><?php echo esc_attr( $i18n_remove ); ?>
162
- </a>
163
- </p>
164
- </div>
165
- </script>
166
-
167
- <script id="tmpl-rwmb-image-item" type="text/html">
168
- <input type="hidden" name="{{{ data.fieldName }}}" value="{{{ data.id }}}" class="rwmb-media-input">
169
- <div class="rwmb-media-preview">
170
- <div class="rwmb-media-content">
171
- <div class="centered">
172
- <# if ( 'image' === data.type && data.sizes ) { #>
173
- <# if ( data.sizes.thumbnail ) { #>
174
- <img src="{{{ data.sizes.thumbnail.url }}}">
175
- <# } else { #>
176
- <img src="{{{ data.sizes.full.url }}}">
177
- <# } #>
178
- <# } else { #>
179
- <# if ( data.image && data.image.src && data.image.src !== data.icon ) { #>
180
- <img src="{{ data.image.src }}" />
181
- <# } else { #>
182
- <img src="{{ data.icon }}" />
183
- <# } #>
184
- <# } #>
185
- </div>
186
- </div>
187
- </div>
188
- <div class="rwmb-overlay"></div>
189
- <div class="rwmb-media-bar">
190
- <a class="rwmb-edit-media" title="<?php echo esc_attr( $i18n_edit ); ?>" href="{{{ data.editLink }}}" target="_blank">
191
- <span class="dashicons dashicons-edit"></span>
192
- </a>
193
- <a href="#" class="rwmb-remove-media" title="<?php echo esc_attr( $i18n_remove ); ?>">
194
- <span class="dashicons dashicons-no-alt"></span>
195
- </a>
196
- </div>
197
- </script>
198
-
199
- <script id="tmpl-rwmb-add-media" type="text/html">
200
- <?php echo $i18n_add; ?>
201
- </script>
202
-
203
- <script id="tmpl-rwmb-media-status" type="text/html">
204
- <# if ( data.maxFiles > 0 ) { #>
205
- {{{ data.items }}}/{{{ data.maxFiles }}}
206
- <# if ( data.items > 1 || data.items < 1 ) { #> <?php echo $i18n_multiple_files; ?> <# } else {#> <?php echo $i18n_single_files; ?> <# } #>
207
- <# } #>
208
- </script>
209
- <?php
210
  }
211
  }
14
  wp_enqueue_media();
15
  wp_enqueue_style( 'rwmb-media', RWMB_CSS_URL . 'media.css', array(), RWMB_VER );
16
  wp_enqueue_script( 'rwmb-media', RWMB_JS_URL . 'media.js', array( 'jquery-ui-sortable', 'underscore', 'backbone' ), RWMB_VER, true );
17
+ wp_localize_script( 'rwmb-media', 'i18nRwmbMedia', array(
18
+ 'add' => apply_filters( 'rwmb_media_add_string', _x( '+ Add Media', 'media', 'meta-box' ) ),
19
+ 'single' => apply_filters( 'rwmb_media_single_files_string', _x( ' file', 'media', 'meta-box' ) ),
20
+ 'multiple' => apply_filters( 'rwmb_media_multiple_files_string', _x( ' files', 'media', 'meta-box' ) ),
21
+ 'remove' => apply_filters( 'rwmb_media_remove_string', _x( 'Remove', 'media', 'meta-box' ) ),
22
+ 'edit' => apply_filters( 'rwmb_media_edit_string', _x( 'Edit', 'media', 'meta-box' ) ),
23
+ 'view' => apply_filters( 'rwmb_media_view_string', _x( 'View', 'media', 'meta-box' ) ),
24
+ 'noTitle' => _x( 'No Title', 'media', 'meta-box' ),
25
+ 'loadingUrl' => RWMB_URL . 'img/loader.gif',
26
+ 'extensions' => self::get_mime_extensions(),
27
+ 'select' => _x( 'Select Files', 'media', 'meta-box' ),
28
+ 'uploadInstructions' => _x( 'Drop files here to upload', 'media', 'meta-box' )
29
+ ) );
30
  }
31
 
32
  /**
108
  return $attributes;
109
  }
110
 
111
+ static function get_mime_extensions()
112
+ {
113
+ $mime_types = wp_get_mime_types();
114
+ $extensions = array();
115
+ foreach( $mime_types as $ext => $mime )
116
+ {
117
+ $ext = explode( '|', $ext );
118
+ $extensions[ $mime ] = $ext;
119
+
120
+ $mime_parts = explode( '/', $mime );
121
+ if( empty( $extensions[ $mime_parts[0] ] ) )
122
+ $extensions[ $mime_parts[0] ] = array();
123
+ $extensions[ $mime_parts[0] ] = $extensions[ $mime_parts[0] . '/*' ] = array_merge( $extensions[ $mime_parts[0] ], $ext );
124
+
125
+ }
126
+
127
+ return $extensions;
128
+ }
129
+
130
  /**
131
  * Save meta value
132
  *
147
  */
148
  static function print_templates()
149
  {
150
+ require_once( RWMB_INC_DIR . 'templates/media.php' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  }
152
  }
inc/fields/object-choice.php CHANGED
@@ -2,38 +2,36 @@
2
  /**
3
  * Abstract field to select an object: post, user, taxonomy, etc.
4
  */
5
- abstract class RWMB_Object_Choice_Field extends RWMB_Field
6
  {
7
  /**
8
  * Get field HTML
9
  *
 
 
10
  * @param mixed $meta
11
  * @param array $field
12
- *
13
  * @return string
14
  */
15
- static function html( $meta, $field )
16
  {
17
- $field_class = RW_Meta_Box::get_class_name( $field );
18
- $meta = (array) $meta;
19
- $options = call_user_func( array( $field_class, 'get_options' ), $field );
20
- $output = '';
21
  switch ( $field['field_type'] )
22
  {
23
  case 'checkbox_list':
24
  case 'radio_list':
25
- $output .= call_user_func( array( $field_class, 'render_list' ), $options, $meta, $field );
26
  break;
27
  case 'select_tree':
28
- $output .= call_user_func( array( $field_class, 'render_select_tree' ), $options, $meta, $field );
29
  break;
30
  case 'select_advanced':
 
 
31
  case 'select':
32
  default:
33
- $output .= call_user_func( array( $field_class, 'render_select' ), $options, $meta, $field );
34
  break;
35
  }
36
- return $output;
37
  }
38
 
39
  /**
@@ -43,13 +41,13 @@ abstract class RWMB_Object_Choice_Field extends RWMB_Field
43
  *
44
  * @return array
45
  */
46
- static function normalize( $field )
47
  {
48
  $field = parent::normalize( $field );
49
  $field = wp_parse_args( $field, array(
50
  'flatten' => true,
51
  'query_args' => array(),
52
- 'field_type' => 'select',
53
  ) );
54
 
55
  if ( 'checkbox_tree' === $field['field_type'] )
@@ -62,28 +60,20 @@ abstract class RWMB_Object_Choice_Field extends RWMB_Field
62
  {
63
  case 'checkbox_list':
64
  case 'radio_list':
65
- $field = wp_parse_args( $field, array(
66
- 'collapse' => true
67
- ) );
68
- $field['flatten'] = 'radio_list' === $field['field_type'] ? true : $field['flatten'];
69
  $field['multiple'] = 'radio_list' === $field['field_type'] ? false : true;
70
- $field = RWMB_Input_Field::normalize( $field );
71
  break;
72
  case 'select_advanced':
73
- $field = RWMB_Select_Advanced_Field::normalize( $field );
74
- $field['flatten'] = true;
75
  break;
76
  case 'select_tree':
77
- $field = RWMB_Select_Field::normalize( $field );
78
- $field['multiple'] = true;
79
  break;
80
  case 'select':
81
  default:
82
- $field = RWMB_Select_Field::normalize( $field );
83
  break;
84
  }
85
-
86
- return $field;
87
  }
88
 
89
  /**
@@ -94,46 +84,34 @@ abstract class RWMB_Object_Choice_Field extends RWMB_Field
94
  *
95
  * @return array
96
  */
97
- static function get_attributes( $field, $value = null )
98
  {
99
  switch ( $field['field_type'] )
100
  {
101
  case 'checkbox_list':
102
  case 'radio_list':
103
- $attributes = RWMB_Input_Field::get_attributes( $field, $value );
104
- $attributes['class'] .= " rwmb-choice";
105
- $attributes['id'] = false;
106
- $attributes['type'] = 'radio_list' === $field['field_type'] ? 'radio' : 'checkbox';
107
- $attributes['name'] .= ! $field['clone'] && $field['multiple'] ? '[]' : '';
108
  break;
109
  case 'select_advanced':
110
- $attributes = RWMB_Select_Advanced_Field::get_attributes( $field, $value );
111
- $attributes['class'] .= " rwmb-select_advanced";
 
112
  break;
113
  case 'select_tree':
114
- $attributes = RWMB_Select_Field::get_attributes( $field, $value );
115
- $attributes['multiple'] = false;
116
- $attributes['id'] = false;
117
- $attributes['class'] .= " rwmb-select";
118
  break;
119
  case 'select':
120
  default:
121
- $attributes = RWMB_Select_Field::get_attributes( $field, $value );
122
- $attributes['class'] .= " rwmb-select";
123
  break;
124
  }
125
-
126
-
127
-
128
- return $attributes;
129
  }
130
 
131
  /**
132
  * Get field names of object to be used by walker
133
- *
134
  * @return array
135
  */
136
- static function get_db_fields()
137
  {
138
  return array(
139
  'parent' => '',
@@ -144,87 +122,15 @@ abstract class RWMB_Object_Choice_Field extends RWMB_Field
144
 
145
  /**
146
  * Enqueue scripts and styles
147
- *
148
- * @return void
149
  */
150
- static function admin_enqueue_scripts()
151
  {
152
- wp_enqueue_style( 'rwmb-object-choice', RWMB_CSS_URL . 'object-choice.css', array(), RWMB_VER );
153
- wp_enqueue_script( 'rwmb-object-choice', RWMB_JS_URL . 'object-choice.js', array(), RWMB_VER, true );
154
  RWMB_Select_Field::admin_enqueue_scripts();
 
155
  RWMB_Select_Advanced_Field::admin_enqueue_scripts();
156
  }
157
 
158
- /**
159
- * Render checkbox_list or radio_list using walker
160
- *
161
- * @param $options
162
- * @param $meta
163
- * @param $field
164
- *
165
- * @return array
166
- */
167
- static function render_list( $options, $meta, $field )
168
- {
169
- $field_class = RW_Meta_Box::get_class_name( $field );
170
- $db_fields = call_user_func( array( $field_class, 'get_db_fields' ), $field );
171
- $walker = new RWMB_Choice_List_Walker( $db_fields, $field, $meta );
172
-
173
- $output = sprintf( '<ul class="rwmb-choice-list %s">', $field['collapse'] ? 'collapse' : '' );
174
-
175
- $output .= $walker->walk( $options, $field['flatten'] ? - 1 : 0 );
176
- $output .= '</ul>';
177
- return $output;
178
- }
179
-
180
- /**
181
- * Render select or select_advanced using walker
182
- *
183
- * @param $options
184
- * @param $meta
185
- * @param $field
186
- *
187
- * @return array
188
- */
189
- static function render_select( $options, $meta, $field )
190
- {
191
- $field_class = RW_Meta_Box::get_class_name( $field );
192
- $attributes = call_user_func( array( $field_class, 'get_attributes' ), $field, $meta );
193
- $db_fields = call_user_func( array( $field_class, 'get_db_fields' ), $field );
194
- $walker = new RWMB_Select_Walker( $db_fields, $field, $meta );
195
-
196
- $output = sprintf(
197
- '<select %s>',
198
- self::render_attributes( $attributes )
199
- );
200
- if ( false === $field['multiple'] )
201
- {
202
- $output .= isset( $field['placeholder'] ) ? "<option value=''>{$field['placeholder']}</option>" : '<option></option>';
203
- }
204
- $output .= $walker->walk( $options, $field['flatten'] ? - 1 : 0 );
205
- $output .= '</select>';
206
- return $output;
207
- }
208
-
209
- /**
210
- * Render select_tree
211
- *
212
- * @param $options
213
- * @param $meta
214
- * @param $field
215
- *
216
- * @return array
217
- */
218
- static function render_select_tree( $options, $meta, $field )
219
- {
220
- $field_class = RW_Meta_Box::get_class_name( $field );
221
- $db_fields = call_user_func( array( $field_class, 'get_db_fields' ), $field );
222
- $walker = new RWMB_Select_Tree_Walker( $db_fields, $field, $meta );
223
- $output = $walker->walk( $options );
224
-
225
- return $output;
226
- }
227
-
228
  /**
229
  * Get options for walker
230
  *
@@ -232,7 +138,7 @@ abstract class RWMB_Object_Choice_Field extends RWMB_Field
232
  *
233
  * @return array
234
  */
235
- static function get_options( $field )
236
  {
237
  return array();
238
  }
2
  /**
3
  * Abstract field to select an object: post, user, taxonomy, etc.
4
  */
5
+ abstract class RWMB_Object_Choice_Field extends RWMB_Choice_Field
6
  {
7
  /**
8
  * Get field HTML
9
  *
10
+ * @param mixed $options
11
+ * @param mixed $db_fields
12
  * @param mixed $meta
13
  * @param array $field
 
14
  * @return string
15
  */
16
+ public static function walk( $options, $db_fields, $meta, $field )
17
  {
 
 
 
 
18
  switch ( $field['field_type'] )
19
  {
20
  case 'checkbox_list':
21
  case 'radio_list':
22
+ return RWMB_Input_List_Field::walk( $options, $db_fields, $meta, $field );
23
  break;
24
  case 'select_tree':
25
+ return RWMB_Select_Tree_Field::walk( $options, $db_fields, $meta, $field );
26
  break;
27
  case 'select_advanced':
28
+ return RWMB_Select_Advanced_Field::walk( $options, $db_fields, $meta, $field );
29
+ break;
30
  case 'select':
31
  default:
32
+ return RWMB_Select_Field::walk( $options, $db_fields, $meta, $field );
33
  break;
34
  }
 
35
  }
36
 
37
  /**
41
  *
42
  * @return array
43
  */
44
+ public static function normalize( $field )
45
  {
46
  $field = parent::normalize( $field );
47
  $field = wp_parse_args( $field, array(
48
  'flatten' => true,
49
  'query_args' => array(),
50
+ 'field_type' => 'select_advanced',
51
  ) );
52
 
53
  if ( 'checkbox_tree' === $field['field_type'] )
60
  {
61
  case 'checkbox_list':
62
  case 'radio_list':
 
 
 
 
63
  $field['multiple'] = 'radio_list' === $field['field_type'] ? false : true;
64
+ return RWMB_Input_List_Field::normalize( $field );
65
  break;
66
  case 'select_advanced':
67
+ return RWMB_Select_Advanced_Field::normalize( $field );
 
68
  break;
69
  case 'select_tree':
70
+ return RWMB_Select_Tree_Field::normalize( $field );
 
71
  break;
72
  case 'select':
73
  default:
74
+ return RWMB_Select_Field::normalize( $field );
75
  break;
76
  }
 
 
77
  }
78
 
79
  /**
84
  *
85
  * @return array
86
  */
87
+ public static function get_attributes( $field, $value = null )
88
  {
89
  switch ( $field['field_type'] )
90
  {
91
  case 'checkbox_list':
92
  case 'radio_list':
93
+ return RWMB_Input_List_Field::get_attributes( $field, $value );
 
 
 
 
94
  break;
95
  case 'select_advanced':
96
+ $attributes = RWMB_Select_Advanced_Field::get_attributes( $field, $value );
97
+ $attributes['class'] .= ' rwmb-select_advanced';
98
+ return $attributes;
99
  break;
100
  case 'select_tree':
101
+ return RWMB_Select_Tree_Field::get_attributes( $field, $value );
 
 
 
102
  break;
103
  case 'select':
104
  default:
105
+ return RWMB_Select_Field::get_attributes( $field, $value );
 
106
  break;
107
  }
 
 
 
 
108
  }
109
 
110
  /**
111
  * Get field names of object to be used by walker
 
112
  * @return array
113
  */
114
+ public static function get_db_fields()
115
  {
116
  return array(
117
  'parent' => '',
122
 
123
  /**
124
  * Enqueue scripts and styles
 
 
125
  */
126
+ public static function admin_enqueue_scripts()
127
  {
128
+ RWMB_Input_List_Field::admin_enqueue_scripts();
 
129
  RWMB_Select_Field::admin_enqueue_scripts();
130
+ RWMB_Select_Tree_Field::admin_enqueue_scripts();
131
  RWMB_Select_Advanced_Field::admin_enqueue_scripts();
132
  }
133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  /**
135
  * Get options for walker
136
  *
138
  *
139
  * @return array
140
  */
141
+ public static function get_options( $field )
142
  {
143
  return array();
144
  }
inc/fields/oembed.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
  /**
3
  * oEmbed field class.
4
  */
@@ -7,7 +8,7 @@ class RWMB_OEmbed_Field extends RWMB_URL_Field
7
  /**
8
  * Enqueue scripts and styles
9
  */
10
- static function admin_enqueue_scripts()
11
  {
12
  wp_enqueue_style( 'rwmb-oembed', RWMB_CSS_URL . 'oembed.css' );
13
  wp_enqueue_script( 'rwmb-oembed', RWMB_JS_URL . 'oembed.js', array(), RWMB_VER, true );
@@ -16,7 +17,7 @@ class RWMB_OEmbed_Field extends RWMB_URL_Field
16
  /**
17
  * Add actions
18
  */
19
- static function add_actions()
20
  {
21
  add_action( 'wp_ajax_rwmb_get_embed', array( __CLASS__, 'wp_ajax_get_embed' ) );
22
  }
@@ -24,7 +25,7 @@ class RWMB_OEmbed_Field extends RWMB_URL_Field
24
  /**
25
  * Ajax callback for returning oEmbed HTML
26
  */
27
- static function wp_ajax_get_embed()
28
  {
29
  $url = (string) filter_input( INPUT_POST, 'url', FILTER_SANITIZE_URL );
30
  wp_send_json_success( self::get_embed( $url ) );
@@ -36,15 +37,29 @@ class RWMB_OEmbed_Field extends RWMB_URL_Field
36
  * @param string $url
37
  * @return string
38
  */
39
- static function get_embed( $url )
40
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  // Try oembed first
42
- $embed = wp_oembed_get( $url );
43
 
44
  // If no oembed provides found, try WordPress auto embed
45
  if ( ! $embed )
46
  {
47
- $embed = $GLOBALS['wp_embed']->shortcode( array(), $url );
48
  }
49
 
50
  return $embed ? $embed : __( 'Embed HTML not available.', 'meta-box' );
@@ -57,7 +72,7 @@ class RWMB_OEmbed_Field extends RWMB_URL_Field
57
  * @param array $field
58
  * @return string
59
  */
60
- static function html( $meta, $field )
61
  {
62
  $attributes = self::get_attributes( $field, $meta );
63
  return sprintf(
@@ -81,9 +96,14 @@ class RWMB_OEmbed_Field extends RWMB_URL_Field
81
  *
82
  * @return mixed Field value
83
  */
84
- static function the_value( $field, $args = array(), $post_id = null )
85
  {
86
- $value = self::get_value( $field, $args, $post_id );
 
 
 
 
 
87
  if ( $field['clone'] )
88
  {
89
  $output = '<ul>';
1
  <?php
2
+
3
  /**
4
  * oEmbed field class.
5
  */
8
  /**
9
  * Enqueue scripts and styles
10
  */
11
+ public static function admin_enqueue_scripts()
12
  {
13
  wp_enqueue_style( 'rwmb-oembed', RWMB_CSS_URL . 'oembed.css' );
14
  wp_enqueue_script( 'rwmb-oembed', RWMB_JS_URL . 'oembed.js', array(), RWMB_VER, true );
17
  /**
18
  * Add actions
19
  */
20
+ public static function add_actions()
21
  {
22
  add_action( 'wp_ajax_rwmb_get_embed', array( __CLASS__, 'wp_ajax_get_embed' ) );
23
  }
25
  /**
26
  * Ajax callback for returning oEmbed HTML
27
  */
28
+ public static function wp_ajax_get_embed()
29
  {
30
  $url = (string) filter_input( INPUT_POST, 'url', FILTER_SANITIZE_URL );
31
  wp_send_json_success( self::get_embed( $url ) );
37
  * @param string $url
38
  * @return string
39
  */
40
+ public static function get_embed( $url )
41
  {
42
+ /**
43
+ * Set arguments for getting embeded HTML.
44
+ * Without arguments, default width will be taken from global $content_width, which can break UI in the admin
45
+ * @link https://github.com/rilwis/meta-box/issues/801
46
+ * @see WP_oEmbed::fetch()
47
+ * @see WP_Embed::shortcode()
48
+ * @see wp_embed_defaults()
49
+ */
50
+ $args = array();
51
+ if ( is_admin() )
52
+ {
53
+ $args['width'] = 360;
54
+ }
55
+
56
  // Try oembed first
57
+ $embed = wp_oembed_get( $url, $args );
58
 
59
  // If no oembed provides found, try WordPress auto embed
60
  if ( ! $embed )
61
  {
62
+ $embed = $GLOBALS['wp_embed']->shortcode( $args, $url );
63
  }
64
 
65
  return $embed ? $embed : __( 'Embed HTML not available.', 'meta-box' );
72
  * @param array $field
73
  * @return string
74
  */
75
+ public static function html( $meta, $field )
76
  {
77
  $attributes = self::get_attributes( $field, $meta );
78
  return sprintf(
96
  *
97
  * @return mixed Field value
98
  */
99
+ public static function the_value( $field, $args = array(), $post_id = null )
100
  {
101
+ $value = self::get_value( $field, $args, $post_id );
102
+ $output = '';
103
+ if ( empty( $value ) )
104
+ {
105
+ return $output;
106
+ }
107
  if ( $field['clone'] )
108
  {
109
  $output = '<ul>';
inc/fields/plupload-image.php CHANGED
@@ -2,161 +2,4 @@
2
  /**
3
  * Image upload field which uses plupload library to drag and drop files to upload.
4
  */
5
- class RWMB_Plupload_Image_Field extends RWMB_Image_Field
6
- {
7
- /**
8
- * Add field actions.
9
- */
10
- static function add_actions()
11
- {
12
- parent::add_actions();
13
- add_action( 'wp_ajax_rwmb_plupload_image_upload', array( __CLASS__, 'handle_upload' ) );
14
- }
15
-
16
- /**
17
- * Upload ajax callback function.
18
- */
19
- static function handle_upload()
20
- {
21
- $post_id = (int) filter_input( INPUT_POST, 'post_id', FILTER_SANITIZE_NUMBER_INT );
22
- $field_id = (string) filter_input( INPUT_POST, 'field_id' );
23
-
24
- check_ajax_referer( "rwmb-upload-images_{$field_id}" );
25
-
26
- $file = $_FILES['async-upload'];
27
- $file_attr = wp_handle_upload( $file, array( 'test_form' => false ) );
28
- $attachment = array(
29
- 'guid' => $file_attr['url'],
30
- 'post_mime_type' => $file_attr['type'],
31
- 'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $file['name'] ) ),
32
- 'post_content' => '',
33
- 'post_status' => 'inherit',
34
- );
35
-
36
- // Adds file as attachment to WordPress
37
- $attachment_id = wp_insert_attachment( $attachment, $file_attr['file'], $post_id );
38
- if ( is_wp_error( $attachment_id ) )
39
- {
40
- wp_send_json_error();
41
- }
42
- wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $file_attr['file'] ) );
43
-
44
- // Save file ID in meta field
45
- add_post_meta( $post_id, $field_id, $attachment_id, false );
46
- wp_send_json_success( self::img_html( $attachment_id ) );
47
- }
48
-
49
- /**
50
- * Enqueue scripts and styles.
51
- */
52
- static function admin_enqueue_scripts()
53
- {
54
- // Enqueue same scripts and styles as for file field
55
- parent::admin_enqueue_scripts();
56
- wp_enqueue_style( 'rwmb-plupload-image', RWMB_CSS_URL . 'plupload-image.css', array( 'wp-admin' ), RWMB_VER );
57
- wp_enqueue_script( 'rwmb-plupload-image', RWMB_JS_URL . 'plupload-image.js', array( 'jquery-ui-sortable', 'wp-ajax-response', 'plupload-all' ), RWMB_VER, true );
58
- wp_localize_script( 'rwmb-plupload-image', 'RWMB', array( 'url' => RWMB_URL ) );
59
- }
60
-
61
- /**
62
- * Get field HTML.
63
- *
64
- * @param mixed $meta
65
- * @param array $field
66
- * @return string
67
- */
68
- static function html( $meta, $field )
69
- {
70
- if ( ! is_array( $meta ) )
71
- $meta = ( array ) $meta;
72
-
73
- // Filter to change the drag & drop box background string
74
- $i18n_drop = apply_filters( 'rwmb_plupload_image_drop_string', _x( 'Drop images here', 'image upload', 'meta-box' ), $field );
75
- $i18n_or = apply_filters( 'rwmb_plupload_image_or_string', _x( 'or', 'image upload', 'meta-box' ), $field );
76
- $i18n_select = apply_filters( 'rwmb_plupload_image_select_string', _x( 'Select Files', 'image upload', 'meta-box' ), $field );
77
-
78
- // Uploaded images
79
-
80
- // Check for max_file_uploads
81
- $classes = array( 'rwmb-drag-drop', 'drag-drop', 'hide-if-no-js', 'new-files' );
82
- if ( ! empty( $field['max_file_uploads'] ) && count( $meta ) >= (int) $field['max_file_uploads'] )
83
- $classes[] = 'hidden';
84
-
85
- $html = self::get_uploaded_images( $meta, $field );
86
-
87
- // Show form upload
88
- $html .= sprintf(
89
- '<div id="%s-dragdrop" class="%s" data-upload_nonce="%s" data-js_options="%s">
90
- <div class = "drag-drop-inside">
91
- <p class="drag-drop-info">%s</p>
92
- <p>%s</p>
93
- <p class="drag-drop-buttons"><input id="%s-browse-button" type="button" value="%s" class="button" /></p>
94
- </div>
95
- </div>',
96
- $field['id'],
97
- implode( ' ', $classes ),
98
- wp_create_nonce( "rwmb-upload-images_{$field['id']}" ),
99
- esc_attr( wp_json_encode( $field['js_options'] ) ),
100
- $i18n_drop,
101
- $i18n_or,
102
- $field['id'],
103
- $i18n_select
104
- );
105
-
106
- return $html;
107
- }
108
-
109
- /**
110
- * Get field value.
111
- * It's the combination of new (uploaded) images and saved images
112
- *
113
- * @param array $new
114
- * @param array $old
115
- * @param int $post_id
116
- * @param array $field
117
- *
118
- * @return array
119
- */
120
- static function value( $new, $old, $post_id, $field )
121
- {
122
- $new = (array) $new;
123
- return array_unique( array_merge( $old, $new ) );
124
- }
125
-
126
- /**
127
- * Normalize parameters for field.
128
- *
129
- * @param array $field
130
- * @return array
131
- */
132
- static function normalize( $field )
133
- {
134
- $field['js_options'] = array(
135
- 'runtimes' => 'html5,silverlight,flash,html4',
136
- 'file_data_name' => 'async-upload',
137
- //'container' => $field['id'] . '-container',
138
- 'browse_button' => $field['id'] . '-browse-button',
139
- 'drop_element' => $field['id'] . '-dragdrop',
140
- 'multiple_queues' => true,
141
- 'max_file_size' => wp_max_upload_size() . 'b',
142
- 'url' => admin_url( 'admin-ajax.php' ),
143
- 'flash_swf_url' => includes_url( 'js/plupload/plupload.flash.swf' ),
144
- 'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
145
- 'multipart' => true,
146
- 'urlstream_upload' => true,
147
- 'filters' => array(
148
- array(
149
- 'title' => _x( 'Allowed Image Files', 'image upload', 'meta-box' ),
150
- 'extensions' => 'jpg,jpeg,gif,png',
151
- ),
152
- ),
153
- 'multipart_params' => array(
154
- 'field_id' => $field['id'],
155
- 'action' => 'rwmb_plupload_image_upload',
156
- ),
157
- );
158
- $field = parent::normalize( $field );
159
-
160
- return $field;
161
- }
162
- }
2
  /**
3
  * Image upload field which uses plupload library to drag and drop files to upload.
4
  */
5
+ class RWMB_Plupload_Image_Field extends RWMB_Image_Upload_Field {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/fields/post.php CHANGED
@@ -11,18 +11,20 @@ class RWMB_Post_Field extends RWMB_Object_Choice_Field
11
  *
12
  * @return array
13
  */
14
- static function normalize( $field )
15
  {
16
  /**
17
  * Set default field args
18
  */
 
19
  $field = wp_parse_args( $field, array(
20
  'post_type' => 'post',
21
- 'field_type' => 'select',
22
  'parent' => false,
23
- 'query_args' => array(),
24
  ) );
25
 
 
 
 
26
  /**
27
  * Set default placeholder
28
  * - If multiple post types: show 'Select a post'
@@ -31,9 +33,9 @@ class RWMB_Post_Field extends RWMB_Object_Choice_Field
31
  if ( empty( $field['placeholder'] ) )
32
  {
33
  $field['placeholder'] = __( 'Select a post', 'meta-box' );
34
- if ( is_string( $field['post_type'] ) && post_type_exists( $field['post_type'] ) )
35
  {
36
- $post_type_object = get_post_type_object( $field['post_type'] );
37
  $field['placeholder'] = sprintf( __( 'Select a %s', 'meta-box' ), $post_type_object->labels->singular_name );
38
  }
39
  }
@@ -50,14 +52,10 @@ class RWMB_Post_Field extends RWMB_Object_Choice_Field
50
  /**
51
  * Set default query args
52
  */
53
- $field['query_args'] = wp_parse_args( $field['query_args'], array(
54
  'post_status' => 'publish',
55
  'posts_per_page' => - 1,
56
  ) );
57
- $field['query_args']['post_type'] = $field['post_type'];
58
-
59
-
60
- $field = parent::normalize( $field );
61
 
62
  return $field;
63
  }
@@ -67,7 +65,7 @@ class RWMB_Post_Field extends RWMB_Object_Choice_Field
67
  *
68
  * @return array
69
  */
70
- static function get_db_fields()
71
  {
72
  return array(
73
  'parent' => 'post_parent',
@@ -89,7 +87,7 @@ class RWMB_Post_Field extends RWMB_Object_Choice_Field
89
  *
90
  * @return array
91
  */
92
- static function meta( $post_id, $saved, $field )
93
  {
94
  if ( isset( $field['parent'] ) && $field['parent'] )
95
  {
@@ -107,24 +105,23 @@ class RWMB_Post_Field extends RWMB_Object_Choice_Field
107
  *
108
  * @return array
109
  */
110
- static function get_options( $field )
111
  {
112
  $query = new WP_Query( $field['query_args'] );
113
  return $query->have_posts() ? $query->posts : array();
114
  }
115
 
116
  /**
117
- * Get post link to display in the frontend
118
- *
119
- * @param int $value Option value, e.g. post ID
120
- * @param int $index Array index
121
- * @param array $field Field parameter
122
- *
123
- * @return string
124
- */
125
- static function get_option_label( &$value, $index, $field )
126
- {
127
- $value = sprintf(
128
  '<a href="%s" title="%s">%s</a>',
129
  esc_url( get_permalink( $value ) ),
130
  the_title_attribute( array(
@@ -133,5 +130,5 @@ class RWMB_Post_Field extends RWMB_Object_Choice_Field
133
  ) ),
134
  get_the_title( $value )
135
  );
136
- }
137
  }
11
  *
12
  * @return array
13
  */
14
+ public static function normalize( $field )
15
  {
16
  /**
17
  * Set default field args
18
  */
19
+ $field = parent::normalize( $field );
20
  $field = wp_parse_args( $field, array(
21
  'post_type' => 'post',
 
22
  'parent' => false,
 
23
  ) );
24
 
25
+ if ( ! isset( $field['query_args']['post_type'] ) )
26
+ $field['query_args']['post_type'] = $field['post_type'];
27
+
28
  /**
29
  * Set default placeholder
30
  * - If multiple post types: show 'Select a post'
33
  if ( empty( $field['placeholder'] ) )
34
  {
35
  $field['placeholder'] = __( 'Select a post', 'meta-box' );
36
+ if ( is_string( $field['query_args']['post_type'] ) && post_type_exists( $field['query_args']['post_type'] ) )
37
  {
38
+ $post_type_object = get_post_type_object( $field['query_args']['post_type'] );
39
  $field['placeholder'] = sprintf( __( 'Select a %s', 'meta-box' ), $post_type_object->labels->singular_name );
40
  }
41
  }
52
  /**
53
  * Set default query args
54
  */
55
+ $field['query_args'] = wp_parse_args( $field['query_args'], array(
56
  'post_status' => 'publish',
57
  'posts_per_page' => - 1,
58
  ) );
 
 
 
 
59
 
60
  return $field;
61
  }
65
  *
66
  * @return array
67
  */
68
+ public static function get_db_fields()
69
  {
70
  return array(
71
  'parent' => 'post_parent',
87
  *
88
  * @return array
89
  */
90
+ public static function meta( $post_id, $saved, $field )
91
  {
92
  if ( isset( $field['parent'] ) && $field['parent'] )
93
  {
105
  *
106
  * @return array
107
  */
108
+ public static function get_options( $field )
109
  {
110
  $query = new WP_Query( $field['query_args'] );
111
  return $query->have_posts() ? $query->posts : array();
112
  }
113
 
114
  /**
115
+ * Get option label
116
+ *
117
+ * @param string $value Option value
118
+ * @param array $field Field parameter
119
+ *
120
+ * @return string
121
+ */
122
+ public static function get_option_label( $value, $field )
123
+ {
124
+ return sprintf(
 
125
  '<a href="%s" title="%s">%s</a>',
126
  esc_url( get_permalink( $value ) ),
127
  the_title_attribute( array(
130
  ) ),
131
  get_the_title( $value )
132
  );
133
+ }
134
  }
inc/fields/radio.php CHANGED
@@ -2,68 +2,18 @@
2
  /**
3
  * Radio field class.
4
  */
5
- class RWMB_Radio_Field extends RWMB_Input_Field
6
  {
7
  /**
8
- * Get field HTML
9
- *
10
- * @param mixed $meta
11
  * @param array $field
12
- *
13
- * @return string
14
- */
15
- static function html( $meta, $field )
16
- {
17
- $html = array();
18
- $tpl = '<label><input %s %s> %s</label>';
19
-
20
- foreach ( $field['options'] as $value => $label )
21
- {
22
- $attributes = self::get_attributes( $field, $value );
23
- $html[] = sprintf(
24
- $tpl,
25
- self::render_attributes( $attributes ),
26
- checked( $value, $meta, false ),
27
- $label
28
- );
29
- }
30
-
31
- return implode( ' ', $html );
32
- }
33
-
34
- /**
35
- * Get the attributes for a field
36
- *
37
- * @param array $field
38
- * @param mixed $value
39
- *
40
  * @return array
41
  */
42
- static function get_attributes( $field, $value = null )
43
  {
44
- $attributes = parent::get_attributes( $field, $value );
45
- $attributes['list'] = false;
46
- $attributes['id'] = false;
47
- $attributes['type'] = 'radio';
48
-
49
- return $attributes;
50
- }
51
 
52
- /**
53
- * Output the field value
54
- * Display option name instead of option value
55
- *
56
- * @use self::meta()
57
- *
58
- * @param array $field Field parameters
59
- * @param array $args Additional arguments. Rarely used. See specific fields for details
60
- * @param int|null $post_id Post ID. null for current post. Optional.
61
- *
62
- * @return mixed Field value
63
- */
64
- static function the_value( $field, $args = array(), $post_id = null )
65
- {
66
- $value = parent::get_value( $field, $args, $post_id );
67
- return empty( $value ) ? '' : $field['options'][$value];
68
  }
69
  }
2
  /**
3
  * Radio field class.
4
  */
5
+ class RWMB_Radio_Field extends RWMB_Input_List_Field
6
  {
7
  /**
8
+ * Normalize parameters for field
 
 
9
  * @param array $field
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  * @return array
11
  */
12
+ static function normalize( $field )
13
  {
14
+ $field['multiple'] = false;
15
+ $field = parent::normalize( $field );
 
 
 
 
 
16
 
17
+ return $field;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  }
19
  }
inc/fields/select-advanced.php CHANGED
@@ -7,8 +7,9 @@ class RWMB_Select_Advanced_Field extends RWMB_Select_Field
7
  /**
8
  * Enqueue scripts and styles
9
  */
10
- static function admin_enqueue_scripts()
11
  {
 
12
  wp_enqueue_style( 'rwmb-select2', RWMB_CSS_URL . 'select2/select2.css', array(), '4.0.1' );
13
  wp_enqueue_style( 'rwmb-select-advanced', RWMB_CSS_URL . 'select-advanced.css', array(), RWMB_VER );
14
 
@@ -18,24 +19,29 @@ class RWMB_Select_Advanced_Field extends RWMB_Select_Field
18
  }
19
 
20
  /**
21
- * Get field HTML
22
  *
23
  * @param mixed $meta
24
  * @param array $field
 
 
 
25
  * @return string
26
  */
27
- static function html( $meta, $field )
28
  {
29
- $attributes = self::get_attributes( $field, $meta );
30
- $html = sprintf(
 
31
  '<select %s>',
32
  self::render_attributes( $attributes )
33
  );
34
- $html .= '<option></option>';
35
- $html .= self::options_html( $field, $meta );
36
- $html .= '</select>';
37
- $html .= self::get_select_all_html( $field['multiple'] );
38
- return $html;
 
39
  }
40
 
41
  /**
@@ -44,7 +50,7 @@ class RWMB_Select_Advanced_Field extends RWMB_Select_Field
44
  * @param array $field
45
  * @return array
46
  */
47
- static function normalize( $field )
48
  {
49
  $field = wp_parse_args( $field, array(
50
  'js_options' => array(),
@@ -69,7 +75,7 @@ class RWMB_Select_Advanced_Field extends RWMB_Select_Field
69
  * @param mixed $value
70
  * @return array
71
  */
72
- static function get_attributes( $field, $value = null )
73
  {
74
  $attributes = parent::get_attributes( $field, $value );
75
  $attributes = wp_parse_args( $attributes, array(
7
  /**
8
  * Enqueue scripts and styles
9
  */
10
+ public static function admin_enqueue_scripts()
11
  {
12
+ parent::admin_enqueue_scripts();
13
  wp_enqueue_style( 'rwmb-select2', RWMB_CSS_URL . 'select2/select2.css', array(), '4.0.1' );
14
  wp_enqueue_style( 'rwmb-select-advanced', RWMB_CSS_URL . 'select-advanced.css', array(), RWMB_VER );
15
 
19
  }
20
 
21
  /**
22
+ * Walk options
23
  *
24
  * @param mixed $meta
25
  * @param array $field
26
+ * @param mixed $options
27
+ * @param mixed $db_fields
28
+ *
29
  * @return string
30
  */
31
+ public static function walk( $options, $db_fields, $meta, $field )
32
  {
33
+ $attributes = call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'get_attributes' ), $field, $meta );
34
+ $walker = new RWMB_Select_Walker( $db_fields, $field, $meta );
35
+ $output = sprintf(
36
  '<select %s>',
37
  self::render_attributes( $attributes )
38
  );
39
+
40
+ $output .= '<option></option>';
41
+ $output .= $walker->walk( $options, $field['flatten'] ? - 1 : 0 );
42
+ $output .= '</select>';
43
+ $output .= self::get_select_all_html( $field );
44
+ return $output;
45
  }
46
 
47
  /**
50
  * @param array $field
51
  * @return array
52
  */
53
+ public static function normalize( $field )
54
  {
55
  $field = wp_parse_args( $field, array(
56
  'js_options' => array(),
75
  * @param mixed $value
76
  * @return array
77
  */
78
+ public static function get_attributes( $field, $value = null )
79
  {
80
  $attributes = parent::get_attributes( $field, $value );
81
  $attributes = wp_parse_args( $attributes, array(
inc/fields/select-tree.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class RWMB_Select_Tree_Field extends RWMB_Select_Field
4
+ {
5
+ /**
6
+ * Walk options
7
+ *
8
+ * @param mixed $meta
9
+ * @param array $field
10
+ * @param mixed $options
11
+ * @param mixed $db_fields
12
+ *
13
+ * @return string
14
+ */
15
+ static function walk( $options, $db_fields, $meta, $field )
16
+ {
17
+ $walker = new RWMB_Select_Tree_Walker( $db_fields, $field, $meta );
18
+ return $walker->walk( $options );
19
+ }
20
+
21
+ /**
22
+ * Enqueue scripts and styles
23
+ */
24
+ static function admin_enqueue_scripts()
25
+ {
26
+ parent::admin_enqueue_scripts();
27
+ wp_enqueue_style( 'rwmb-select-tree', RWMB_CSS_URL . 'select-tree.css', array( 'rwmb-select' ), RWMB_VER );
28
+ wp_enqueue_script( 'rwmb-select-tree', RWMB_JS_URL . 'select-tree.js', array( 'rwmb-select' ), RWMB_VER, true );
29
+ }
30
+
31
+ /**
32
+ * Normalize parameters for field
33
+ *
34
+ * @param array $field
35
+ *
36
+ * @return array
37
+ */
38
+ static function normalize( $field )
39
+ {
40
+ $field['multiple'] = true;
41
+ $field['size'] = 0;
42
+ $field = parent::normalize( $field );
43
+
44
+ return $field;
45
+ }
46
+
47
+ /**
48
+ * Get the attributes for a field
49
+ *
50
+ * @param array $field
51
+ * @param mixed $value
52
+ *
53
+ * @return array
54
+ */
55
+ static function get_attributes( $field, $value = null )
56
+ {
57
+ $attributes = parent::get_attributes( $field, $value );
58
+ $attributes['multiple'] = false;
59
+ $attributes['id'] = false;
60
+
61
+ return $attributes;
62
+ }
63
+ }
inc/fields/select.php CHANGED
@@ -2,59 +2,60 @@
2
  /**
3
  * Select field class.
4
  */
5
- class RWMB_Select_Field extends RWMB_Field
6
  {
7
  /**
8
  * Enqueue scripts and styles
9
  */
10
- static function admin_enqueue_scripts()
11
  {
12
  wp_enqueue_style( 'rwmb-select', RWMB_CSS_URL . 'select.css', array(), RWMB_VER );
13
  wp_enqueue_script( 'rwmb-select', RWMB_JS_URL . 'select.js', array(), RWMB_VER, true );
14
  }
15
 
16
  /**
17
- * Get field HTML
18
  *
19
  * @param mixed $meta
20
  * @param array $field
 
 
21
  *
22
  * @return string
23
  */
24
- static function html( $meta, $field )
25
  {
26
- $attributes = call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'get_attributes' ), $field, $meta );
27
- $html = sprintf(
 
28
  '<select %s>',
29
  self::render_attributes( $attributes )
30
  );
31
-
32
- $html .= $field['placeholder'] ? "<option value=''>{$field['placeholder']}</option>" : '<option></option>';
33
-
34
- $html .= self::options_html( $field, $meta );
35
-
36
- $html .= '</select>';
37
-
38
- $html .= self::get_select_all_html( $field['multiple'] );
39
-
40
- return $html;
41
  }
42
 
43
  /**
44
  * Normalize parameters for field
45
  *
46
  * @param array $field
47
- *
48
  * @return array
49
  */
50
- static function normalize( $field )
51
  {
52
  $field = parent::normalize( $field );
 
53
  $field = wp_parse_args( $field, array(
54
- 'size' => $field['multiple'] ? 5 : 0,
 
55
  ) );
56
 
57
- $field['field_name'] .= ! $field['clone'] && $field['multiple'] ? '[]' : '';
58
  return $field;
59
  }
60
 
@@ -66,7 +67,7 @@ class RWMB_Select_Field extends RWMB_Field
66
  *
67
  * @return array
68
  */
69
- static function get_attributes( $field, $value = null )
70
  {
71
  $attributes = parent::get_attributes( $field, $value );
72
  $attributes = wp_parse_args( $attributes, array(
@@ -77,116 +78,17 @@ class RWMB_Select_Field extends RWMB_Field
77
  return $attributes;
78
  }
79
 
80
- /**
81
- * Creates html for options
82
- *
83
- * @param array $field
84
- * @param mixed $meta
85
- *
86
- * @return array
87
- */
88
- static function options_html( $field, $meta )
89
- {
90
- $html = '';
91
-
92
- $option = '<option value="%s"%s>%s</option>';
93
-
94
- foreach ( $field['options'] as $value => $label )
95
- {
96
- $html .= sprintf(
97
- $option,
98
- $value,
99
- selected( in_array( (string) $value, (array) $meta, true ), true, false ),
100
- $label
101
- );
102
- }
103
-
104
- return $html;
105
- }
106
-
107
- /**
108
- * Output the field value
109
- * Display unordered list of option labels, not option values
110
- *
111
- * @param array $field Field parameters
112
- * @param array $args Additional arguments. Not used for these fields.
113
- * @param int|null $post_id Post ID. null for current post. Optional.
114
- *
115
- * @return string Link(s) to post
116
- */
117
- static function the_value( $field, $args = array(), $post_id = null )
118
- {
119
- $value = self::get_value( $field, $args, $post_id );
120
- if ( ! $value )
121
- return '';
122
-
123
- $function = array( RW_Meta_Box::get_class_name( $field ), 'get_option_label' );
124
-
125
- if ( $field['clone'] )
126
- {
127
- $output = '<ul>';
128
- if ( $field['multiple'] )
129
- {
130
- foreach ( $value as $subvalue )
131
- {
132
- $output .= '<li>';
133
- array_walk_recursive( $subvalue, $function, $field );
134
- $output .= '<ul><li>' . implode( '</li><li>', $subvalue ) . '</li></ul>';
135
- $output .= '</li>';
136
- }
137
- }
138
- else
139
- {
140
- array_walk_recursive( $value, $function, $field );
141
- $output = '<li>' . implode( '</li><li>', $value ) . '</li>';
142
- }
143
- $output .= '</ul>';
144
- }
145
- else
146
- {
147
- if ( $field['multiple'] )
148
- {
149
- array_walk_recursive( $value, $function, $field );
150
- $output = '<ul><li>' . implode( '</li><li>', $value ) . '</li></ul>';
151
- }
152
- else
153
- {
154
- call_user_func_array( $function, array( &$value, 0, $field ) );
155
- $output = $value;
156
- }
157
- }
158
-
159
- return $output;
160
- }
161
-
162
- /**
163
- * Get option label to display in the frontend
164
- *
165
- * @param int $value Option value
166
- * @param int $index Array index
167
- * @param array $field Field parameter
168
- *
169
- * @return string
170
- */
171
- static function get_option_label( &$value, $index, $field )
172
- {
173
- $value = $field['options'][$value];
174
- }
175
-
176
  /**
177
  * Get html for select all|none for multiple select
178
  *
179
- * @param $multiple
180
- *
181
  * @return string
182
  */
183
- static function get_select_all_html( $multiple )
184
  {
185
- if ( $multiple === true )
186
  {
187
- return '<div class="rwmb-select-all-none">
188
- ' . __( 'Select', 'meta-box' ) . ': <a data-type="all" href="#">' . __( 'All', 'meta-box' ) . '</a> | <a data-type="none" href="#">' . __( 'None', 'meta-box' ) . '</a>
189
- </div>';
190
  }
191
  return '';
192
  }
2
  /**
3
  * Select field class.
4
  */
5
+ class RWMB_Select_Field extends RWMB_Choice_Field
6
  {
7
  /**
8
  * Enqueue scripts and styles
9
  */
10
+ public static function admin_enqueue_scripts()
11
  {
12
  wp_enqueue_style( 'rwmb-select', RWMB_CSS_URL . 'select.css', array(), RWMB_VER );
13
  wp_enqueue_script( 'rwmb-select', RWMB_JS_URL . 'select.js', array(), RWMB_VER, true );
14
  }
15
 
16
  /**
17
+ * Walk options
18
  *
19
  * @param mixed $meta
20
  * @param array $field
21
+ * @param mixed $options
22
+ * @param mixed $db_fields
23
  *
24
  * @return string
25
  */
26
+ public static function walk( $options, $db_fields, $meta, $field )
27
  {
28
+ $attributes = call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'get_attributes' ), $field, $meta );
29
+ $walker = new RWMB_Select_Walker( $db_fields, $field, $meta );
30
+ $output = sprintf(
31
  '<select %s>',
32
  self::render_attributes( $attributes )
33
  );
34
+ if ( false === $field['multiple'] )
35
+ {
36
+ $output .= isset( $field['placeholder'] ) ? "<option value=''>{$field['placeholder']}</option>" : '<option></option>';
37
+ }
38
+ $output .= $walker->walk( $options, $field['flatten'] ? - 1 : 0 );
39
+ $output .= '</select>';
40
+ $output .= self::get_select_all_html( $field );
41
+ return $output;
 
 
42
  }
43
 
44
  /**
45
  * Normalize parameters for field
46
  *
47
  * @param array $field
 
48
  * @return array
49
  */
50
+ public static function normalize( $field )
51
  {
52
  $field = parent::normalize( $field );
53
+ $field = $field['multiple'] ? RWMB_Multiple_Values_Field::normalize( $field ) : $field;
54
  $field = wp_parse_args( $field, array(
55
+ 'size' => $field['multiple'] ? 5 : 0,
56
+ 'select_all_none' => false,
57
  ) );
58
 
 
59
  return $field;
60
  }
61
 
67
  *
68
  * @return array
69
  */
70
+ public static function get_attributes( $field, $value = null )
71
  {
72
  $attributes = parent::get_attributes( $field, $value );
73
  $attributes = wp_parse_args( $attributes, array(
78
  return $attributes;
79
  }
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  /**
82
  * Get html for select all|none for multiple select
83
  *
84
+ * @param array $field
 
85
  * @return string
86
  */
87
+ public static function get_select_all_html( $field )
88
  {
89
+ if ( $field['multiple'] && $field['select_all_none'] )
90
  {
91
+ return '<div class="rwmb-select-all-none">' . __( 'Select', 'meta-box' ) . ': <a data-type="all" href="#">' . __( 'All', 'meta-box' ) . '</a> | <a data-type="none" href="#">' . __( 'None', 'meta-box' ) . '</a></div>';
 
 
92
  }
93
  return '';
94
  }
inc/fields/taxonomy.php CHANGED
@@ -25,10 +25,9 @@ class RWMB_Taxonomy_Field extends RWMB_Object_Choice_Field
25
  /**
26
  * Set default field args
27
  */
 
28
  $field = wp_parse_args( $field, array(
29
  'taxonomy' => 'category',
30
- 'field_type' => 'select',
31
- 'query_args' => array(),
32
  ) );
33
 
34
  /**
@@ -58,7 +57,6 @@ class RWMB_Taxonomy_Field extends RWMB_Object_Choice_Field
58
  */
59
  $field['clone'] = false;
60
 
61
- $field = parent::normalize( $field );
62
  return $field;
63
  }
64
 
@@ -147,32 +145,16 @@ class RWMB_Taxonomy_Field extends RWMB_Object_Choice_Field
147
  }
148
 
149
  /**
150
- * Output the field value
151
- * Display unordered list of option labels, not option values
152
- *
153
- * @param array $field Field parameters
154
- * @param array $args Additional arguments. Not used for these fields.
155
- * @param int|null $post_id Post ID. null for current post. Optional.
156
- *
157
- * @return string Link(s) to post
158
- */
159
- static function the_value( $field, $args = array(), $post_id = null )
160
- {
161
- return RWMB_Select_Field::the_value( $field, $args, $post_id );
162
- }
163
-
164
- /**
165
- * Get post link to display in the frontend
166
  *
167
- * @param object $value Option value, e.g. term object
168
- * @param int $index Array index
169
- * @param array $field Field parameter
170
  *
171
  * @return string
172
  */
173
- static function get_option_label( &$value, $index, $field )
174
  {
175
- $value = sprintf(
176
  '<a href="%s" title="%s">%s</a>',
177
  esc_url( get_term_link( $value ) ),
178
  esc_attr( $value->name ),
25
  /**
26
  * Set default field args
27
  */
28
+ $field = parent::normalize( $field );
29
  $field = wp_parse_args( $field, array(
30
  'taxonomy' => 'category',
 
 
31
  ) );
32
 
33
  /**
57
  */
58
  $field['clone'] = false;
59
 
 
60
  return $field;
61
  }
62
 
145
  }
146
 
147
  /**
148
+ * Get option label
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  *
150
+ * @param string $value Option value
151
+ * @param array $field Field parameter
 
152
  *
153
  * @return string
154
  */
155
+ static function get_option_label( $value, $field )
156
  {
157
+ return sprintf(
158
  '<a href="%s" title="%s">%s</a>',
159
  esc_url( get_term_link( $value ) ),
160
  esc_attr( $value->name ),
inc/fields/thickbox-image.php CHANGED
@@ -1,16 +1,36 @@
1
  <?php
2
  /**
3
  * Image upload field which uses thickbox library to upload.
4
- * @deprecated
5
  */
6
  class RWMB_Thickbox_Image_Field extends RWMB_Image_Field
7
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  /**
9
  * Enqueue scripts and styles
10
- *
11
- * @return void
12
  */
13
- static function admin_enqueue_scripts()
14
  {
15
  parent::admin_enqueue_scripts();
16
 
@@ -28,12 +48,12 @@ class RWMB_Thickbox_Image_Field extends RWMB_Image_Field
28
  *
29
  * @return string
30
  */
31
- static function html( $meta, $field )
32
  {
33
  $i18n_title = apply_filters( 'rwmb_thickbox_image_upload_string', _x( 'Upload Images', 'image upload', 'meta-box' ), $field );
34
 
35
  // Uploaded images
36
- $html = self::get_uploaded_images( $meta, $field );
37
 
38
  // Show form upload
39
  $html .= "<a href='#' class='button rwmb-thickbox-upload' data-field_id='{$field['id']}'>{$i18n_title}</a>";
@@ -52,7 +72,7 @@ class RWMB_Thickbox_Image_Field extends RWMB_Image_Field
52
  *
53
  * @return array
54
  */
55
- static function value( $new, $old, $post_id, $field )
56
  {
57
  return array_unique( array_merge( $old, $new ) );
58
  }
1
  <?php
2
  /**
3
  * Image upload field which uses thickbox library to upload.
4
+ * @deprecated Use image_advanced instead
5
  */
6
  class RWMB_Thickbox_Image_Field extends RWMB_Image_Field
7
  {
8
+ /**
9
+ * Add custom actions for the field.
10
+ */
11
+ public static function add_actions()
12
+ {
13
+ parent::add_actions();
14
+ add_filter( 'get_media_item_args', array( __CLASS__, 'allow_img_insertion' ) );
15
+ }
16
+
17
+ /**
18
+ * Always enable insert to post button in the popup
19
+ * @link https://github.com/rilwis/meta-box/issues/809
20
+ * @link http://wordpress.stackexchange.com/q/22175/2051
21
+ * @param array $vars
22
+ * @return array
23
+ */
24
+ public static function allow_img_insertion( $vars )
25
+ {
26
+ $vars['send'] = true; // 'send' as in "Send to Editor"
27
+ return $vars;
28
+ }
29
+
30
  /**
31
  * Enqueue scripts and styles
 
 
32
  */
33
+ public static function admin_enqueue_scripts()
34
  {
35
  parent::admin_enqueue_scripts();
36
 
48
  *
49
  * @return string
50
  */
51
+ public static function html( $meta, $field )
52
  {
53
  $i18n_title = apply_filters( 'rwmb_thickbox_image_upload_string', _x( 'Upload Images', 'image upload', 'meta-box' ), $field );
54
 
55
  // Uploaded images
56
+ $html = parent::get_uploaded_images( $meta, $field );
57
 
58
  // Show form upload
59
  $html .= "<a href='#' class='button rwmb-thickbox-upload' data-field_id='{$field['id']}'>{$i18n_title}</a>";
72
  *
73
  * @return array
74
  */
75
+ public static function value( $new, $old, $post_id, $field )
76
  {
77
  return array_unique( array_merge( $old, $new ) );
78
  }
inc/fields/time.php CHANGED
@@ -2,57 +2,18 @@
2
  /**
3
  * Time field class.
4
  */
5
- class RWMB_Time_Field extends RWMB_Text_Field
6
  {
7
  /**
8
  * Enqueue scripts and styles
9
- */
10
- static function admin_enqueue_scripts()
11
- {
12
- $url = RWMB_CSS_URL . 'jqueryui';
13
- wp_register_style( 'jquery-ui-core', "{$url}/jquery.ui.core.css", array(), '1.8.17' );
14
- wp_register_style( 'jquery-ui-theme', "{$url}/jquery.ui.theme.css", array(), '1.8.17' );
15
- wp_register_style( 'jquery-ui-datepicker', "{$url}/jquery.ui.datepicker.css", array( 'jquery-ui-core', 'jquery-ui-theme' ), '1.8.17' );
16
- wp_register_style( 'wp-datepicker', RWMB_CSS_URL . 'datepicker.css', array( 'jquery-ui-core', 'jquery-ui-theme' ), '1.8.17' );
17
- wp_register_style( 'jquery-ui-slider', "{$url}/jquery.ui.slider.css", array( 'jquery-ui-core', 'jquery-ui-theme' ), '1.8.17' );
18
- wp_enqueue_style( 'jquery-ui-timepicker', "{$url}/jquery-ui-timepicker-addon.min.css", array( 'jquery-ui-datepicker', 'jquery-ui-slider', 'wp-datepicker' ), '1.5.0' );
19
-
20
- $url = RWMB_JS_URL . 'jqueryui';
21
- wp_register_script( 'jquery-ui-timepicker', "{$url}/jquery-ui-timepicker-addon.min.js", array( 'jquery-ui-datepicker', 'jquery-ui-slider' ), '1.5.0', true );
22
-
23
- /**
24
- * Localization
25
- * Use 1 minified JS file which contains all languages for simpilicity (in version < 4.4.2 we use separated JS files).
26
- * The language is set in Javascript
27
- *
28
- * Note: we use full locale (de-DE) and fallback to short locale (de)
29
- */
30
- $locale = str_replace( '_', '-', get_locale() );
31
- $locale_short = substr( $locale, 0, 2 );
32
- wp_register_script( 'jquery-ui-timepicker-i18n', "{$url}/jquery-ui-timepicker-addon-i18n.min.js", array( 'jquery-ui-timepicker' ), '1.5.0', true );
33
-
34
- wp_enqueue_script( 'rwmb-time', RWMB_JS_URL . 'time.js', array( 'jquery-ui-timepicker-i18n' ), RWMB_VER, true );
35
- wp_localize_script( 'rwmb-time', 'RWMB_Timepicker', array(
36
- 'locale' => $locale,
37
- 'localeShort' => $locale_short,
38
- ) );
39
- }
40
-
41
- /**
42
- * Get field HTML
43
  *
44
- * @param mixed $meta
45
- * @param array $field
46
- * @return string
47
  */
48
- static function html( $meta, $field )
49
  {
50
- $output = parent::html( $meta, $field );
51
- if ( $field['inline'] )
52
- {
53
- $output .= '<div class="rwmb-time-inline"></div>';
54
- }
55
- return $output;
56
  }
57
 
58
  /**
@@ -61,37 +22,10 @@ class RWMB_Time_Field extends RWMB_Text_Field
61
  * @param array $field
62
  * @return array
63
  */
64
- static function normalize( $field )
65
  {
66
- $field = wp_parse_args( $field, array(
67
- 'js_options' => array(),
68
- 'inline' => false,
69
- ) );
70
-
71
- // Deprecate 'format', but keep it for backward compatible
72
- // Use 'js_options' instead
73
- $field['js_options'] = wp_parse_args( $field['js_options'], array(
74
- 'showButtonPanel' => true,
75
- 'timeFormat' => empty( $field['format'] ) ? 'HH:mm' : $field['format'],
76
- ) );
77
-
78
  $field = parent::normalize( $field );
 
79
  return $field;
80
  }
81
-
82
- /**
83
- * Get the attributes for a field
84
- *
85
- * @param array $field
86
- * @param mixed $value
87
- * @return array
88
- */
89
- static function get_attributes( $field, $value = null )
90
- {
91
- $attributes = parent::get_attributes( $field, $value );
92
- $attributes = wp_parse_args( $attributes, array(
93
- 'data-options' => wp_json_encode( $field['js_options'] ),
94
- ) );
95
- return $attributes;
96
- }
97
  }
2
  /**
3
  * Time field class.
4
  */
5
+ class RWMB_Time_Field extends RWMB_Datetime_Field
6
  {
7
  /**
8
  * Enqueue scripts and styles
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  *
10
+ * @return void
 
 
11
  */
12
+ public static function admin_enqueue_scripts()
13
  {
14
+ parent::admin_register_scripts();
15
+ wp_enqueue_style( 'jquery-ui-timepicker' );
16
+ wp_enqueue_script( 'rwmb-time' );
 
 
 
17
  }
18
 
19
  /**
22
  * @param array $field
23
  * @return array
24
  */
25
+ public static function normalize( $field )
26
  {
 
 
 
 
 
 
 
 
 
 
 
 
27
  $field = parent::normalize( $field );
28
+ $field['js_options']['timeFormat'] = empty( $field['format'] ) ? $field['js_options']['timeFormat'] : $field['format'];
29
  return $field;
30
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  }
inc/fields/user.php CHANGED
@@ -16,10 +16,7 @@ class RWMB_User_Field extends RWMB_Object_Choice_Field
16
  /**
17
  * Set default field args
18
  */
19
- $field = wp_parse_args( $field, array(
20
- 'field_type' => 'select',
21
- 'query_args' => array(),
22
- ) );
23
 
24
  /**
25
  * Prevent select tree for user since it's not hierarchical
@@ -45,7 +42,6 @@ class RWMB_User_Field extends RWMB_Object_Choice_Field
45
  'role' => '',
46
  'fields' => 'all',
47
  ) );
48
- $field = parent::normalize( $field );
49
 
50
  return $field;
51
  }
@@ -78,17 +74,16 @@ class RWMB_User_Field extends RWMB_Object_Choice_Field
78
  }
79
 
80
  /**
81
- * Get option label to display in the frontend
82
  *
83
- * @param int $value Option value
84
- * @param int $index Array index
85
- * @param array $field Field parameter
86
  *
87
  * @return string
88
  */
89
- static function get_option_label( &$value, $index, $field )
90
  {
91
  $user = get_userdata( $value );
92
- $value = '<a href="' . get_author_posts_url( $value ) . '">' . $user->display_name . '</a>';
93
  }
94
  }
16
  /**
17
  * Set default field args
18
  */
19
+ $field = parent::normalize( $field );
 
 
 
20
 
21
  /**
22
  * Prevent select tree for user since it's not hierarchical
42
  'role' => '',
43
  'fields' => 'all',
44
  ) );
 
45
 
46
  return $field;
47
  }
74
  }
75
 
76
  /**
77
+ * Get option label
78
  *
79
+ * @param string $value Option value
80
+ * @param array $field Field parameter
 
81
  *
82
  * @return string
83
  */
84
+ static function get_option_label( $value, $field )
85
  {
86
  $user = get_userdata( $value );
87
+ return '<a href="' . get_author_posts_url( $value ) . '">' . $user->display_name . '</a>';
88
  }
89
  }
inc/functions.php CHANGED
@@ -20,14 +20,12 @@ if ( ! function_exists( 'rwmb_meta' ) )
20
  * If meta boxes is registered in the backend only, we can't get field's params
21
  * This is for backward compatibility with version < 4.8.0
22
  */
23
- if ( false === RWMB_Helper::find_field( $key ) )
 
24
  {
25
  return apply_filters( 'rwmb_meta', RWMB_Helper::meta( $key, $args, $post_id ) );
26
  }
27
- $args = wp_parse_args( $args, array(
28
- 'type' => 'text',
29
- ) );
30
- $meta = in_array( $args['type'], array( 'oembed', 'map' ) ) ?
31
  rwmb_the_value( $key, $args, $post_id, false ) :
32
  rwmb_get_value( $key, $args, $post_id );
33
  return apply_filters( 'rwmb_meta', $meta, $key, $args, $post_id );
@@ -62,7 +60,7 @@ if ( ! function_exists( 'rwmb_get_value' ) )
62
  * @param array $args Additional arguments. Rarely used. See specific fields for details
63
  * @param int|null $post_id Post ID. null for current post. Optional.
64
  */
65
- $value = apply_filters( 'rwmb_get_value', $value, $field, $args, $post_id );
66
 
67
  return $value;
68
  }
20
  * If meta boxes is registered in the backend only, we can't get field's params
21
  * This is for backward compatibility with version < 4.8.0
22
  */
23
+ $field = RWMB_Helper::find_field( $key );
24
+ if ( false === $field || isset( $args['type'] ) )
25
  {
26
  return apply_filters( 'rwmb_meta', RWMB_Helper::meta( $key, $args, $post_id ) );
27
  }
28
+ $meta = in_array( $field['type'], array( 'oembed', 'map' ) ) ?
 
 
 
29
  rwmb_the_value( $key, $args, $post_id, false ) :
30
  rwmb_get_value( $key, $args, $post_id );
31
  return apply_filters( 'rwmb_meta', $meta, $key, $args, $post_id );
60
  * @param array $args Additional arguments. Rarely used. See specific fields for details
61
  * @param int|null $post_id Post ID. null for current post. Optional.
62
  */
63
+ $value = apply_filters( 'rwmb_get_value', $value, $field, $args, $post_id );
64
 
65
  return $value;
66
  }
inc/helper.php CHANGED
@@ -16,17 +16,25 @@ class RWMB_Helper
16
 
17
  /**
18
  * Hash all fields into an indexed array for search
 
19
  */
20
- public static function hash_fields()
21
  {
 
 
22
  $meta_boxes = RWMB_Core::get_meta_boxes();
23
  foreach ( $meta_boxes as $meta_box )
24
  {
 
 
 
 
 
25
  foreach ( $meta_box['fields'] as $field )
26
  {
27
  if ( ! empty( $field['id'] ) )
28
  {
29
- self::$fields[$field['id']] = $field;
30
  }
31
  }
32
  }
@@ -36,18 +44,24 @@ class RWMB_Helper
36
  * Find field by field ID.
37
  * This function finds field in meta boxes registered by 'rwmb_meta_boxes' filter.
38
  *
39
- * @param string $field_id Field ID
 
40
  * @return array|false Field params (array) if success. False otherwise.
41
  */
42
- public static function find_field( $field_id )
43
  {
44
- if ( empty( self::$fields ) )
 
45
  {
46
- self::hash_fields();
47
  }
48
-
49
- $field = isset( self::$fields[$field_id] ) ? self::$fields[$field_id] : false;
50
- return $field ? call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'normalize' ), $field ) : false;
 
 
 
 
51
  }
52
 
53
  /**
16
 
17
  /**
18
  * Hash all fields into an indexed array for search
19
+ * @param string $post_type Post type
20
  */
21
+ public static function hash_fields( $post_type )
22
  {
23
+ self::$fields[$post_type] = array();
24
+
25
  $meta_boxes = RWMB_Core::get_meta_boxes();
26
  foreach ( $meta_boxes as $meta_box )
27
  {
28
+ $meta_box = RW_Meta_Box::normalize( $meta_box );
29
+ if ( ! in_array( $post_type, $meta_box['post_types'] ) )
30
+ {
31
+ continue;
32
+ }
33
  foreach ( $meta_box['fields'] as $field )
34
  {
35
  if ( ! empty( $field['id'] ) )
36
  {
37
+ self::$fields[$post_type][$field['id']] = $field;
38
  }
39
  }
40
  }
44
  * Find field by field ID.
45
  * This function finds field in meta boxes registered by 'rwmb_meta_boxes' filter.
46
  *
47
+ * @param string $field_id Field ID
48
+ * @param int $post_id
49
  * @return array|false Field params (array) if success. False otherwise.
50
  */
51
+ public static function find_field( $field_id, $post_id = null )
52
  {
53
+ $post_type = get_post_type( $post_id );
54
+ if ( empty( self::$fields[$post_type] ) )
55
  {
56
+ self::hash_fields( $post_type );
57
  }
58
+ $fields = self::$fields[$post_type];
59
+ if ( ! isset( $fields[$field_id] ) )
60
+ {
61
+ return false;
62
+ }
63
+ $field = $fields[$field_id];
64
+ return call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'normalize' ), $field );
65
  }
66
 
67
  /**
inc/loader.php CHANGED
@@ -28,7 +28,7 @@ class RWMB_Loader
28
  public function constants()
29
  {
30
  // Script version, used to add version for scripts and styles
31
- define( 'RWMB_VER', '4.8.3' );
32
 
33
  list( $path, $url ) = self::get_path();
34
 
@@ -50,31 +50,25 @@ class RWMB_Loader
50
  * @param string $base Base folder path
51
  * @return array Path and URL.
52
  */
53
- static public function get_path( $base = '' )
54
  {
55
  // Plugin base path
56
- $path = $base ? $base : dirname( dirname( __FILE__ ) );
57
- $path = untrailingslashit( $path );
58
- $abspath = untrailingslashit( ABSPATH );
59
 
60
- // Check if plugin is a symbolic link (only when it's installed as a standalone plugin).
61
- if ( false === strpos( $path, $abspath ) )
62
  {
63
- if ( ! function_exists( 'is_plugin_active' ) )
64
- {
65
- require_once ABSPATH . 'wp-admin/includes/plugin.php';
66
- }
67
- $basename = basename( $path );
68
- if ( is_plugin_active( "$basename/$basename.php" ) )
69
- {
70
- $path = trailingslashit( WP_PLUGIN_DIR ) . $basename;
71
- }
72
  }
73
-
74
- // Get plugin base URL
75
- $content_url = untrailingslashit( dirname( dirname( get_stylesheet_directory_uri() ) ) );
76
- $content_dir = untrailingslashit( WP_CONTENT_DIR );
77
- $url = str_replace( wp_normalize_path( $content_dir ), $content_url, wp_normalize_path( $path ) );
78
 
79
  $path = trailingslashit( $path );
80
  $url = trailingslashit( $url );
28
  public function constants()
29
  {
30
  // Script version, used to add version for scripts and styles
31
+ define( 'RWMB_VER', '4.8.4' );
32
 
33
  list( $path, $url ) = self::get_path();
34
 
50
  * @param string $base Base folder path
51
  * @return array Path and URL.
52
  */
53
+ public static function get_path( $base = '' )
54
  {
55
  // Plugin base path
56
+ $path = $base ? $base : dirname( dirname( __FILE__ ) );
57
+ $path = wp_normalize_path( untrailingslashit( $path ) );
 
58
 
59
+ // Installed as a plugin?
60
+ if ( 0 === strpos( $path, wp_normalize_path( WP_PLUGIN_DIR ) ) || 0 === strpos( $path, wp_normalize_path( WPMU_PLUGIN_DIR ) ) )
61
  {
62
+ $url = plugins_url( '', $path . '/' . basename( $path ) );
63
+ }
64
+ // Included into themes
65
+ else
66
+ {
67
+ // Get plugin base URL
68
+ $content_url = untrailingslashit( dirname( dirname( get_stylesheet_directory_uri() ) ) );
69
+ $content_dir = untrailingslashit( WP_CONTENT_DIR );
70
+ $url = str_replace( wp_normalize_path( $content_dir ), $content_url, $path );
71
  }
 
 
 
 
 
72
 
73
  $path = trailingslashit( $path );
74
  $url = trailingslashit( $url );
inc/meta-box.php CHANGED
@@ -40,8 +40,10 @@ class RW_Meta_Box
40
  if ( ! is_admin() )
41
  return;
42
 
43
- // Assign meta box values to local variables and add it's missed values
44
- $this->meta_box = self::normalize( $meta_box );
 
 
45
  $this->fields = &$this->meta_box['fields'];
46
 
47
  // Allow users to show/hide meta box
@@ -305,7 +307,6 @@ class RW_Meta_Box
305
 
306
  /**
307
  * Use 'post_types' for better understanding and fallback to 'pages' for previous versions
308
- *
309
  * @since 4.4.1
310
  */
311
  if ( ! empty( $meta_box['pages'] ) )
@@ -319,9 +320,6 @@ class RW_Meta_Box
319
  $meta_box['post_types'] = array( $meta_box['post_types'] );
320
  }
321
 
322
- // Set default values for fields
323
- $meta_box['fields'] = self::normalize_fields( $meta_box['fields'] );
324
-
325
  // Allow to add default values for meta box
326
  $meta_box = apply_filters( 'rwmb_normalize_meta_box', $meta_box );
327
  $meta_box = apply_filters( "rwmb_normalize_{$meta_box['id']}_meta_box", $meta_box );
40
  if ( ! is_admin() )
41
  return;
42
 
43
+ $meta_box = self::normalize( $meta_box );
44
+ $meta_box['fields'] = self::normalize_fields( $meta_box['fields'] );
45
+
46
+ $this->meta_box = $meta_box;
47
  $this->fields = &$this->meta_box['fields'];
48
 
49
  // Allow users to show/hide meta box
307
 
308
  /**
309
  * Use 'post_types' for better understanding and fallback to 'pages' for previous versions
 
310
  * @since 4.4.1
311
  */
312
  if ( ! empty( $meta_box['pages'] ) )
320
  $meta_box['post_types'] = array( $meta_box['post_types'] );
321
  }
322
 
 
 
 
323
  // Allow to add default values for meta box
324
  $meta_box = apply_filters( 'rwmb_normalize_meta_box', $meta_box );
325
  $meta_box = apply_filters( "rwmb_normalize_{$meta_box['id']}_meta_box", $meta_box );
inc/templates/image-advanced.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script id="tmpl-rwmb-image-item" type="text/html">
2
+ <input type="hidden" name="{{{ data.fieldName }}}" value="{{{ data.id }}}" class="rwmb-media-input">
3
+ <div class="rwmb-media-preview">
4
+ <div class="rwmb-media-content">
5
+ <div class="centered">
6
+ <# if ( 'image' === data.type && data.sizes ) { #>
7
+ <# if ( data.sizes.thumbnail ) { #>
8
+ <img src="{{{ data.sizes.thumbnail.url }}}">
9
+ <# } else { #>
10
+ <img src="{{{ data.sizes.full.url }}}">
11
+ <# } #>
12
+ <# } else { #>
13
+ <# if ( data.image && data.image.src && data.image.src !== data.icon ) { #>
14
+ <img src="{{ data.image.src }}" />
15
+ <# } else { #>
16
+ <img src="{{ data.icon }}" />
17
+ <# } #>
18
+ <# } #>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ <div class="rwmb-overlay"></div>
23
+ <div class="rwmb-media-bar">
24
+ <a class="rwmb-edit-media" title="{{{ i18nRwmbMedia.edit }}}" href="{{{ data.editLink }}}" target="_blank">
25
+ <span class="dashicons dashicons-edit"></span>
26
+ </a>
27
+ <a href="#" class="rwmb-remove-media" title="{{{ i18nRwmbMedia.remove }}}">
28
+ <span class="dashicons dashicons-no-alt"></span>
29
+ </a>
30
+ </div>
31
+ </script>
inc/templates/media.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script id="tmpl-rwmb-media-item" type="text/html">
2
+ <input type="hidden" name="{{{ data.fieldName }}}" value="{{{ data.id }}}" class="rwmb-media-input">
3
+ <div class="rwmb-media-preview">
4
+ <div class="rwmb-media-content">
5
+ <div class="centered">
6
+ <# if ( 'image' === data.type && data.sizes ) { #>
7
+ <# if ( data.sizes.thumbnail ) { #>
8
+ <img src="{{{ data.sizes.thumbnail.url }}}">
9
+ <# } else { #>
10
+ <img src="{{{ data.sizes.full.url }}}">
11
+ <# } #>
12
+ <# } else { #>
13
+ <# if ( data.image && data.image.src && data.image.src !== data.icon ) { #>
14
+ <img src="{{ data.image.src }}" />
15
+ <# } else { #>
16
+ <img src="{{ data.icon }}" />
17
+ <# } #>
18
+ <# } #>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ <div class="rwmb-media-info">
23
+ <h4>
24
+ <a href="{{{ data.url }}}" target="_blank" title="{{{ i18nRwmbMedia.view }}}">
25
+ <# if( data.title ) { #> {{{ data.title }}}
26
+ <# } else { #> {{{ i18nRwmbMedia.noTitle }}}
27
+ <# } #>
28
+ </a>
29
+ </h4>
30
+ <p>{{{ data.mime }}}</p>
31
+ <p>
32
+ <a class="rwmb-edit-media" title="{{{ i18nRwmbMedia.edit }}}" href="{{{ data.editLink }}}" target="_blank">
33
+ <span class="dashicons dashicons-edit"></span>{{{ i18nRwmbMedia.edit }}}
34
+ </a>
35
+ <a href="#" class="rwmb-remove-media" title="{{{ i18nRwmbMedia.remove }}}">
36
+ <span class="dashicons dashicons-no-alt"></span>{{{ i18nRwmbMedia.remove }}}
37
+ </a>
38
+ </p>
39
+ </div>
40
+ </script>
41
+
42
+ <script id="tmpl-rwmb-media-status" type="text/html">
43
+ <# if ( data.maxFiles > 0 ) { #>
44
+ {{{ data.items }}}/{{{ data.maxFiles }}}
45
+ <# if ( 1 < data.maxFiles ) { #> {{{ i18nRwmbMedia.multiple }}} <# } else {#> {{{ i18nRwmbMedia.single }}} <# } #>
46
+ <# } #>
47
+ </script>
inc/templates/upload.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <script id="tmpl-rwmb-upload-area" type="text/html">
2
+ <div class="rwmb-upload-inside">
3
+ <h3>{{{ i18nRwmbMedia.uploadInstructions }}}</h3>
4
+ <p> or</p>
5
+ <p><a href="#" class="rwmb-browse-button button button-hero" id="{{{ _.uniqueId( 'rwmb-upload-browser-') }}}">{{{ i18nRwmbMedia.select }}}</a></p>
6
+ </div>
7
+ </script>
inc/walkers/{choice-list-walker.php → input-list-walker.php} RENAMED
@@ -1,9 +1,9 @@
1
  <?php
2
  /**
3
- * Choice List Walker
4
  * For checkbox and radio list fields
5
  */
6
- class RWMB_Choice_List_Walker extends RWMB_Walker
7
  {
8
  /**
9
  * @see Walker::start_lvl()
@@ -14,7 +14,7 @@ class RWMB_Choice_List_Walker extends RWMB_Walker
14
  */
15
  public function start_lvl( &$output, $depth = 0, $args = array() )
16
  {
17
- $output .= "<ul class='rwmb-choice-list'>";
18
  }
19
 
20
  /**
1
  <?php
2
  /**
3
+ * Input List Walker
4
  * For checkbox and radio list fields
5
  */
6
+ class RWMB_Input_List_Walker extends RWMB_Walker
7
  {
8
  /**
9
  * @see Walker::start_lvl()
14
  */
15
  public function start_lvl( &$output, $depth = 0, $args = array() )
16
  {
17
+ $output .= "<ul class='rwmb-input-list'>";
18
  }
19
 
20
  /**
js/clone.js CHANGED
@@ -112,7 +112,7 @@ jQuery( function ( $ )
112
  // Reset select to first
113
  $field.prop( 'selectedIndex', 0 )
114
  }
115
- else
116
  {
117
  // Reset value
118
  $field.val( '' );
112
  // Reset select to first
113
  $field.prop( 'selectedIndex', 0 )
114
  }
115
+ else if ( 'hidden' !== $field.attr( 'type' ) )
116
  {
117
  // Reset value
118
  $field.val( '' );
js/date.js CHANGED
@@ -9,10 +9,47 @@ jQuery( function ( $ )
9
  function update()
10
  {
11
  var $this = $( this ),
12
- options = $this.data( 'options' );
 
 
 
13
 
14
- $this.siblings( '.ui-datepicker-append' ).remove(); // Remove appended text
15
- $this.removeClass( 'hasDatepicker' ).datepicker( options );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  }
17
 
18
  $( ':input.rwmb-date' ).each( update );
9
  function update()
10
  {
11
  var $this = $( this ),
12
+ options = $this.data( 'options' ),
13
+ $inline = $this.siblings( '.rwmb-datetime-inline' ),
14
+ $timestamp = $this.siblings( '.rwmb-datetime-timestamp' ),
15
+ current = $this.val();
16
 
17
+ $this.siblings( '.ui-datepicker-append' ).remove(); // Remove appended text
18
+ if ( $timestamp.length )
19
+ {
20
+ var $picker = $inline.length ? $inline : $this;
21
+ options.onSelect = function ()
22
+ {
23
+ $timestamp.val( getTimestamp( $picker.datepicker( 'getDate' ) ) );
24
+ };
25
+ }
26
+
27
+ if ( $inline.length )
28
+ {
29
+ options.altField = '#' + $this.attr( 'id' );
30
+ $inline
31
+ .removeClass( 'hasDatepicker' )
32
+ .empty()
33
+ .prop( 'id', '' )
34
+ .datepicker( options )
35
+ .datepicker( 'setDate', current );
36
+ }
37
+ else
38
+ {
39
+ $this.removeClass( 'hasDatepicker' ).datepicker( options );
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Convert date to Unix timestamp in milliseconds
45
+ * @link http://stackoverflow.com/a/14006555/556258
46
+ * @param date
47
+ * @return number
48
+ */
49
+ function getTimestamp( date )
50
+ {
51
+ var milliseconds = Date.UTC( date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds() );
52
+ return Math.floor( milliseconds / 1000 );
53
  }
54
 
55
  $( ':input.rwmb-date' ).each( update );
js/datetime.js CHANGED
@@ -9,11 +9,47 @@ jQuery( function ( $ )
9
  function update()
10
  {
11
  var $this = $( this ),
12
- options = $this.data( 'options' );
 
 
 
13
 
14
- $this.siblings( '.ui-datepicker-append' ).remove(); // Remove appended text
15
- $this.removeClass( 'hasDatepicker' ).datetimepicker( options );
 
 
 
 
 
 
 
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  }
18
 
19
  // Set language if available
9
  function update()
10
  {
11
  var $this = $( this ),
12
+ options = $this.data( 'options' ),
13
+ $inline = $this.siblings( '.rwmb-datetime-inline' ),
14
+ $timestamp = $this.siblings( '.rwmb-datetime-timestamp' ),
15
+ current = $this.val();
16
 
17
+ $this.siblings( '.ui-datepicker-append' ).remove(); // Remove appended text
18
+ if ( $timestamp.length )
19
+ {
20
+ var $picker = $inline.length ? $inline : $this;
21
+ options.onSelect = function ()
22
+ {
23
+ $timestamp.val( getTimestamp( $picker.datetimepicker( 'getDate' ) ) );
24
+ };
25
+ }
26
 
27
+ if ( $inline.length )
28
+ {
29
+ options.altField = '#' + $this.attr( 'id' );
30
+ $inline
31
+ .removeClass( 'hasDatepicker' )
32
+ .empty()
33
+ .prop( 'id', '' )
34
+ .datetimepicker( options )
35
+ .datetimepicker( 'setDate', current );
36
+ }
37
+ else
38
+ {
39
+ $this.removeClass( 'hasDatepicker' ).datetimepicker( options );
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Convert date to Unix timestamp in milliseconds
45
+ * @link http://stackoverflow.com/a/14006555/556258
46
+ * @param date
47
+ * @return number
48
+ */
49
+ function getTimestamp( date )
50
+ {
51
+ var milliseconds = Date.UTC( date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds() );
52
+ return Math.floor( milliseconds / 1000 );
53
  }
54
 
55
  // Set language if available
js/file-upload.js ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ window.rwmb = window.rwmb || {};
2
+
3
+ jQuery( function ( $ )
4
+ {
5
+ 'use strict';
6
+
7
+ var views = rwmb.views = rwmb.views || {},
8
+ MediaField = views.MediaField,
9
+ FileUploadField, UploadButton;
10
+
11
+ FileUploadField = views.FileUploadField = MediaField.extend( {
12
+ createAddButton: function ()
13
+ {
14
+ this.addButton = new UploadButton( { collection: this.collection, props: this.props } );
15
+ }
16
+ } );
17
+
18
+ UploadButton = views.UploadButton = Backbone.View.extend( {
19
+ className: 'rwmb-upload-area',
20
+ tagName : 'div',
21
+ template: wp.template( 'rwmb-upload-area' ),
22
+ render : function ()
23
+ {
24
+ this.$el.html( this.template( {} ) );
25
+ return this;
26
+ },
27
+
28
+ initialize: function ( options )
29
+ {
30
+ this.props = options.props;
31
+ this.el.id = _.uniqueId( 'rwmb-upload-area-');
32
+ this.render();
33
+
34
+ //Areas
35
+ this.dropzone = this.el;
36
+ this.browser = this.$('.rwmb-browse-button')[0];
37
+
38
+ this.supports = {
39
+ upload: wp.Uploader.browser.supported
40
+ };
41
+
42
+ this.supported = this.supports.upload;
43
+
44
+ if ( this.supported ) {
45
+ this.initUploader();
46
+ }
47
+
48
+ this.listenTo( this.collection, 'add remove reset', function ()
49
+ {
50
+ var maxFiles = this.props.get( 'maxFiles' );
51
+
52
+ if ( maxFiles > 0 )
53
+ {
54
+ this.$el.toggle( this.collection.length < maxFiles );
55
+ }
56
+ } );
57
+ },
58
+
59
+ //Initializes plupload
60
+ //Uses code from wp.Uploader
61
+ initUploader: function ()
62
+ {
63
+ var isIE = navigator.userAgent.indexOf('Trident/') != -1 || navigator.userAgent.indexOf('MSIE ') != -1,
64
+ self = this,
65
+ extensions = this.getExtensions().join( ',' );
66
+ this.plupload = $.extend( true, {
67
+ multipart_params: {},
68
+ multipart: true,
69
+ urlstream_upload: true,
70
+ drop_element: this.dropzone,
71
+ browse_button: this.browser,
72
+ filters:{}}, wp.Uploader.defaults );
73
+
74
+ if( extensions )
75
+ this.plupload.filters.mime_types = [ { title: i18nRwmbMedia.select, extensions: extensions } ];
76
+
77
+ // Make sure flash sends cookies (seems in IE it does without switching to urlstream mode)
78
+ if ( ! isIE && 'flash' === plupload.predictRuntime( this.plupload ) &&
79
+ ( ! this.plupload.required_features || ! this.plupload.required_features.hasOwnProperty( 'send_binary_string' ) ) )
80
+ {
81
+ this.plupload.required_features = this.plupload.required_features || {};
82
+ this.plupload.required_features.send_binary_string = true;
83
+ }
84
+
85
+ // Initialize the plupload instance.
86
+ this.uploader = new plupload.Uploader( this.plupload );
87
+ this.uploader.init();
88
+
89
+ this.uploader.bind( 'FilesAdded', function( up, files )
90
+ {
91
+ _.each( files, function( file )
92
+ {
93
+ var attributes, image;
94
+
95
+ // Ignore failed uploads.
96
+ if ( plupload.FAILED === file.status )
97
+ {
98
+ return;
99
+ }
100
+
101
+ // Generate attributes for a new `Attachment` model.
102
+ attributes = _.extend({
103
+ file: file,
104
+ uploading: true,
105
+ date: new Date(),
106
+ filename: file.name,
107
+ menuOrder: 0,
108
+ uploadedTo: wp.media.model.settings.post.id,
109
+ icon: i18nRwmbMedia.loadingUrl
110
+ }, _.pick( file, 'loaded', 'size', 'percent' ) );
111
+
112
+ // Handle early mime type scanning for images.
113
+ image = /(?:jpe?g|png|gif)$/i.exec( file.name );
114
+
115
+ // For images set the model's type and subtype attributes.
116
+ if ( image )
117
+ {
118
+ attributes.type = 'image';
119
+
120
+ // `jpeg`, `png` and `gif` are valid subtypes.
121
+ // `jpg` is not, so map it to `jpeg`.
122
+ attributes.subtype = ( 'jpg' === image[0] ) ? 'jpeg' : image[0];
123
+ }
124
+
125
+ // Create a model for the attachment, and add it to the Upload queue collection
126
+ // so listeners to the upload queue can track and display upload progress.
127
+ file.attachment = wp.media.model.Attachment.create( attributes );
128
+ wp.Uploader.queue.add( file.attachment );
129
+ self.collection.add( file.attachment );
130
+ });
131
+
132
+ up.refresh();
133
+ up.start();
134
+ });
135
+
136
+ this.uploader.bind( 'UploadProgress', function( up, file ) {
137
+ file.attachment.set( _.pick( file, 'loaded', 'percent' ) );
138
+ });
139
+
140
+ this.uploader.bind( 'FileUploaded', function( up, file, response ) {
141
+ var complete;
142
+
143
+ try {
144
+ response = JSON.parse( response.response );
145
+ } catch ( e ) {
146
+ return false;
147
+ }
148
+
149
+ if ( ! _.isObject( response ) || _.isUndefined( response.success ) || ! response.success )
150
+ return false;
151
+
152
+ _.each(['file','loaded','size','percent'], function( key ) {
153
+ file.attachment.unset( key );
154
+ });
155
+
156
+ file.attachment.set( _.extend( response.data, { uploading: false }) );
157
+ wp.media.model.Attachment.get( response.data.id, file.attachment );
158
+
159
+ complete = wp.Uploader.queue.all( function( attachment ) {
160
+ return ! attachment.get('uploading');
161
+ });
162
+
163
+ if ( complete )
164
+ wp.Uploader.queue.reset();
165
+ });
166
+
167
+ this.uploader.bind( 'Error', function ( up, error )
168
+ {
169
+ if( error.file.attachment )
170
+ error.file.attachment.destroy();
171
+ } );
172
+ },
173
+
174
+ getExtensions: function ()
175
+ {
176
+ var mimeTypes = this.props.get( 'mimeType' ).split(','),
177
+ exts = [];
178
+
179
+ _.each( mimeTypes, function( current, index )
180
+ {
181
+ if( i18nRwmbMedia.extensions[ current ] )
182
+ exts = exts.concat( i18nRwmbMedia.extensions[ current ] );
183
+ });
184
+ return exts;
185
+ }
186
+ } );
187
+
188
+ /**
189
+ * Initialize fields
190
+ * @return void
191
+ */
192
+ function init()
193
+ {
194
+ new FileUploadField( { input: this, el: $( this ).siblings( 'div.rwmb-media-view' ) } );
195
+ }
196
+ $( ':input.rwmb-file_upload' ).each( init );
197
+ $( '.rwmb-input' )
198
+ .on( 'clone', ':input.rwmb-file_upload', init )
199
+ } );
js/image-advanced.js ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ window.rwmb = window.rwmb || {};
2
+
3
+ jQuery( function ( $ )
4
+ {
5
+ 'use strict';
6
+
7
+ var views = rwmb.views = rwmb.views || {},
8
+ MediaField = views.MediaField,
9
+ MediaItem = views.MediaItem,
10
+ MediaList = views.MediaList,
11
+ ImageField, ImageList, ImageItem;
12
+
13
+ ImageField = views.ImageField = MediaField.extend( {
14
+ createList: function ()
15
+ {
16
+ this.list = new MediaList( { collection: this.collection, props: this.props, itemView: ImageItem } );
17
+ }
18
+ } );
19
+
20
+ ImageItem = views.ImageItem = MediaItem.extend( {
21
+ className: 'rwmb-image-item',
22
+ template : wp.template( 'rwmb-image-item' )
23
+ } );
24
+
25
+ /**
26
+ * Initialize image fields
27
+ * @return void
28
+ */
29
+ function initImageField()
30
+ {
31
+ new ImageField( { input: this, el: $( this ).siblings( 'div.rwmb-media-view' ) } );
32
+ }
33
+ $( ':input.rwmb-image_advanced' ).each( initImageField );
34
+ $( '.rwmb-input' )
35
+ .on( 'clone', ':input.rwmb-image_advanced', initImageField )
36
+ } );
js/image-upload.js ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ window.rwmb = window.rwmb || {};
2
+
3
+ jQuery( function ( $ )
4
+ {
5
+ 'use strict';
6
+
7
+ var views = rwmb.views = rwmb.views || {},
8
+ ImageField = views.ImageField,
9
+ ImageUploadField,
10
+ UploadButton = views.UploadButton;
11
+
12
+ ImageUploadField = views.ImageUploadField = ImageField.extend( {
13
+ createAddButton: function ()
14
+ {
15
+ this.addButton = new UploadButton( { collection: this.collection, props: this.props } );
16
+ }
17
+ } );
18
+
19
+ /**
20
+ * Initialize fields
21
+ * @return void
22
+ */
23
+ function init()
24
+ {
25
+ new ImageUploadField( { input: this, el: $( this ).siblings( 'div.rwmb-media-view' ) } );
26
+ console.log('win');
27
+ }
28
+ $( ':input.rwmb-image_upload, :input.rwmb-plupload_image' ).each( init );
29
+ $( '.rwmb-input' )
30
+ .on( 'clone', ':input.rwmb-image_upload, :input.rwmb-plupload_image', init )
31
+ } );
js/input-list.js ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery( function( $ )
2
+ {
3
+ function update()
4
+ {
5
+ var $this = $( this ),
6
+ $children = $this.closest( 'li' ).children('ul');
7
+
8
+ if ( $this.is( ':checked' ) )
9
+ {
10
+ $children.removeClass( 'hidden' );
11
+ }
12
+ else
13
+ {
14
+ $children
15
+ .addClass( 'hidden' )
16
+ .find( 'input' )
17
+ .removeAttr( 'checked' );
18
+ }
19
+ }
20
+
21
+ $( '.rwmb-input' )
22
+ .on( 'change', '.rwmb-input-list.collapse :checkbox', update )
23
+ .on( 'clone', '.rwmb-input-list.collapse :checkbox', update );
24
+ $( '.rwmb-input-list.collapse :checkbox' ).each( update );
25
+ } );
js/media.js CHANGED
@@ -5,23 +5,22 @@ jQuery( function ( $ )
5
  'use strict';
6
 
7
  var views = rwmb.views = rwmb.views || {},
8
- MediaField, MediaList, MediaItem, ImageField, ImageList, ImageItem, MediaButton, MediaStatus, UploadButton;
 
9
 
10
  MediaList = views.MediaList = Backbone.View.extend( {
11
  tagName : 'ul',
12
  className : 'rwmb-media-list',
13
- createItemView: function ( options )
14
- {
15
- return new MediaItem( options );
16
- },
17
-
18
  addItemView: function ( item )
19
  {
20
- this.itemViews[item.cid] = this.createItemView( {
21
- model : item,
22
- collection: this.collection,
23
- props : this.props
24
- } );
 
 
 
25
  this.$el.append( this.itemViews[item.cid].el );
26
  },
27
 
@@ -36,6 +35,7 @@ jQuery( function ( $ )
36
  var that = this;
37
  this.itemViews = {};
38
  this.props = options.props;
 
39
 
40
  this.listenTo( this.collection, 'add', this.addItemView );
41
 
@@ -49,16 +49,14 @@ jQuery( function ( $ )
49
  } );
50
 
51
  //Sort media using sortable
52
- this.$el.sortable( { delay: 150 } );
53
 
54
  this.render();
55
- }
56
- } );
57
 
58
- ImageList = views.ImageList = MediaList.extend( {
59
- createItemView: function ( options )
60
  {
61
- return new ImageItem( options );
62
  }
63
  } );
64
 
@@ -74,6 +72,11 @@ jQuery( function ( $ )
74
  //Create collection
75
  this.collection = new wp.media.model.Attachments();
76
 
 
 
 
 
 
77
  //Render
78
  this.render();
79
 
@@ -104,7 +107,7 @@ jQuery( function ( $ )
104
  //Listen for destroy event on input
105
  this.$input
106
  .on( 'remove', function(){
107
- if ( that.props.gat( 'forceDelete' ) )
108
  {
109
  _.each( _.clone( that.collection.models ), function ( model )
110
  {
@@ -114,23 +117,31 @@ jQuery( function ( $ )
114
  } )
115
  },
116
 
117
- render: function ()
118
  {
119
- //Empty then add parts
120
- this.$el.empty();
121
- this.$el.append( new MediaList( { collection: this.collection, props: this.props } ).el );
122
- this.$el.append( new MediaButton( { collection: this.collection, props: this.props } ).el );
123
- this.$el.append( new MediaStatus( { collection: this.collection, props: this.props } ).el );
124
- }
125
- } );
 
 
 
 
 
126
 
127
- ImageField = views.ImageField = MediaField.extend( {
128
  render: function ()
129
  {
130
- this.$el.empty();
131
- this.$el.append( new ImageList( { collection: this.collection, props: this.props } ).el );
132
- this.$el.append( new MediaButton( { collection: this.collection, props: this.props } ).el );
133
- this.$el.append( new MediaStatus( { collection: this.collection, props: this.props } ).el );
 
 
 
 
134
  }
135
  } );
136
 
@@ -158,7 +169,6 @@ jQuery( function ( $ )
158
  MediaButton = views.MediaButton = Backbone.View.extend( {
159
  className: 'rwmb-add-media button',
160
  tagName : 'a',
161
- template : wp.template( 'rwmb-add-media' ),
162
  events : {
163
  click: function ()
164
  {
@@ -167,7 +177,7 @@ jQuery( function ( $ )
167
  // Destroy the previous collection frame.
168
  if ( this._frame )
169
  {
170
- this.stopListening( this._frame );
171
  this._frame.dispose();
172
  }
173
 
@@ -180,19 +190,18 @@ jQuery( function ( $ )
180
  type: this.props.get( 'mimeType' )
181
  }
182
  } );
183
-
184
- this.listenTo( this._frame, 'select', function ()
185
  {
186
  var selection = this._frame.state().get( 'selection' );
187
  this.collection.add( selection.models );
188
- } );
189
 
190
  this._frame.open();
191
  }
192
  },
193
  render : function ()
194
  {
195
- this.$el.html( this.template( {} ) );
196
  return this;
197
  },
198
 
@@ -202,13 +211,10 @@ jQuery( function ( $ )
202
  this.listenTo( this.collection, 'add remove reset', function ()
203
  {
204
  var maxFiles = this.props.get( 'maxFiles' );
205
- if ( maxFiles > 0 && this.collection.length >= maxFiles )
206
- {
207
- this.$el.hide();
208
- }
209
- else
210
  {
211
- this.$el.show();
212
  }
213
  } );
214
 
@@ -227,7 +233,11 @@ jQuery( function ( $ )
227
  this.listenTo( this.model, 'destroy', function ( model )
228
  {
229
  this.collection.remove( this.model );
230
- } );
 
 
 
 
231
  },
232
 
233
  events: {
@@ -252,10 +262,6 @@ jQuery( function ( $ )
252
  }
253
  } );
254
 
255
- ImageItem = views.ImageItem = MediaItem.extend( {
256
- className: 'rwmb-image-item',
257
- template : wp.template( 'rwmb-image-item' )
258
- } );
259
 
260
  /**
261
  * Initialize media fields
@@ -266,14 +272,8 @@ jQuery( function ( $ )
266
  new MediaField( { input: this, el: $( this ).siblings( 'div.rwmb-media-view' ) } );
267
  }
268
 
269
- function initImageField()
270
- {
271
- new ImageField( { input: this, el: $( this ).siblings( 'div.rwmb-media-view' ) } );
272
- }
273
 
274
  $( ':input.rwmb-file_advanced' ).each( initMediaField );
275
- $( ':input.rwmb-image_advanced' ).each( initImageField );
276
  $( '.rwmb-input' )
277
- .on( 'clone', ':input.rwmb-file_advanced', initMediaField )
278
- .on( 'clone', ':input.rwmb-image_advanced', initImageField )
279
  } );
5
  'use strict';
6
 
7
  var views = rwmb.views = rwmb.views || {},
8
+ MediaField, MediaList, MediaItem, MediaButton, MediaStatus;
9
+ rwmb.test = 'spoon';
10
 
11
  MediaList = views.MediaList = Backbone.View.extend( {
12
  tagName : 'ul',
13
  className : 'rwmb-media-list',
 
 
 
 
 
14
  addItemView: function ( item )
15
  {
16
+ if( ! this.itemViews[item.cid] )
17
+ {
18
+ this.itemViews[item.cid] = new this.itemView( {
19
+ model : item,
20
+ collection: this.collection,
21
+ props : this.props
22
+ } );
23
+ }
24
  this.$el.append( this.itemViews[item.cid].el );
25
  },
26
 
35
  var that = this;
36
  this.itemViews = {};
37
  this.props = options.props;
38
+ this.itemView = options.itemView || MediaItem;
39
 
40
  this.listenTo( this.collection, 'add', this.addItemView );
41
 
49
  } );
50
 
51
  //Sort media using sortable
52
+ this.initSort();
53
 
54
  this.render();
55
+ },
 
56
 
57
+ initSort: function ()
 
58
  {
59
+ this.$el.sortable( { delay: 150 } );
60
  }
61
  } );
62
 
72
  //Create collection
73
  this.collection = new wp.media.model.Attachments();
74
 
75
+ //Create views
76
+ this.createList();
77
+ this.createAddButton()
78
+ this.createStatus();
79
+
80
  //Render
81
  this.render();
82
 
107
  //Listen for destroy event on input
108
  this.$input
109
  .on( 'remove', function(){
110
+ if ( that.props.get( 'forceDelete' ) )
111
  {
112
  _.each( _.clone( that.collection.models ), function ( model )
113
  {
117
  } )
118
  },
119
 
120
+ createList: function ()
121
  {
122
+ this.list = new MediaList( { collection: this.collection, props: this.props } );
123
+ },
124
+
125
+ createAddButton: function ()
126
+ {
127
+ this.addButton = new MediaButton( { collection: this.collection, props: this.props } );
128
+ },
129
+
130
+ createStatus: function ()
131
+ {
132
+ this.status = new MediaStatus( { collection: this.collection, props: this.props } );
133
+ },
134
 
 
135
  render: function ()
136
  {
137
+ //Empty then add parts
138
+ this.$el
139
+ .empty()
140
+ .append(
141
+ this.list.el,
142
+ this.addButton.el,
143
+ this.status.el
144
+ );
145
  }
146
  } );
147
 
169
  MediaButton = views.MediaButton = Backbone.View.extend( {
170
  className: 'rwmb-add-media button',
171
  tagName : 'a',
 
172
  events : {
173
  click: function ()
174
  {
177
  // Destroy the previous collection frame.
178
  if ( this._frame )
179
  {
180
+ //this.stopListening( this._frame );
181
  this._frame.dispose();
182
  }
183
 
190
  type: this.props.get( 'mimeType' )
191
  }
192
  } );
193
+ this._frame.on( 'select', function ()
 
194
  {
195
  var selection = this._frame.state().get( 'selection' );
196
  this.collection.add( selection.models );
197
+ }, this );
198
 
199
  this._frame.open();
200
  }
201
  },
202
  render : function ()
203
  {
204
+ this.$el.text( i18nRwmbMedia.add );
205
  return this;
206
  },
207
 
211
  this.listenTo( this.collection, 'add remove reset', function ()
212
  {
213
  var maxFiles = this.props.get( 'maxFiles' );
214
+
215
+ if ( maxFiles > 0 )
 
 
 
216
  {
217
+ this.$el.toggle( this.collection.length < maxFiles );
218
  }
219
  } );
220
 
233
  this.listenTo( this.model, 'destroy', function ( model )
234
  {
235
  this.collection.remove( this.model );
236
+ } )
237
+ .listenTo( this.model, 'change', function()
238
+ {
239
+ this.render();
240
+ });
241
  },
242
 
243
  events: {
262
  }
263
  } );
264
 
 
 
 
 
265
 
266
  /**
267
  * Initialize media fields
272
  new MediaField( { input: this, el: $( this ).siblings( 'div.rwmb-media-view' ) } );
273
  }
274
 
 
 
 
 
275
 
276
  $( ':input.rwmb-file_advanced' ).each( initMediaField );
 
277
  $( '.rwmb-input' )
278
+ .on( 'clone', ':input.rwmb-file_advanced', initMediaField );
 
279
  } );
js/object-choice.js DELETED
@@ -1,45 +0,0 @@
1
- jQuery( function( $ )
2
- {
3
- 'use strict';
4
- function updateChecklist()
5
- {
6
- var $this = $( this ),
7
- $children = $this.closest( 'li' ).children('ul');
8
-
9
- if ( $this.is( ':checked' ) )
10
- {
11
- $children.removeClass( 'hidden' );
12
- }
13
- else
14
- {
15
- $children
16
- .addClass( 'hidden' )
17
- .find( 'input' )
18
- .removeAttr( 'checked' );
19
- }
20
- }
21
-
22
- $( '.rwmb-input' )
23
- .on( 'change', '.rwmb-choice-list.collapse :checkbox', updateChecklist )
24
- .on( 'clone', '.rwmb-choice-list.collapse :checkbox', updateChecklist );
25
- $( '.rwmb-choice-list.collapse :checkbox' ).each( updateChecklist );
26
-
27
-
28
- function updateSelectTree()
29
- {
30
- var $this = $( this ),
31
- val = $this.val(),
32
- $selected = $this.siblings( "[data-parent-id='" + val + "']" ),
33
- $notSelected = $this.parent().find( '.rwmb-select-tree' ).not( $selected );
34
-
35
- $selected.removeClass( 'hidden' );
36
- $notSelected
37
- .addClass( 'hidden' )
38
- .find( 'select' )
39
- .prop( 'selectedIndex', 0 );
40
- }
41
-
42
- $( '.rwmb-input' )
43
- .on( 'change', '.rwmb-select-tree select', updateSelectTree )
44
- .on( 'clone', '.rwmb-select-tree select', updateSelectTree );
45
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/plupload-image.js DELETED
@@ -1,139 +0,0 @@
1
- jQuery( function ( $ )
2
- {
3
- 'use strict';
4
-
5
- // Hide "Uploaded files" title if there are no files uploaded after deleting files
6
- $( '.rwmb-images' ).on( 'click', '.rwmb-delete-file', function ()
7
- {
8
- // Check if we need to show drop target
9
- var $dragndrop = $( this ).parents( '.rwmb-images' ).siblings( '.rwmb-drag-drop' );
10
-
11
- // After delete files, show the Drag & Drop section
12
- $dragndrop.removeClass( 'hidden' );
13
- } );
14
-
15
- $( '.rwmb-drag-drop' ).each( function ()
16
- {
17
- // Declare vars
18
- var $dropArea = $( this ),
19
- $imageList = $dropArea.siblings( '.rwmb-uploaded' ),
20
- uploaderData = $dropArea.data( 'js_options' ),
21
- uploader;
22
-
23
- // Extend uploaderData
24
- uploaderData.multipart_params = $.extend(
25
- {
26
- _ajax_nonce: $dropArea.data( 'upload_nonce' ),
27
- post_id : $( '#post_ID' ).val()
28
- },
29
- uploaderData.multipart_params
30
- );
31
-
32
- // Create uploader
33
- uploader = new plupload.Uploader( uploaderData );
34
- uploader.init();
35
-
36
- // Add files
37
- uploader.bind( 'FilesAdded', function ( up, files )
38
- {
39
- var maxFileUploads = $imageList.data( 'max_file_uploads' ),
40
- uploaded = $imageList.children().length,
41
- msg = maxFileUploads > 1 ? rwmbFile.maxFileUploadsPlural : rwmbFile.maxFileUploadsSingle;
42
-
43
- msg = msg.replace( '%d', maxFileUploads );
44
-
45
- // Remove files from queue if exceed max file uploads
46
- if ( maxFileUploads > 0 && ( uploaded + files.length ) > maxFileUploads )
47
- {
48
- if ( uploaded < maxFileUploads )
49
- {
50
- var diff = maxFileUploads - uploaded;
51
- up.splice( diff - 1, files.length - diff );
52
- files = up.files;
53
- }
54
- alert( msg );
55
- }
56
-
57
- // Hide drag & drop section if reach max file uploads
58
- if ( maxFileUploads > 0 && uploaded + files.length >= maxFileUploads )
59
- {
60
- $dropArea.addClass( 'hidden' );
61
- }
62
-
63
- var max = parseInt( up.settings.max_file_size, 10 );
64
-
65
- // Upload files
66
- plupload.each( files, function ( file )
67
- {
68
- addLoading( up, file, $imageList );
69
- addThrobber( file );
70
- if ( file.size >= max )
71
- {
72
- removeError( file );
73
- }
74
- } );
75
- up.refresh();
76
- up.start();
77
- } );
78
-
79
- uploader.bind( 'Error', function ( up, e )
80
- {
81
- addLoading( up, e.file, $imageList );
82
- removeError( e.file );
83
- up.removeFile( e.file );
84
- } );
85
-
86
- uploader.bind( 'FileUploaded', function ( up, file, r )
87
- {
88
- r = $.parseJSON( r.response );
89
- if ( r.success )
90
- {
91
- $( 'li#' + file.id ).replaceWith( r.data );
92
- }
93
- else
94
- {
95
- removeError( file );
96
- }
97
- } );
98
- } );
99
-
100
- /**
101
- * Helper functions
102
- */
103
-
104
- /**
105
- * Removes li element if there is an error with the file
106
- *
107
- * @return void
108
- */
109
- function removeError( file )
110
- {
111
- $( 'li#' + file.id )
112
- .addClass( 'rwmb-image-error' )
113
- .delay( 1600 )
114
- .fadeOut( 'slow', function ()
115
- {
116
- $( this ).remove();
117
- } );
118
- }
119
-
120
- /**
121
- * Adds loading li element
122
- *
123
- * @return void
124
- */
125
- function addLoading( up, file, $ul )
126
- {
127
- $ul.removeClass( 'hidden' ).append( '<li id="' + file.id + '"><div class="rwmb-image-uploading-bar"></div><div id="' + file.id + '-throbber" class="rwmb-image-uploading-status"></div></li>' );
128
- }
129
-
130
- /**
131
- * Adds loading throbber while waiting for a response
132
- *
133
- * @return void
134
- */
135
- function addThrobber( file )
136
- {
137
- $( '#' + file.id + '-throbber' ).html( '<img class="rwmb-loader" height="64" width="64" src="' + RWMB.url + 'img/loader.gif">' );
138
- }
139
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/select-tree.js ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery( function( $ )
2
+ {
3
+ 'use strict';
4
+
5
+ function update()
6
+ {
7
+ var $this = $( this ),
8
+ val = $this.val(),
9
+ $selected = $this.siblings( "[data-parent-id='" + val + "']" ),
10
+ $notSelected = $this.parent().find( '.rwmb-select-tree' ).not( $selected );
11
+
12
+ $selected.removeClass( 'hidden' );
13
+ $notSelected
14
+ .addClass( 'hidden' )
15
+ .find( 'select' )
16
+ .prop( 'selectedIndex', 0 );
17
+ }
18
+
19
+ $( '.rwmb-input' )
20
+ .on( 'change', '.rwmb-select-tree select', update )
21
+ .on( 'clone', '.rwmb-select-tree select', update );
22
+ } );
js/time.js CHANGED
@@ -9,10 +9,26 @@ jQuery( function ( $ )
9
  function update()
10
  {
11
  var $this = $( this ),
12
- options = $this.data( 'options' );
 
 
13
 
14
  $this.siblings( '.ui-datepicker-append' ).remove(); // Remove appended text
15
- $this.removeClass( 'hasDatepicker' ).timepicker( options );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  }
17
 
18
  // Set language if available
9
  function update()
10
  {
11
  var $this = $( this ),
12
+ options = $this.data( 'options' ),
13
+ $inline = $this.siblings( '.rwmb-datetime-inline' ),
14
+ current = $this.val();
15
 
16
  $this.siblings( '.ui-datepicker-append' ).remove(); // Remove appended text
17
+
18
+ if( $inline.length )
19
+ {
20
+ options.altField = '#' + $this.attr( 'id' );
21
+ $inline
22
+ .removeClass( 'hasDatepicker' )
23
+ .empty()
24
+ .prop( 'id', '' )
25
+ .timepicker( options )
26
+ .timepicker( "setTime", current );
27
+ }
28
+ else
29
+ {
30
+ $this.removeClass( 'hasDatepicker' ).timepicker( options );
31
+ }
32
  }
33
 
34
  // Set language if available
meta-box.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Meta Box
4
  * Plugin URI: https://metabox.io
5
  * Description: Create custom meta boxes and custom fields for any post type in WordPress.
6
- * Version: 4.8.3
7
  * Author: Rilwis
8
  * Author URI: http://www.deluxeblogtips.com
9
  * License: GPL2+
3
  * Plugin Name: Meta Box
4
  * Plugin URI: https://metabox.io
5
  * Description: Create custom meta boxes and custom fields for any post type in WordPress.
6
+ * Version: 4.8.4
7
  * Author: Rilwis
8
  * Author URI: http://www.deluxeblogtips.com
9
  * License: GPL2+
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === Meta Box ===
2
- Contributors: rilwis, fitwp, f-j-kaiser, funkatronic, PerWiklander, ruanmer, Omnicia
3
  Donate link: http://www.deluxeblogtips.com/donate
4
  Tags: meta-box, custom fields, custom field, meta, meta-boxes, admin, advanced, custom, edit, field, file, image, magic fields, matrix, more fields, Post, repeater, simple fields, text, textarea, type, cms, fields post
5
  Requires at least: 4.1
6
  Tested up to: 4.4.2
7
- Stable tag: 4.8.3
8
  License: GPLv2 or later
9
 
10
  Meta Box plugin is a powerful, professional solution to create custom meta boxes and custom fields for WordPress websites.
@@ -77,6 +77,23 @@ To getting started with the plugin API, please read [this tutorial](https://meta
77
 
78
  == Changelog ==
79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  = 4.8.3 =
81
  * Improvement: WYSIWYG field now can be cloned. Sorting clone hasn't worked yet.
82
  * Fix: 'std' value not working if there is 'divider' or 'heading' field withough 'id'
1
  === Meta Box ===
2
+ Contributors: metabox, rilwis, fitwp, f-j-kaiser, funkatronic, PerWiklander, ruanmer, Omnicia
3
  Donate link: http://www.deluxeblogtips.com/donate
4
  Tags: meta-box, custom fields, custom field, meta, meta-boxes, admin, advanced, custom, edit, field, file, image, magic fields, matrix, more fields, Post, repeater, simple fields, text, textarea, type, cms, fields post
5
  Requires at least: 4.1
6
  Tested up to: 4.4.2
7
+ Stable tag: 4.8.4
8
  License: GPLv2 or later
9
 
10
  Meta Box plugin is a powerful, professional solution to create custom meta boxes and custom fields for WordPress websites.
77
 
78
  == Changelog ==
79
 
80
+ = 4.8.4 =
81
+ * Improvement: Refactor code for plupload_image. Introduces file_upload and image_upload field which acts the same as plupload_image but for files and images.
82
+ * Improvement: Do not show "Embed is not available" if fields don't have any value
83
+ * Improvement: Refactor date/time related fields. 'timestamp' now works for date field as well.
84
+ * Improvement: Add 'inline' mode for date/datetime fields.
85
+ * Improvement: Add option 'select_all_none' for select/select2 with default = false
86
+ * Fix: users now can register 2 meta boxes with same field IDs for different post types.
87
+ * Fix: width of embeded video if $content_width is too large.
88
+ * Fix: autoloader now works more safely.
89
+ * Fix: post field doesn't show correct post link
90
+ * Fix: select field must call field's get_value to get field's value as 'select' is used in many non-inherited classes
91
+ * Fix: Allows old syntax for `query_args.post_types` for post/user/taxonomy fields
92
+ * Fix: Do not reset value for hidden field when clone
93
+ * Fix: Missing Insert into Post button for thickbox_image field
94
+ * Fix: Date picker cut off by TinyMCE
95
+ * Fix: CSS for multi months in date picker
96
+
97
  = 4.8.3 =
98
  * Improvement: WYSIWYG field now can be cloned. Sorting clone hasn't worked yet.
99
  * Fix: 'std' value not working if there is 'divider' or 'heading' field withough 'id'