Version Description
- September 18th, 2015 =
- Fixed adding custom fields and using an image as an icon (https://gist.github.com/EvanHerman/6bbc8de82f34b4cb3c5c#comments)
Download this release
Release Info
Developer | eherman24 |
Plugin | Timeline Express |
Version | 1.1.7.4 |
Comparing to | |
See all releases |
Code changes from version 1.1.7.3 to 1.1.7.4
- README.md +5 -1
- classes/class.timeline-express.php +8 -4
- lib/cmb_metaboxes/helpers/cmb_Meta_Box_Sanitize.php +346 -0
- lib/cmb_metaboxes/helpers/cmb_Meta_Box_Show_Filters.php +105 -0
- lib/cmb_metaboxes/helpers/cmb_Meta_Box_ajax.php +203 -0
- lib/cmb_metaboxes/helpers/cmb_Meta_Box_field.php +497 -0
- lib/cmb_metaboxes/helpers/cmb_Meta_Box_types.php +794 -0
- lib/cmb_metaboxes/images/ico-delete.png +0 -0
- lib/cmb_metaboxes/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- lib/cmb_metaboxes/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- lib/cmb_metaboxes/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- lib/cmb_metaboxes/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- lib/cmb_metaboxes/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- lib/cmb_metaboxes/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- lib/cmb_metaboxes/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- lib/cmb_metaboxes/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- lib/cmb_metaboxes/images/ui-icons_222222_256x240.png +0 -0
- lib/cmb_metaboxes/images/ui-icons_2e83ff_256x240.png +0 -0
- lib/cmb_metaboxes/images/ui-icons_454545_256x240.png +0 -0
- lib/cmb_metaboxes/images/ui-icons_888888_256x240.png +0 -0
- lib/cmb_metaboxes/images/ui-icons_cd0a0a_256x240.png +0 -0
- lib/cmb_metaboxes/init.php +1185 -0
- lib/cmb_metaboxes/js/cmb.js +797 -0
- lib/cmb_metaboxes/js/cmb.min.js +1 -0
- lib/cmb_metaboxes/js/jquery.datePicker.min.js +2038 -0
- lib/cmb_metaboxes/js/jquery.timePicker.min.js +13 -0
- lib/cmb_metaboxes/readme.md +296 -0
- lib/cmb_metaboxes/style.css +621 -0
- lib/cmb_metaboxes/style.min.css +1 -0
- readme.txt +5 -2
- timeline-express.php +2 -2
README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
Timeline Express v1.1.7.
|
2 |
================
|
3 |
|
4 |
Timeline express allows you to create a vertical animated and responsive timeline of posts , without writing a single line of code. Sweet!
|
@@ -289,6 +289,10 @@ Have an idea for a future release feature? I love hearing about new ideas! You c
|
|
289 |
|
290 |
|
291 |
### Changelog
|
|
|
|
|
|
|
|
|
292 |
###### 1.1.7.3 - July 15th, 2015
|
293 |
* Remove duplicate date picker fields on announcements
|
294 |
|
1 |
+
Timeline Express v1.1.7.4
|
2 |
================
|
3 |
|
4 |
Timeline express allows you to create a vertical animated and responsive timeline of posts , without writing a single line of code. Sweet!
|
289 |
|
290 |
|
291 |
### Changelog
|
292 |
+
|
293 |
+
###### 1.1.7.4 - September 18th, 2015
|
294 |
+
* Fixed adding custom fields and using an image as an icon (https://gist.github.com/EvanHerman/6bbc8de82f34b4cb3c5c#comments)
|
295 |
+
|
296 |
###### 1.1.7.3 - July 15th, 2015
|
297 |
* Remove duplicate date picker fields on announcements
|
298 |
|
classes/class.timeline-express.php
CHANGED
@@ -589,11 +589,15 @@ if(!class_exists("timelineExpressBase"))
|
|
589 |
$custom_fields = apply_filters( 'timeline_express_custom_fields', $custom_field );
|
590 |
$i = 0;
|
591 |
// first, check if any custom fields are defined...
|
592 |
-
if( !empty( $custom_fields ) ) {
|
593 |
foreach( $custom_fields as $user_defined_field ) {
|
594 |
-
|
595 |
-
|
596 |
-
|
|
|
|
|
|
|
|
|
597 |
$i++;
|
598 |
}
|
599 |
}
|
589 |
$custom_fields = apply_filters( 'timeline_express_custom_fields', $custom_field );
|
590 |
$i = 0;
|
591 |
// first, check if any custom fields are defined...
|
592 |
+
if( ! empty( $custom_fields ) ) {
|
593 |
foreach( $custom_fields as $user_defined_field ) {
|
594 |
+
// Email text field
|
595 |
+
$announcement_metabox->add_field( array(
|
596 |
+
'name' => $custom_fields[$i]['name'],
|
597 |
+
'desc' => $custom_fields[$i]['desc'],
|
598 |
+
'id' => $custom_fields[$i]['id'],
|
599 |
+
'type' => $custom_fields[$i]['type'],
|
600 |
+
) );
|
601 |
$i++;
|
602 |
}
|
603 |
}
|
lib/cmb_metaboxes/helpers/cmb_Meta_Box_Sanitize.php
ADDED
@@ -0,0 +1,346 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* CMB field validation
|
5 |
+
* @since 0.0.4
|
6 |
+
*/
|
7 |
+
class cmb_Meta_Box_Sanitize {
|
8 |
+
|
9 |
+
/**
|
10 |
+
* A CMB field object
|
11 |
+
* @var cmb_Meta_Box_field object
|
12 |
+
*/
|
13 |
+
public $field;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Field's $_POST value
|
17 |
+
* @var mixed
|
18 |
+
*/
|
19 |
+
public $value;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Setup our class vars
|
23 |
+
* @since 1.1.0
|
24 |
+
* @param object $field A CMB field object
|
25 |
+
* @param mixed $value Field value
|
26 |
+
*/
|
27 |
+
public function __construct( $field, $value ) {
|
28 |
+
$this->field = $field;
|
29 |
+
$this->value = $value;
|
30 |
+
$this->object_id = cmb_Meta_Box::get_object_id();
|
31 |
+
$this->object_type = cmb_Meta_Box::get_object_type();
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Catchall method if field's 'sanitization_cb' is NOT defined, or field type does not have a corresponding validation method
|
36 |
+
* @since 1.0.0
|
37 |
+
* @param string $name Non-existent method name
|
38 |
+
* @param array $arguments All arguments passed to the method
|
39 |
+
*/
|
40 |
+
public function __call( $name, $arguments ) {
|
41 |
+
list( $value ) = $arguments;
|
42 |
+
return $this->default_sanitization( $value );
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Default fallback sanitization method. Applies filters.
|
47 |
+
* @since 1.0.2
|
48 |
+
* @param mixed $value Meta value
|
49 |
+
*/
|
50 |
+
public function default_sanitization( $value ) {
|
51 |
+
|
52 |
+
// Allow field type validation via filter
|
53 |
+
$updated = apply_filters( 'cmb_validate_'. $this->field->type(), null, $value, $this->object_id, $this->field->args(), $this );
|
54 |
+
|
55 |
+
if ( null !== $updated )
|
56 |
+
return $updated;
|
57 |
+
|
58 |
+
switch ( $this->field->type() ) {
|
59 |
+
case 'wysiwyg':
|
60 |
+
// $value = wp_kses( $value );
|
61 |
+
// break;
|
62 |
+
case 'textarea_small':
|
63 |
+
return $this->textarea( $value );
|
64 |
+
case 'taxonomy_select':
|
65 |
+
case 'taxonomy_radio':
|
66 |
+
case 'taxonomy_multicheck':
|
67 |
+
if ( $this->field->args( 'taxonomy' ) ) {
|
68 |
+
return wp_set_object_terms( $this->object_id, $value, $this->field->args( 'taxonomy' ) );
|
69 |
+
}
|
70 |
+
case 'multicheck':
|
71 |
+
case 'file_list':
|
72 |
+
case 'oembed':
|
73 |
+
// no filtering
|
74 |
+
return $value;
|
75 |
+
default:
|
76 |
+
// Handle repeatable fields array
|
77 |
+
// We'll fallback to 'sanitize_text_field'
|
78 |
+
return is_array( $value ) ? array_map( 'sanitize_text_field', $value ) : call_user_func( 'sanitize_text_field', $value );
|
79 |
+
}
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Simple checkbox validation
|
84 |
+
* @since 1.0.1
|
85 |
+
* @param mixed $val 'on' or false
|
86 |
+
* @return mixed 'on' or false
|
87 |
+
*/
|
88 |
+
public function checkbox( $value ) {
|
89 |
+
return $value === 'on' ? 'on' : false;
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Validate url in a meta value
|
94 |
+
* @since 1.0.1
|
95 |
+
* @param string $value Meta value
|
96 |
+
* @return string Empty string or escaped url
|
97 |
+
*/
|
98 |
+
public function text_url( $value ) {
|
99 |
+
$protocols = $this->field->args( 'protocols' );
|
100 |
+
// for repeatable
|
101 |
+
if ( is_array( $value ) ) {
|
102 |
+
foreach ( $value as $key => $val ) {
|
103 |
+
$value[ $key ] = $val ? esc_url_raw( $val, $protocols ) : $this->field->args( 'default' );
|
104 |
+
}
|
105 |
+
} else {
|
106 |
+
$value = $value ? esc_url_raw( $value, $protocols ) : $this->field->args( 'default' );
|
107 |
+
}
|
108 |
+
|
109 |
+
return $value;
|
110 |
+
}
|
111 |
+
|
112 |
+
public function colorpicker( $value ) {
|
113 |
+
// for repeatable
|
114 |
+
if ( is_array( $value ) ) {
|
115 |
+
$check = $value;
|
116 |
+
$value = array();
|
117 |
+
foreach ( $check as $key => $val ) {
|
118 |
+
if ( $val && '#' != $val ) {
|
119 |
+
$value[ $key ] = esc_attr( $val );
|
120 |
+
}
|
121 |
+
}
|
122 |
+
} else {
|
123 |
+
$value = ! $value || '#' == $value ? '' : esc_attr( $value );
|
124 |
+
}
|
125 |
+
return $value;
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Validate email in a meta value
|
130 |
+
* @since 1.0.1
|
131 |
+
* @param string $value Meta value
|
132 |
+
* @return string Empty string or validated email
|
133 |
+
*/
|
134 |
+
public function text_email( $value ) {
|
135 |
+
// for repeatable
|
136 |
+
if ( is_array( $value ) ) {
|
137 |
+
foreach ( $value as $key => $val ) {
|
138 |
+
$val = trim( $val );
|
139 |
+
$value[ $key ] = is_email( $val ) ? $val : '';
|
140 |
+
}
|
141 |
+
} else {
|
142 |
+
$value = trim( $value );
|
143 |
+
$value = is_email( $value ) ? $value : '';
|
144 |
+
}
|
145 |
+
|
146 |
+
return $value;
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Validate money in a meta value
|
151 |
+
* @since 1.0.1
|
152 |
+
* @param string $value Meta value
|
153 |
+
* @return string Empty string or validated money value
|
154 |
+
*/
|
155 |
+
public function text_money( $value ) {
|
156 |
+
|
157 |
+
global $wp_locale;
|
158 |
+
|
159 |
+
$search = array( $wp_locale->number_format['thousands_sep'], $wp_locale->number_format['decimal_point'] );
|
160 |
+
$replace = array( '', '.' );
|
161 |
+
|
162 |
+
// for repeatable
|
163 |
+
if ( is_array( $value ) ) {
|
164 |
+
foreach ( $value as $key => $val ) {
|
165 |
+
$value[ $key ] = number_format_i18n( (float) str_ireplace( $search, $replace, $val ), 2 );
|
166 |
+
}
|
167 |
+
} else {
|
168 |
+
$value = number_format_i18n( (float) str_ireplace( $search, $replace, $value ), 2 );
|
169 |
+
}
|
170 |
+
|
171 |
+
return $value;
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Converts text date to timestamp
|
176 |
+
* @since 1.0.2
|
177 |
+
* @param string $value Meta value
|
178 |
+
* @return string Timestring
|
179 |
+
*/
|
180 |
+
public function text_date_timestamp( $value ) {
|
181 |
+
return is_array( $value ) ? array_map( 'strtotime', $value ) : strtotime( $value );
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Datetime to timestamp
|
186 |
+
* @since 1.0.1
|
187 |
+
* @param string $value Meta value
|
188 |
+
* @return string Timestring
|
189 |
+
*/
|
190 |
+
public function text_datetime_timestamp( $value, $repeat = false ) {
|
191 |
+
|
192 |
+
$test = is_array( $value ) ? array_filter( $value ) : '';
|
193 |
+
if ( empty( $test ) )
|
194 |
+
return '';
|
195 |
+
|
196 |
+
if ( $repeat_value = $this->_check_repeat( $value, __FUNCTION__, $repeat ) )
|
197 |
+
return $repeat_value;
|
198 |
+
|
199 |
+
$value = strtotime( $value['date'] .' '. $value['time'] );
|
200 |
+
|
201 |
+
if ( $tz_offset = $this->field->field_timezone_offset() )
|
202 |
+
$value += $tz_offset;
|
203 |
+
|
204 |
+
return $value;
|
205 |
+
}
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Datetime to imestamp with timezone
|
209 |
+
* @since 1.0.1
|
210 |
+
* @param string $value Meta value
|
211 |
+
* @return string Timestring
|
212 |
+
*/
|
213 |
+
public function text_datetime_timestamp_timezone( $value, $repeat = false ) {
|
214 |
+
|
215 |
+
$test = is_array( $value ) ? array_filter( $value ) : '';
|
216 |
+
if ( empty( $test ) )
|
217 |
+
return '';
|
218 |
+
|
219 |
+
if ( $repeat_value = $this->_check_repeat( $value, __FUNCTION__, $repeat ) )
|
220 |
+
return $repeat_value;
|
221 |
+
|
222 |
+
$tzstring = null;
|
223 |
+
|
224 |
+
if ( is_array( $value ) && array_key_exists( 'timezone', $value ) )
|
225 |
+
$tzstring = $value['timezone'];
|
226 |
+
|
227 |
+
if ( empty( $tzstring ) )
|
228 |
+
$tzstring = cmb_Meta_Box::timezone_string();
|
229 |
+
|
230 |
+
$offset = cmb_Meta_Box::timezone_offset( $tzstring, true );
|
231 |
+
|
232 |
+
if ( substr( $tzstring, 0, 3 ) === 'UTC' )
|
233 |
+
$tzstring = timezone_name_from_abbr( '', $offset, 0 );
|
234 |
+
|
235 |
+
$value = new DateTime( $value['date'] .' '. $value['time'], new DateTimeZone( $tzstring ) );
|
236 |
+
$value = serialize( $value );
|
237 |
+
|
238 |
+
return $value;
|
239 |
+
}
|
240 |
+
|
241 |
+
/**
|
242 |
+
* Sanitize textareas and wysiwyg fields
|
243 |
+
* @since 1.0.1
|
244 |
+
* @param string $value Meta value
|
245 |
+
* @return string Sanitized data
|
246 |
+
*/
|
247 |
+
public function textarea( $value ) {
|
248 |
+
return is_array( $value ) ? array_map( 'wp_kses_post', $value ) : wp_kses_post( $value );
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Sanitize code textareas
|
253 |
+
* @since 1.0.2
|
254 |
+
* @param string $value Meta value
|
255 |
+
* @return string Sanitized data
|
256 |
+
*/
|
257 |
+
public function textarea_code( $value, $repeat = false ) {
|
258 |
+
if ( $repeat_value = $this->_check_repeat( $value, __FUNCTION__, $repeat ) )
|
259 |
+
return $repeat_value;
|
260 |
+
|
261 |
+
return htmlspecialchars_decode( stripslashes( $value ) );
|
262 |
+
}
|
263 |
+
|
264 |
+
/**
|
265 |
+
* Peforms saving of `file` attachement's ID
|
266 |
+
* @since 1.1.0
|
267 |
+
* @param string $value File url
|
268 |
+
*/
|
269 |
+
public function _save_file_id( $value ) {
|
270 |
+
$group = $this->field->group;
|
271 |
+
$args = $this->field->args();
|
272 |
+
$args['id'] = $args['_id'] . '_id';
|
273 |
+
|
274 |
+
unset( $args['_id'], $args['_name'] );
|
275 |
+
// And get new field object
|
276 |
+
$field = new cmb_Meta_Box_field( $args, $group );
|
277 |
+
$id_key = $field->_id();
|
278 |
+
$id_val_old = $field->escaped_value( 'absint' );
|
279 |
+
|
280 |
+
if ( $group ) {
|
281 |
+
// Check group $_POST data
|
282 |
+
$i = $group->index;
|
283 |
+
$base_id = $group->_id();
|
284 |
+
$id_val = isset( $_POST[ $base_id ][ $i ][ $id_key ] ) ? absint( $_POST[ $base_id ][ $i ][ $id_key ] ) : 0;
|
285 |
+
|
286 |
+
} else {
|
287 |
+
// Check standard $_POST data
|
288 |
+
$id_val = isset( $_POST[ $field->id() ] ) ? $_POST[ $field->id() ] : null;
|
289 |
+
|
290 |
+
}
|
291 |
+
|
292 |
+
// If there is no ID saved yet, try to get it from the url
|
293 |
+
if ( $value && ! $id_val ) {
|
294 |
+
$id_val = cmb_Meta_Box::image_id_from_url( $value );
|
295 |
+
}
|
296 |
+
|
297 |
+
if ( $group ) {
|
298 |
+
return array(
|
299 |
+
'attach_id' => $id_val,
|
300 |
+
'field_id' => $id_key
|
301 |
+
);
|
302 |
+
}
|
303 |
+
|
304 |
+
if ( $id_val && $id_val != $id_val_old ) {
|
305 |
+
return $field->update_data( $id_val );
|
306 |
+
} elseif ( empty( $id_val ) && $id_val_old ) {
|
307 |
+
return $field->remove_data( $old );
|
308 |
+
}
|
309 |
+
}
|
310 |
+
|
311 |
+
/**
|
312 |
+
* Handles saving of attachment post ID and sanitizing file url
|
313 |
+
* @since 1.1.0
|
314 |
+
* @param string $value File url
|
315 |
+
* @return string Sanitized url
|
316 |
+
*/
|
317 |
+
public function file( $value ) {
|
318 |
+
// If NOT specified to NOT save the file ID
|
319 |
+
if ( $this->field->args( 'save_id' ) ) {
|
320 |
+
$id_value = $this->_save_file_id( $value );
|
321 |
+
}
|
322 |
+
$clean = $this->text_url( $value );
|
323 |
+
|
324 |
+
// Return an array with url/id if saving a group field
|
325 |
+
return $this->field->group ? array_merge( array( 'url' => $clean), $id_value ) : $clean;
|
326 |
+
}
|
327 |
+
|
328 |
+
/**
|
329 |
+
* If repeating, loop through and re-apply sanitization method
|
330 |
+
* @since 1.1.0
|
331 |
+
* @param mixed $value Meta value
|
332 |
+
* @param string $method Class method
|
333 |
+
* @param bool $repeat Whether repeating or not
|
334 |
+
* @return mixed Sanitized value
|
335 |
+
*/
|
336 |
+
public function _check_repeat( $value, $method, $repeat ) {
|
337 |
+
if ( $repeat || ! $this->field->args( 'repeatable' ) )
|
338 |
+
return;
|
339 |
+
$new_value = array();
|
340 |
+
foreach ( $value as $iterator => $val ) {
|
341 |
+
$new_value[] = $this->$method( $val, true );
|
342 |
+
}
|
343 |
+
return $new_value;
|
344 |
+
}
|
345 |
+
|
346 |
+
}
|
lib/cmb_metaboxes/helpers/cmb_Meta_Box_Show_Filters.php
ADDED
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Show On Filters
|
5 |
+
* Use the 'cmb_show_on' filter to further refine the conditions under which a metabox is displayed.
|
6 |
+
* Below you can limit it by ID and page template
|
7 |
+
*
|
8 |
+
* All methods in this class are automatically filtered
|
9 |
+
*
|
10 |
+
* @since 1.0.0
|
11 |
+
*/
|
12 |
+
class cmb_Meta_Box_Show_Filters {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Add metaboxes for an specific ID
|
16 |
+
* @since 1.0.0
|
17 |
+
* @param bool $display To display or not
|
18 |
+
* @param array $meta_box Metabox config array
|
19 |
+
* @return bool Whether to display this metabox on the current page.
|
20 |
+
*/
|
21 |
+
public static function check_id( $display, $meta_box ) {
|
22 |
+
|
23 |
+
if ( ! isset( $meta_box['show_on']['key'] ) || 'id' !== $meta_box['show_on']['key'] )
|
24 |
+
return $display;
|
25 |
+
|
26 |
+
$object_id = is_admin() ? cmb_Meta_Box::get_object_id() : @get_the_id();
|
27 |
+
|
28 |
+
if ( ! $object_id )
|
29 |
+
return false;
|
30 |
+
|
31 |
+
// If current page id is in the included array, display the metabox
|
32 |
+
return in_array( $object_id, (array) $meta_box['show_on']['value'] );
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Add metaboxes for an specific Page Template
|
37 |
+
* @since 1.0.0
|
38 |
+
* @param bool $display To display or not
|
39 |
+
* @param array $meta_box Metabox config array
|
40 |
+
* @return bool Whether to display this metabox on the current page.
|
41 |
+
*/
|
42 |
+
public static function check_page_template( $display, $meta_box ) {
|
43 |
+
|
44 |
+
if ( ! isset( $meta_box['show_on']['key'] ) || 'page-template' !== $meta_box['show_on']['key'] )
|
45 |
+
return $display;
|
46 |
+
|
47 |
+
$object_id = cmb_Meta_Box::get_object_id();
|
48 |
+
|
49 |
+
if ( ! $object_id || cmb_Meta_Box::get_object_type() !== 'post' )
|
50 |
+
return false;
|
51 |
+
|
52 |
+
// Get current template
|
53 |
+
$current_template = get_post_meta( $object_id, '_wp_page_template', true );
|
54 |
+
|
55 |
+
// See if there's a match
|
56 |
+
if ( $current_template && in_array( $current_template, (array) $meta_box['show_on']['value'] ) )
|
57 |
+
return true;
|
58 |
+
|
59 |
+
return false;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Only show options-page metaboxes on their options page (but only enforce on the admin side)
|
64 |
+
* @since 1.0.0
|
65 |
+
* @param bool $display To display or not
|
66 |
+
* @param array $meta_box Metabox config array
|
67 |
+
* @return bool Whether to display this metabox on the current page.
|
68 |
+
*/
|
69 |
+
public static function check_admin_page( $display, $meta_box ) {
|
70 |
+
|
71 |
+
// check if this is a 'options-page' metabox
|
72 |
+
if ( ! isset( $meta_box['show_on']['key'] ) || 'options-page' !== $meta_box['show_on']['key'] )
|
73 |
+
return $display;
|
74 |
+
|
75 |
+
// Enforce 'show_on' filter in the admin
|
76 |
+
if ( is_admin() ) {
|
77 |
+
|
78 |
+
// If there is no 'page' query var, our filter isn't applicable
|
79 |
+
if ( ! isset( $_GET['page'] ) )
|
80 |
+
return $display;
|
81 |
+
|
82 |
+
if ( ! isset( $meta_box['show_on']['value'] ) )
|
83 |
+
return false;
|
84 |
+
|
85 |
+
$pages = $meta_box['show_on']['value'];
|
86 |
+
|
87 |
+
if ( is_array( $pages ) ) {
|
88 |
+
foreach ( $pages as $page ) {
|
89 |
+
if ( $_GET['page'] == $page )
|
90 |
+
return true;
|
91 |
+
}
|
92 |
+
} else {
|
93 |
+
if ( $_GET['page'] == $pages )
|
94 |
+
return true;
|
95 |
+
}
|
96 |
+
|
97 |
+
return false;
|
98 |
+
|
99 |
+
}
|
100 |
+
|
101 |
+
// Allow options-page metaboxes to be displayed anywhere on the front-end
|
102 |
+
return true;
|
103 |
+
}
|
104 |
+
|
105 |
+
}
|
lib/cmb_metaboxes/helpers/cmb_Meta_Box_ajax.php
ADDED
@@ -0,0 +1,203 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* CMB ajax methods
|
5 |
+
* (i.e. a lot of work to get oEmbeds to work with non-post objects)
|
6 |
+
*
|
7 |
+
* @since 0.9.5
|
8 |
+
*/
|
9 |
+
class cmb_Meta_Box_ajax {
|
10 |
+
|
11 |
+
// A single instance of this class.
|
12 |
+
public static $instance = null;
|
13 |
+
// Whether to hijack the oembed cache system
|
14 |
+
public static $hijack = false;
|
15 |
+
public static $object_id = 0;
|
16 |
+
public static $embed_args = array();
|
17 |
+
public static $object_type = 'post';
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Creates or returns an instance of this class.
|
21 |
+
* @since 0.1.0
|
22 |
+
* @return cmb_Meta_Box_ajax A single instance of this class.
|
23 |
+
*/
|
24 |
+
public static function get() {
|
25 |
+
if ( self::$instance === null )
|
26 |
+
self::$instance = new self();
|
27 |
+
|
28 |
+
return self::$instance;
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Handles our oEmbed ajax request
|
33 |
+
* @since 0.9.5
|
34 |
+
* @return object oEmbed embed code | fallback | error message
|
35 |
+
*/
|
36 |
+
public function oembed_handler() {
|
37 |
+
|
38 |
+
// verify our nonce
|
39 |
+
if ( ! ( isset( $_REQUEST['cmb_ajax_nonce'], $_REQUEST['oembed_url'] ) && wp_verify_nonce( $_REQUEST['cmb_ajax_nonce'], 'ajax_nonce' ) ) )
|
40 |
+
die();
|
41 |
+
|
42 |
+
// sanitize our search string
|
43 |
+
$oembed_string = sanitize_text_field( $_REQUEST['oembed_url'] );
|
44 |
+
|
45 |
+
// send back error if empty
|
46 |
+
if ( empty( $oembed_string ) )
|
47 |
+
self::send_result( '<p class="ui-state-error-text">'. __( 'Please Try Again', 'cmb' ) .'</p>', false );
|
48 |
+
|
49 |
+
// Set width of embed
|
50 |
+
$embed_width = isset( $_REQUEST['oembed_width'] ) && intval( $_REQUEST['oembed_width'] ) < 640 ? intval( $_REQUEST['oembed_width'] ) : '640';
|
51 |
+
|
52 |
+
// set url
|
53 |
+
$oembed_url = esc_url( $oembed_string );
|
54 |
+
// set args
|
55 |
+
$embed_args = array( 'width' => $embed_width );
|
56 |
+
|
57 |
+
// Get embed code (or fallback link)
|
58 |
+
$html = self::get_oembed( $oembed_url, $_REQUEST['object_id'], array(
|
59 |
+
'object_type' => isset( $_REQUEST['object_type'] ) ? $_REQUEST['object_type'] : 'post',
|
60 |
+
'oembed_args' => $embed_args,
|
61 |
+
'field_id' => $_REQUEST['field_id'],
|
62 |
+
) );
|
63 |
+
|
64 |
+
self::send_result( $html );
|
65 |
+
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Retrieves oEmbed from url/object ID
|
70 |
+
* @since 0.9.5
|
71 |
+
* @param string $url URL to retrieve oEmbed
|
72 |
+
* @param int $object_id Object ID
|
73 |
+
* @param array $args Arguments for method
|
74 |
+
* @return string html markup with embed or fallback
|
75 |
+
*/
|
76 |
+
public static function get_oembed( $url, $object_id, $args = array() ) {
|
77 |
+
global $wp_embed;
|
78 |
+
|
79 |
+
$oembed_url = esc_url( $url );
|
80 |
+
|
81 |
+
// Sanitize object_id
|
82 |
+
self::$object_id = is_numeric( $object_id ) ? absint( $object_id ) : sanitize_text_field( $object_id );
|
83 |
+
|
84 |
+
$args = wp_parse_args( $args, array(
|
85 |
+
'object_type' => 'post',
|
86 |
+
'oembed_args' => self::$embed_args,
|
87 |
+
'field_id' => false,
|
88 |
+
'cache_key' => false,
|
89 |
+
) );
|
90 |
+
|
91 |
+
self::$embed_args =& $args;
|
92 |
+
|
93 |
+
// set the post_ID so oEmbed won't fail
|
94 |
+
// wp-includes/class-wp-embed.php, WP_Embed::shortcode(), line 162
|
95 |
+
$wp_embed->post_ID = self::$object_id;
|
96 |
+
|
97 |
+
// Special scenario if NOT a post object
|
98 |
+
if ( isset( $args['object_type'] ) && $args['object_type'] != 'post' ) {
|
99 |
+
|
100 |
+
if ( 'options-page' == $args['object_type'] ) {
|
101 |
+
// bogus id to pass some numeric checks
|
102 |
+
// Issue with a VERY large WP install?
|
103 |
+
$wp_embed->post_ID = 1987645321;
|
104 |
+
// Use our own cache key to correspond to this field (vs one cache key per url)
|
105 |
+
$args['cache_key'] = $args['field_id'] .'_cache';
|
106 |
+
}
|
107 |
+
// Ok, we need to hijack the oembed cache system
|
108 |
+
self::$hijack = true;
|
109 |
+
self::$object_type = $args['object_type'];
|
110 |
+
|
111 |
+
// Gets ombed cache from our object's meta (vs postmeta)
|
112 |
+
add_filter( 'get_post_metadata', array( 'cmb_Meta_Box_ajax', 'hijack_oembed_cache_get' ), 10, 3 );
|
113 |
+
// Sets ombed cache in our object's meta (vs postmeta)
|
114 |
+
add_filter( 'update_post_metadata', array( 'cmb_Meta_Box_ajax', 'hijack_oembed_cache_set' ), 10, 4 );
|
115 |
+
|
116 |
+
}
|
117 |
+
|
118 |
+
$embed_args = '';
|
119 |
+
foreach ( $args['oembed_args'] as $key => $val ) {
|
120 |
+
$embed_args .= " $key=\"$val\"";
|
121 |
+
}
|
122 |
+
|
123 |
+
// ping WordPress for an embed
|
124 |
+
$check_embed = $wp_embed->run_shortcode( '[embed'. $embed_args .']'. $oembed_url .'[/embed]' );
|
125 |
+
|
126 |
+
// fallback that WordPress creates when no oEmbed was found
|
127 |
+
$fallback = $wp_embed->maybe_make_link( $oembed_url );
|
128 |
+
|
129 |
+
// Send back our embed
|
130 |
+
if ( $check_embed && $check_embed != $fallback )
|
131 |
+
return '<div class="embed_status">'. $check_embed .'<p class="cmb_remove_wrapper"><a href="#" class="cmb_remove_file_button" rel="'. $args['field_id'] .'">'. __( 'Remove Embed', 'cmb' ) .'</a></p></div>';
|
132 |
+
|
133 |
+
// Otherwise, send back error info that no oEmbeds were found
|
134 |
+
return '<p class="ui-state-error-text">'. sprintf( __( 'No oEmbed Results Found for %s. View more info at', 'cmb' ), $fallback ) .' <a href="http://codex.wordpress.org/Embeds" target="_blank">codex.wordpress.org/Embeds</a>.</p>';
|
135 |
+
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Hijacks retrieving of cached oEmbed.
|
140 |
+
* Returns cached data from relevant object metadata (vs postmeta)
|
141 |
+
*
|
142 |
+
* @since 0.9.5
|
143 |
+
* @param boolean $check Whether to retrieve postmeta or override
|
144 |
+
* @param int $object_id Object ID
|
145 |
+
* @param string $meta_key Object metakey
|
146 |
+
* @return mixed Object's oEmbed cached data
|
147 |
+
*/
|
148 |
+
public static function hijack_oembed_cache_get( $check, $object_id, $meta_key ) {
|
149 |
+
|
150 |
+
if ( ! self::$hijack || ( self::$object_id != $object_id && 1987645321 !== $object_id ) )
|
151 |
+
return $check;
|
152 |
+
|
153 |
+
// get cached data
|
154 |
+
$data = 'options-page' === self::$object_type
|
155 |
+
? cmb_Meta_Box::get_option( self::$object_id, self::$embed_args['cache_key'] )
|
156 |
+
: get_metadata( self::$object_type, self::$object_id, $meta_key, true );
|
157 |
+
|
158 |
+
return $data;
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Hijacks saving of cached oEmbed.
|
163 |
+
* Saves cached data to relevant object metadata (vs postmeta)
|
164 |
+
*
|
165 |
+
* @since 0.9.5
|
166 |
+
* @param boolean $check Whether to continue setting postmeta
|
167 |
+
* @param int $object_id Object ID to get postmeta from
|
168 |
+
* @param string $meta_key Postmeta's key
|
169 |
+
* @param mixed $meta_value Value of the postmeta to be saved
|
170 |
+
* @return boolean Whether to continue setting
|
171 |
+
*/
|
172 |
+
public static function hijack_oembed_cache_set( $check, $object_id, $meta_key, $meta_value ) {
|
173 |
+
if ( ! self::$hijack || ( self::$object_id != $object_id && 1987645321 !== $object_id ) )
|
174 |
+
return $check;
|
175 |
+
|
176 |
+
// Cache the result to our metadata
|
177 |
+
if ( 'options-page' === self::$object_type ) {
|
178 |
+
// Set the option
|
179 |
+
cmb_Meta_Box::update_option( self::$object_id, self::$embed_args['cache_key'], $meta_value, array( 'type' => 'oembed' ) );
|
180 |
+
// Save the option
|
181 |
+
cmb_Meta_Box::save_option( self::$object_id );
|
182 |
+
} else {
|
183 |
+
update_metadata( self::$object_type, self::$object_id, $meta_key, $meta_value );
|
184 |
+
}
|
185 |
+
|
186 |
+
// Anything other than `null` to cancel saving to postmeta
|
187 |
+
return true;
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* Helper to send json encoded response to ajax
|
192 |
+
* @since 0.9.5
|
193 |
+
* @param string $data Data to be shown via ajax
|
194 |
+
* @param boolean $success Success or fail
|
195 |
+
*/
|
196 |
+
public static function send_result( $data, $success = true ) {
|
197 |
+
$found = $success ? 'found' : 'not found';
|
198 |
+
// send back our encoded data
|
199 |
+
echo json_encode( array( 'result' => $data, 'id' => $found ) );
|
200 |
+
die();
|
201 |
+
}
|
202 |
+
|
203 |
+
}
|
lib/cmb_metaboxes/helpers/cmb_Meta_Box_field.php
ADDED
@@ -0,0 +1,497 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* CMB field class
|
5 |
+
* @since 1.1.0
|
6 |
+
*/
|
7 |
+
class cmb_Meta_Box_field {
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Metabox object id
|
11 |
+
* @var mixed
|
12 |
+
* @since 1.1.0
|
13 |
+
*/
|
14 |
+
public $object_id;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Metabox object type
|
18 |
+
* @var mixed
|
19 |
+
* @since 1.1.0
|
20 |
+
*/
|
21 |
+
public $object_type;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Field arguments
|
25 |
+
* @var mixed
|
26 |
+
* @since 1.1.0
|
27 |
+
*/
|
28 |
+
public $args;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Field group object
|
32 |
+
* @var mixed
|
33 |
+
* @since 1.1.0
|
34 |
+
*/
|
35 |
+
public $group;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Field meta value
|
39 |
+
* @var mixed
|
40 |
+
* @since 1.1.0
|
41 |
+
*/
|
42 |
+
public $value;
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Constructs our field object
|
46 |
+
* @since 1.1.0
|
47 |
+
* @param array $field_args Field arguments
|
48 |
+
* @param array $group_field (optional) Group field object
|
49 |
+
*/
|
50 |
+
public function __construct( $field_args, $group_field = null ) {
|
51 |
+
$this->object_id = cmb_Meta_Box::get_object_id();
|
52 |
+
$this->object_type = cmb_Meta_Box::get_object_type();
|
53 |
+
$this->group = ! empty( $group_field ) ? $group_field : false;
|
54 |
+
$this->args = $this->_set_field_defaults( $field_args );
|
55 |
+
|
56 |
+
// Allow an override for the field's value
|
57 |
+
// (assuming no one would want to save 'cmb_no_override_val' as a value)
|
58 |
+
$this->value = apply_filters( 'cmb_override_meta_value', 'cmb_no_override_val', $this->object_id, $this->args(), $this->object_type, $this );
|
59 |
+
|
60 |
+
// If no override, get our meta
|
61 |
+
$this->value = 'cmb_no_override_val' === $this->value
|
62 |
+
? $this->get_data()
|
63 |
+
: $this->value;
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Non-existent methods fallback to checking for field arguments of the same name
|
68 |
+
* @since 1.1.0
|
69 |
+
* @param string $name Method name
|
70 |
+
* @param array $arguments Array of passed-in arguments
|
71 |
+
* @return mixed Value of field argument
|
72 |
+
*/
|
73 |
+
public function __call( $name, $arguments ) {
|
74 |
+
$key = isset( $arguments[0] ) ? $arguments[0] : false;
|
75 |
+
return $this->args( $name, $key );
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Retrieves the field id
|
80 |
+
* @since 1.1.0
|
81 |
+
* @param boolean $raw Whether to retrieve pre-modidifed id
|
82 |
+
* @return string Field id
|
83 |
+
*/
|
84 |
+
public function id( $raw = false ) {
|
85 |
+
$id = $raw ? '_id' : 'id';
|
86 |
+
return $this->args( $id );
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Get a field argument
|
91 |
+
* @since 1.1.0
|
92 |
+
* @param string $key Argument to check
|
93 |
+
* @param string $key Sub argument to check
|
94 |
+
* @return mixed Argument value or false if non-existent
|
95 |
+
*/
|
96 |
+
public function args( $key = '', $_key = '' ) {
|
97 |
+
$vars = $this->_data( 'args', $key );
|
98 |
+
if ( $_key ) {
|
99 |
+
return isset( $vars[ $_key ] ) ? $vars[ $_key ] : false;
|
100 |
+
}
|
101 |
+
return $vars;
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Get Field's value
|
106 |
+
* @since 1.1.0
|
107 |
+
* @param string $key If value is an array, is used to get array key->value
|
108 |
+
* @return mixed Field value or false if non-existent
|
109 |
+
*/
|
110 |
+
public function value( $key = '' ) {
|
111 |
+
return $this->_data( 'value', $key );
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Retrieve a portion of a field property
|
116 |
+
* @since 1.1.0
|
117 |
+
* @param string $var Field property to check
|
118 |
+
* @param string $key Field property array key to check
|
119 |
+
* @return mixed Queried property value or false
|
120 |
+
*/
|
121 |
+
public function _data( $var, $key = '' ) {
|
122 |
+
$vars = $this->$var;
|
123 |
+
if ( $key ) {
|
124 |
+
return isset( $vars[ $key ] ) ? $vars[ $key ] : false;
|
125 |
+
}
|
126 |
+
return $vars;
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Retrieves metadata/option data
|
131 |
+
* @since 1.0.1
|
132 |
+
* @param string $field_id Meta key/Option array key
|
133 |
+
* @return mixed Meta/Option value
|
134 |
+
*/
|
135 |
+
public function get_data( $field_id = '', $args = array() ) {
|
136 |
+
if ( $field_id ) {
|
137 |
+
$args['field_id'] = $field_id;
|
138 |
+
} else if ( $this->group ) {
|
139 |
+
$args['field_id'] = $this->group->id();
|
140 |
+
}
|
141 |
+
extract( $this->data_args( $args ) );
|
142 |
+
|
143 |
+
$data = 'options-page' === $type
|
144 |
+
? cmb_Meta_Box::get_option( $id, $field_id )
|
145 |
+
: get_metadata( $type, $id, $field_id, ( $single || $repeat ) /* If multicheck this can be multiple values */ );
|
146 |
+
|
147 |
+
if ( $this->group && $data ) {
|
148 |
+
$data = isset( $data[ $this->group->args( 'count' ) ][ $this->args( '_id' ) ] )
|
149 |
+
? $data[ $this->group->args( 'count' ) ][ $this->args( '_id' ) ]
|
150 |
+
: false;
|
151 |
+
}
|
152 |
+
return $data;
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Updates metadata/option data
|
157 |
+
* @since 1.0.1
|
158 |
+
* @param mixed $value Value to update data with
|
159 |
+
* @param bool $single Whether data is an array (add_metadata)
|
160 |
+
*/
|
161 |
+
public function update_data( $new_value, $single = true ) {
|
162 |
+
extract( $this->data_args( array( 'new_value' => $new_value, 'single' => $single ) ) );
|
163 |
+
|
164 |
+
$new_value = $repeat ? array_values( $new_value ) : $new_value;
|
165 |
+
|
166 |
+
if ( 'options-page' === $type )
|
167 |
+
return cmb_Meta_Box::update_option( $id, $field_id, $new_value, $single );
|
168 |
+
|
169 |
+
if ( ! $single )
|
170 |
+
return add_metadata( $type, $id, $field_id, $new_value, false );
|
171 |
+
|
172 |
+
return update_metadata( $type, $id, $field_id, $new_value );
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Removes/updates metadata/option data
|
177 |
+
* @since 1.0.1
|
178 |
+
* @param string $old Old value
|
179 |
+
*/
|
180 |
+
public function remove_data( $old = '' ) {
|
181 |
+
extract( $this->data_args() );
|
182 |
+
|
183 |
+
return 'options-page' === $type
|
184 |
+
? cmb_Meta_Box::remove_option( $id, $field_id )
|
185 |
+
: delete_metadata( $type, $id, $field_id, $old );
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* data variables for get/set data methods
|
190 |
+
* @since 1.1.0
|
191 |
+
* @param array $args Override arguments
|
192 |
+
* @return array Updated arguments
|
193 |
+
*/
|
194 |
+
public function data_args( $args = array() ) {
|
195 |
+
$args = wp_parse_args( $args, array(
|
196 |
+
'type' => $this->object_type,
|
197 |
+
'id' => $this->object_id,
|
198 |
+
'field_id' => $this->id( true ),
|
199 |
+
'repeat' => $this->args( 'repeatable' ),
|
200 |
+
'single' => ! $this->args( 'multiple' ),
|
201 |
+
) );
|
202 |
+
return $args;
|
203 |
+
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Checks if field has a registered validation callback
|
207 |
+
* @since 1.0.1
|
208 |
+
* @param mixed $meta_value Meta value
|
209 |
+
* @return mixed Possibly validated meta value
|
210 |
+
*/
|
211 |
+
public function sanitization_cb( $meta_value ) {
|
212 |
+
if ( empty( $meta_value ) )
|
213 |
+
return $meta_value;
|
214 |
+
|
215 |
+
// Check if the field has a registered validation callback
|
216 |
+
$cb = $this->maybe_callback( 'sanitization_cb' );
|
217 |
+
if ( false === $cb ) {
|
218 |
+
// If requestion NO validation, return meta value
|
219 |
+
return $meta_value;
|
220 |
+
} elseif ( $cb ) {
|
221 |
+
// Ok, callback is good, let's run it.
|
222 |
+
return call_user_func( $cb, $meta_value, $this->args(), $this );
|
223 |
+
}
|
224 |
+
|
225 |
+
$clean = new cmb_Meta_Box_Sanitize( $this, $meta_value );
|
226 |
+
// Validation via 'cmb_Meta_Box_Sanitize' (with fallback filter)
|
227 |
+
return $clean->{$this->type()}( $meta_value );
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* Checks if field has a callback value
|
232 |
+
* @since 1.0.1
|
233 |
+
* @param string $cb Callback string
|
234 |
+
* @return mixed NULL, false for NO validation, or $cb string if it exists.
|
235 |
+
*/
|
236 |
+
public function maybe_callback( $cb ) {
|
237 |
+
$field_args = $this->args();
|
238 |
+
if ( ! isset( $field_args[ $cb ] ) )
|
239 |
+
return;
|
240 |
+
|
241 |
+
// Check if metabox is requesting NO validation
|
242 |
+
$cb = false !== $field_args[ $cb ] && 'false' !== $field_args[ $cb ] ? $field_args[ $cb ] : false;
|
243 |
+
|
244 |
+
// If requestion NO validation, return false
|
245 |
+
if ( ! $cb )
|
246 |
+
return false;
|
247 |
+
|
248 |
+
if ( is_callable( $cb ) )
|
249 |
+
return $cb;
|
250 |
+
}
|
251 |
+
|
252 |
+
/**
|
253 |
+
* Determine if current type is excempt from escaping
|
254 |
+
* @since 1.1.0
|
255 |
+
* @return bool True if exempt
|
256 |
+
*/
|
257 |
+
public function escaping_exception() {
|
258 |
+
// These types cannot be escaped
|
259 |
+
return in_array( $this->type(), array(
|
260 |
+
'file_list',
|
261 |
+
'multicheck',
|
262 |
+
'text_datetime_timestamp_timezone',
|
263 |
+
) );
|
264 |
+
}
|
265 |
+
|
266 |
+
/**
|
267 |
+
* Determine if current type cannot be repeatable
|
268 |
+
* @since 1.1.0
|
269 |
+
* @param string $type Field type to check
|
270 |
+
* @return bool True if type cannot be repeatable
|
271 |
+
*/
|
272 |
+
public function repeatable_exception( $type ) {
|
273 |
+
// These types cannot be escaped
|
274 |
+
return in_array( $type, array(
|
275 |
+
'file', // Use file_list
|
276 |
+
'radio',
|
277 |
+
'title',
|
278 |
+
'group',
|
279 |
+
// @todo Ajax load wp_editor: http://wordpress.stackexchange.com/questions/51776/how-to-load-wp-editor-through-ajax-jquery
|
280 |
+
'wysiwyg',
|
281 |
+
'checkbox',
|
282 |
+
'radio_inline',
|
283 |
+
'taxonomy_radio',
|
284 |
+
'taxonomy_select',
|
285 |
+
'taxonomy_multicheck',
|
286 |
+
) );
|
287 |
+
}
|
288 |
+
|
289 |
+
/**
|
290 |
+
* Escape the value before output. Defaults to 'esc_attr()'
|
291 |
+
* @since 1.0.1
|
292 |
+
* @param mixed $meta_value Meta value
|
293 |
+
* @param mixed $func Escaping function (if not esc_attr())
|
294 |
+
* @return mixed Final value
|
295 |
+
*/
|
296 |
+
public function escaped_value( $func = 'esc_attr', $meta_value = '' ) {
|
297 |
+
|
298 |
+
if ( isset( $this->escaped_value ) )
|
299 |
+
return $this->escaped_value;
|
300 |
+
|
301 |
+
$meta_value = $meta_value ? $meta_value : $this->value();
|
302 |
+
// Check if the field has a registered escaping callback
|
303 |
+
$cb = $this->maybe_callback( 'escape_cb' );
|
304 |
+
if ( false === $cb || $this->escaping_exception() ) {
|
305 |
+
// If requesting NO escaping, return meta value
|
306 |
+
return ! empty( $meta_value ) ? $meta_value : $this->args( 'default' );
|
307 |
+
} elseif ( $cb ) {
|
308 |
+
// Ok, callback is good, let's run it.
|
309 |
+
return call_user_func( $cb, $meta_value, $this->args(), $this );
|
310 |
+
}
|
311 |
+
|
312 |
+
// Or custom escaping filter can be used
|
313 |
+
$esc = apply_filters( 'cmb_types_esc_'. $this->type(), null, $meta_value, $this->args(), $this );
|
314 |
+
if ( null !== $esc ) {
|
315 |
+
return $esc;
|
316 |
+
}
|
317 |
+
|
318 |
+
// escaping function passed in?
|
319 |
+
$func = $func ? $func : 'esc_attr';
|
320 |
+
$meta_value = ! empty( $meta_value ) ? $meta_value : $this->args( 'default' );
|
321 |
+
|
322 |
+
if ( is_array( $meta_value ) ) {
|
323 |
+
foreach ( $meta_value as $key => $value ) {
|
324 |
+
$meta_value[ $key ] = call_user_func( $func, $value );
|
325 |
+
}
|
326 |
+
} else {
|
327 |
+
$meta_value = call_user_func( $func, $meta_value );
|
328 |
+
}
|
329 |
+
|
330 |
+
$this->escaped_value = $meta_value;
|
331 |
+
return $this->escaped_value;
|
332 |
+
}
|
333 |
+
|
334 |
+
/**
|
335 |
+
* Offset a time value based on timezone
|
336 |
+
* @since 1.0.0
|
337 |
+
* @return string Offset time string
|
338 |
+
*/
|
339 |
+
public function field_timezone_offset() {
|
340 |
+
return cmb_Meta_Box::timezone_offset( $this->field_timezone() );
|
341 |
+
}
|
342 |
+
|
343 |
+
/**
|
344 |
+
* Return timezone string
|
345 |
+
* @since 1.0.0
|
346 |
+
* @return string Timezone string
|
347 |
+
*/
|
348 |
+
public function field_timezone() {
|
349 |
+
|
350 |
+
// Is timezone arg set?
|
351 |
+
if ( $this->args( 'timezone' ) ) {
|
352 |
+
return $this->args( 'timezone' ) ;
|
353 |
+
}
|
354 |
+
// Is there another meta key with a timezone stored as its value we should use?
|
355 |
+
else if ( $this->args( 'timezone_meta_key' ) ) {
|
356 |
+
return $this->get_data( $this->args( 'timezone_meta_key' ) );
|
357 |
+
}
|
358 |
+
|
359 |
+
return false;
|
360 |
+
}
|
361 |
+
|
362 |
+
/**
|
363 |
+
* Render a field row
|
364 |
+
* @since 1.0.0
|
365 |
+
*/
|
366 |
+
public function render_field() {
|
367 |
+
|
368 |
+
// If field is requesting to not be shown on the front-end
|
369 |
+
if ( ! is_admin() && ! $this->args( 'on_front' ) )
|
370 |
+
return;
|
371 |
+
|
372 |
+
// If field is requesting to be conditionally shown
|
373 |
+
if ( is_callable( $this->args( 'show_on_cb' ) ) && ! call_user_func( $this->args( 'show_on_cb' ), $this ) )
|
374 |
+
return;
|
375 |
+
|
376 |
+
$classes = 'cmb-type-'. sanitize_html_class( $this->type() );
|
377 |
+
$classes .= ' cmb_id_'. sanitize_html_class( $this->id() );
|
378 |
+
$classes .= $this->args( 'repeatable' ) ? ' cmb-repeat' : '';
|
379 |
+
// 'inline' flag, or _inline in the field type, set to true
|
380 |
+
$classes .= $this->args( 'inline' ) ? ' cmb-inline' : '';
|
381 |
+
$is_side = 'side' === $this->args( 'context' );
|
382 |
+
|
383 |
+
printf( "<tr class=\"%s\">\n", $classes );
|
384 |
+
|
385 |
+
if ( 'title' == $this->type() || ! $this->args( 'show_names' ) || $is_side ) {
|
386 |
+
echo "\t<td colspan=\"2\">\n";
|
387 |
+
|
388 |
+
if ( ! $this->args( 'show_names' ) || $is_side ) {
|
389 |
+
$style = ! $is_side || 'title' == $this->type() ? ' style="display:none;"' : '';
|
390 |
+
printf( "\n<label%s for=\"%s\">%s</label>\n", $style, $this->id(), $this->args( 'name' ) );
|
391 |
+
}
|
392 |
+
} else {
|
393 |
+
|
394 |
+
$style = 'post' == $this->object_type ? ' style="width:18%"' : '';
|
395 |
+
// $tag = 'side' !== $this->args( 'context' ) ? 'th' : 'p';
|
396 |
+
$tag = 'th';
|
397 |
+
printf( '<%1$s%2$s><label for="%3$s">%4$s</label></%1$s>', $tag, $style, $this->id(), $this->args( 'name' ) );
|
398 |
+
|
399 |
+
echo "\n\t<td>\n";
|
400 |
+
}
|
401 |
+
|
402 |
+
echo $this->args( 'before' );
|
403 |
+
|
404 |
+
$this_type = new cmb_Meta_Box_types( $this );
|
405 |
+
$this_type->render();
|
406 |
+
|
407 |
+
echo $this->args( 'after' );
|
408 |
+
|
409 |
+
echo "\n\t</td>\n</tr>";
|
410 |
+
}
|
411 |
+
|
412 |
+
/**
|
413 |
+
* Replaces a hash key - {#} - with the repeatable count
|
414 |
+
* @since 1.2.0
|
415 |
+
* @param string $value Value to update
|
416 |
+
* @return string Updated value
|
417 |
+
*/
|
418 |
+
public function replace_hash( $value ) {
|
419 |
+
// Replace hash with 1 based count
|
420 |
+
return str_ireplace( '{#}', ( $this->count() + 1 ), $value );
|
421 |
+
}
|
422 |
+
|
423 |
+
/**
|
424 |
+
* Fills in empty field parameters with defaults
|
425 |
+
* @since 1.1.0
|
426 |
+
* @param array $args Metabox field config array
|
427 |
+
*/
|
428 |
+
public function _set_field_defaults( $args ) {
|
429 |
+
|
430 |
+
// Set up blank or default values for empty ones
|
431 |
+
if ( ! isset( $args['name'] ) ) $args['name'] = '';
|
432 |
+
if ( ! isset( $args['desc'] ) ) $args['desc'] = '';
|
433 |
+
if ( ! isset( $args['before'] ) ) $args['before'] = '';
|
434 |
+
if ( ! isset( $args['after'] ) ) $args['after'] = '';
|
435 |
+
if ( ! isset( $args['protocols'] ) ) $args['protocols'] = null;
|
436 |
+
if ( ! isset( $args['description'] ) ) {
|
437 |
+
$args['description'] = isset( $args['desc'] ) ? $args['desc'] : '';
|
438 |
+
}
|
439 |
+
if ( ! isset( $args['default'] ) ) {
|
440 |
+
// Phase out 'std', and use 'default' instead
|
441 |
+
$args['default'] = isset( $args['std'] ) ? $args['std'] : '';
|
442 |
+
}
|
443 |
+
if ( ! isset( $args['preview_size'] ) ) $args['preview_size'] = array( 50, 50 );
|
444 |
+
if ( ! isset( $args['date_format'] ) ) $args['date_format'] = 'm\/d\/Y';
|
445 |
+
if ( ! isset( $args['time_format'] ) ) $args['time_format'] = 'h:i A';
|
446 |
+
// Allow a filter override of the default value
|
447 |
+
$args['default'] = apply_filters( 'cmb_default_filter', $args['default'], $args, $this->object_type, $this->object_type );
|
448 |
+
$args['allow'] = 'file' == $args['type'] && ! isset( $args['allow'] ) ? array( 'url', 'attachment' ) : array();
|
449 |
+
$args['save_id'] = 'file' == $args['type'] && ! ( isset( $args['save_id'] ) && ! $args['save_id'] );
|
450 |
+
// $args['multiple'] = isset( $args['multiple'] ) ? $args['multiple'] : ( 'multicheck' == $args['type'] ? true : false );
|
451 |
+
$args['multiple'] = isset( $args['multiple'] ) ? $args['multiple'] : false;
|
452 |
+
$args['repeatable'] = isset( $args['repeatable'] ) && $args['repeatable'] && ! $this->repeatable_exception( $args['type'] );
|
453 |
+
$args['inline'] = isset( $args['inline'] ) && $args['inline'] || false !== stripos( $args['type'], '_inline' );
|
454 |
+
$args['on_front'] = ! ( isset( $args['on_front'] ) && ! $args['on_front'] );
|
455 |
+
$args['attributes'] = isset( $args['attributes'] ) && is_array( $args['attributes'] ) ? $args['attributes'] : array();
|
456 |
+
$args['options'] = isset( $args['options'] ) && is_array( $args['options'] ) ? $args['options'] : array();
|
457 |
+
|
458 |
+
$args['options'] = 'group' == $args['type'] ? wp_parse_args( $args['options'], array(
|
459 |
+
'add_button' => __( 'Add Group', 'cmb' ),
|
460 |
+
'remove_button' => __( 'Remove Group', 'cmb' ),
|
461 |
+
) ) : $args['options'];
|
462 |
+
|
463 |
+
$args['_id'] = $args['id'];
|
464 |
+
$args['_name'] = $args['id'];
|
465 |
+
|
466 |
+
if ( $this->group ) {
|
467 |
+
$args['id'] = $this->group->args( 'id' ) .'_'. $this->group->args( 'count' ) .'_'. $args['id'];
|
468 |
+
$args['_name'] = $this->group->args( 'id' ) .'['. $this->group->args( 'count' ) .']['. $args['_name'] .']';
|
469 |
+
}
|
470 |
+
|
471 |
+
if ( 'wysiwyg' == $args['type'] ) {
|
472 |
+
$args['id'] = strtolower( str_ireplace( '-', '_', $args['id'] ) );
|
473 |
+
$args['options']['textarea_name'] = $args['_name'];
|
474 |
+
}
|
475 |
+
|
476 |
+
$option_types = array( 'taxonomy_select', 'taxonomy_radio', 'taxonomy_radio_inline' );
|
477 |
+
if ( in_array( $args['type'], $option_types, true ) ) {
|
478 |
+
|
479 |
+
// @todo implemention
|
480 |
+
$args['show_option_all'] = isset( $args['show_option_all'] ) && ! $args['show_option_all'] ? false : true;
|
481 |
+
$args['show_option_none'] = isset( $args['show_option_none'] ) && ! $args['show_option_none'] ? false : true;
|
482 |
+
|
483 |
+
}
|
484 |
+
|
485 |
+
return $args;
|
486 |
+
}
|
487 |
+
|
488 |
+
/**
|
489 |
+
* Updates attributes array values unless they exist from the field config array
|
490 |
+
* @since 1.1.0
|
491 |
+
* @param array $attrs Array of attributes to update
|
492 |
+
*/
|
493 |
+
public function maybe_set_attributes( $attrs = array() ) {
|
494 |
+
return wp_parse_args( $this->args['attributes'], $attrs );
|
495 |
+
}
|
496 |
+
|
497 |
+
}
|
lib/cmb_metaboxes/helpers/cmb_Meta_Box_types.php
ADDED
@@ -0,0 +1,794 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* CMB field types
|
5 |
+
*
|
6 |
+
* @todo test taxonomy methods with non-post objects
|
7 |
+
* @todo test all methods with non-post objects
|
8 |
+
* @todo Date/Time fields should store date format as data attribute for JS
|
9 |
+
*
|
10 |
+
* @since 1.0.0
|
11 |
+
*/
|
12 |
+
class cmb_Meta_Box_types {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* An iterator value for repeatable fields
|
16 |
+
* @var integer
|
17 |
+
* @since 1.0.0
|
18 |
+
*/
|
19 |
+
public $iterator = 0;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Current field
|
23 |
+
* @var array
|
24 |
+
* @since 1.0.0
|
25 |
+
*/
|
26 |
+
public $field;
|
27 |
+
|
28 |
+
public function __construct( $field ) {
|
29 |
+
$this->field = $field;
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Default fallback. Allows rendering fields via "cmb_render_$name" hook
|
34 |
+
* @since 1.0.0
|
35 |
+
* @param string $name Non-existent method name
|
36 |
+
* @param array $arguments All arguments passed to the method
|
37 |
+
*/
|
38 |
+
public function __call( $name, $arguments ) {
|
39 |
+
// When a non-registered field is called, send it through an action.
|
40 |
+
do_action( "cmb_render_$name", $this->field->args(), $this->field->escaped_value(), $this->field->object_id, $this->field->object_type, $this );
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Render a field (and handle repeatable)
|
45 |
+
* @since 1.1.0
|
46 |
+
*/
|
47 |
+
public function render() {
|
48 |
+
if ( $this->field->args( 'repeatable' ) ) {
|
49 |
+
$this->render_repeatable_field();
|
50 |
+
} else {
|
51 |
+
$this->_render();
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Render a field type
|
57 |
+
* @since 1.1.0
|
58 |
+
*/
|
59 |
+
protected function _render() {
|
60 |
+
echo $this->{$this->field->type()}();
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Checks if we can get a post object, and if so, uses `get_the_terms` which utilizes caching
|
65 |
+
* @since 1.0.2
|
66 |
+
* @return mixed Array of terms on success
|
67 |
+
*/
|
68 |
+
public function get_object_terms() {
|
69 |
+
$object_id = $this->field->object_id;
|
70 |
+
$taxonomy = $this->field->args( 'taxonomy' );
|
71 |
+
|
72 |
+
if ( ! $post = get_post( $object_id ) ) {
|
73 |
+
|
74 |
+
$cache_key = 'cmb-cache-'. $taxonomy .'-'. $object_id;
|
75 |
+
|
76 |
+
// Check cache
|
77 |
+
$cached = $test = get_transient( $cache_key );
|
78 |
+
if ( $cached )
|
79 |
+
return $cached;
|
80 |
+
|
81 |
+
$cached = wp_get_object_terms( $object_id, $taxonomy );
|
82 |
+
// Do our own (minimal) caching. Long enough for a page-load.
|
83 |
+
$set = set_transient( $cache_key, $cached, 60 );
|
84 |
+
return $cached;
|
85 |
+
}
|
86 |
+
|
87 |
+
// WP caches internally so it's better to use
|
88 |
+
return get_the_terms( $post, $taxonomy );
|
89 |
+
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Determine a file's extension
|
94 |
+
* @since 1.0.0
|
95 |
+
* @param string $file File url
|
96 |
+
* @return string|false File extension or false
|
97 |
+
*/
|
98 |
+
public function get_file_ext( $file ) {
|
99 |
+
$parsed = @parse_url( $file, PHP_URL_PATH );
|
100 |
+
return $parsed ? strtolower( pathinfo( $parsed, PATHINFO_EXTENSION ) ) : false;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Determines if a file has a valid image extension
|
105 |
+
* @since 1.0.0
|
106 |
+
* @param string $file File url
|
107 |
+
* @return bool Whether file has a valid image extension
|
108 |
+
*/
|
109 |
+
public function is_valid_img_ext( $file ) {
|
110 |
+
$file_ext = $this->get_file_ext( $file );
|
111 |
+
|
112 |
+
$this->valid = empty( $this->valid )
|
113 |
+
? (array) apply_filters( 'cmb_valid_img_types', array( 'jpg', 'jpeg', 'png', 'gif', 'ico', 'icon' ) )
|
114 |
+
: $this->valid;
|
115 |
+
|
116 |
+
return ( $file_ext && in_array( $file_ext, $this->valid ) );
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Handles parsing and filtering attributes while preserving any passed in via field config.
|
121 |
+
* @since 1.1.0
|
122 |
+
* @param array $args Override arguments
|
123 |
+
* @param string $element Element for filter
|
124 |
+
* @param array $defaults Default arguments
|
125 |
+
* @return array Parsed and filtered arguments
|
126 |
+
*/
|
127 |
+
public function parse_args( $args, $element, $defaults ) {
|
128 |
+
return wp_parse_args( apply_filters( "cmb_{$element}_attributes", $this->field->maybe_set_attributes( $args ), $this->field, $this ), $defaults );
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Combines attributes into a string for a form element
|
133 |
+
* @since 1.1.0
|
134 |
+
* @param array $attrs Attributes to concatenate
|
135 |
+
* @param array $attr_exclude Attributes that should NOT be concatenated
|
136 |
+
* @return string String of attributes for form element
|
137 |
+
*/
|
138 |
+
public function concat_attrs( $attrs, $attr_exclude = array() ) {
|
139 |
+
$attributes = '';
|
140 |
+
foreach ( $attrs as $attr => $val ) {
|
141 |
+
if ( ! in_array( $attr, (array) $attr_exclude, true ) )
|
142 |
+
$attributes .= sprintf( ' %s="%s"', $attr, $val );
|
143 |
+
}
|
144 |
+
return $attributes;
|
145 |
+
}
|
146 |
+
|
147 |
+
/**
|
148 |
+
* Generates html for an option element
|
149 |
+
* @since 1.1.0
|
150 |
+
* @param string $opt_label Option label
|
151 |
+
* @param string $opt_value Option value
|
152 |
+
* @param mixed $selected Selected attribute if option is selected
|
153 |
+
* @return string Generated option element html
|
154 |
+
*/
|
155 |
+
public function option( $opt_label, $opt_value, $selected ) {
|
156 |
+
return sprintf( "\t".'<option value="%s" %s>%s</option>', $opt_value, selected( $selected, true, false ), $opt_label )."\n";
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Generates options html
|
161 |
+
* @since 1.1.0
|
162 |
+
* @param array $args Optional arguments
|
163 |
+
* @param string $method Method to generate individual option item
|
164 |
+
* @return string Concatenated html options
|
165 |
+
*/
|
166 |
+
public function concat_options( $args = array(), $method = 'list_input' ) {
|
167 |
+
|
168 |
+
$options = (array) $this->field->args( 'options' );
|
169 |
+
$saved_value = $this->field->escaped_value();
|
170 |
+
$value = $saved_value ? $saved_value : $this->field->args( 'default' );
|
171 |
+
|
172 |
+
$_options = ''; $i = 1;
|
173 |
+
foreach ( $options as $option_key => $option ) {
|
174 |
+
|
175 |
+
// Check for the "old" way
|
176 |
+
$opt_label = is_array( $option ) && array_key_exists( 'name', $option ) ? $option['name'] : $option;
|
177 |
+
$opt_value = is_array( $option ) && array_key_exists( 'value', $option ) ? $option['value'] : $option_key;
|
178 |
+
// Check if this option is the value of the input
|
179 |
+
$is_current = $value == $opt_value;
|
180 |
+
|
181 |
+
if ( ! empty( $args ) ) {
|
182 |
+
// Clone args & modify for just this item
|
183 |
+
$this_args = $args;
|
184 |
+
$this_args['value'] = $opt_value;
|
185 |
+
$this_args['label'] = $opt_label;
|
186 |
+
if ( $is_current )
|
187 |
+
$this_args['checked'] = 'checked';
|
188 |
+
|
189 |
+
$_options .= $this->$method( $this_args, $i );
|
190 |
+
} else {
|
191 |
+
$_options .= $this->option( $opt_label, $opt_value, $is_current );
|
192 |
+
}
|
193 |
+
$i++;
|
194 |
+
}
|
195 |
+
return $_options;
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Generates html for list item with input
|
200 |
+
* @since 1.1.0
|
201 |
+
* @param array $args Override arguments
|
202 |
+
* @param int $i Iterator value
|
203 |
+
* @return string Gnerated list item html
|
204 |
+
*/
|
205 |
+
public function list_input( $args = array(), $i ) {
|
206 |
+
$args = $this->parse_args( $args, 'list_input', array(
|
207 |
+
'type' => 'radio',
|
208 |
+
'class' => 'cmb_option',
|
209 |
+
'name' => $this->_name(),
|
210 |
+
'id' => $this->_id( $i ),
|
211 |
+
'value' => $this->field->escaped_value(),
|
212 |
+
'label' => '',
|
213 |
+
) );
|
214 |
+
|
215 |
+
return sprintf( "\t".'<li><input%s/> <label for="%s">%s</label></li>'."\n", $this->concat_attrs( $args, 'label' ), $args['id'], $args['label'] );
|
216 |
+
}
|
217 |
+
|
218 |
+
/**
|
219 |
+
* Generates html for list item with checkbox input
|
220 |
+
* @since 1.1.0
|
221 |
+
* @param array $args Override arguments
|
222 |
+
* @param int $i Iterator value
|
223 |
+
* @return string Gnerated list item html
|
224 |
+
*/
|
225 |
+
public function list_input_checkbox( $args, $i ) {
|
226 |
+
unset( $args['selected'] );
|
227 |
+
$saved_value = $this->field->escaped_value();
|
228 |
+
if ( is_array( $saved_value ) && in_array( $args['value'], $saved_value ) ) {
|
229 |
+
$args['checked'] = 'checked';
|
230 |
+
}
|
231 |
+
return $this->list_input( $args, $i );
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Generates repeatable field table markup
|
236 |
+
* @since 1.0.0
|
237 |
+
*/
|
238 |
+
public function render_repeatable_field() {
|
239 |
+
$table_id = $this->field->id() .'_repeat';
|
240 |
+
|
241 |
+
$this->_desc( true, true );
|
242 |
+
?>
|
243 |
+
|
244 |
+
<table id="<?php echo $table_id; ?>" class="cmb-repeat-table">
|
245 |
+
<tbody>
|
246 |
+
<?php $this->repeatable_rows(); ?>
|
247 |
+
</tbody>
|
248 |
+
</table>
|
249 |
+
<p class="add-row">
|
250 |
+
<a data-selector="<?php echo $table_id; ?>" class="add-row-button button" href="#"><?php _e( 'Add Row', 'cmb' ); ?></a>
|
251 |
+
</p>
|
252 |
+
|
253 |
+
<?php
|
254 |
+
// reset iterator
|
255 |
+
$this->iterator = 0;
|
256 |
+
}
|
257 |
+
|
258 |
+
/**
|
259 |
+
* Generates repeatable field rows
|
260 |
+
* @since 1.1.0
|
261 |
+
*/
|
262 |
+
public function repeatable_rows() {
|
263 |
+
$meta_value = $this->field->escaped_value();
|
264 |
+
// check for default content
|
265 |
+
$default = $this->field->args( 'default' );
|
266 |
+
|
267 |
+
// check for saved data
|
268 |
+
if ( ! empty( $meta_value ) ) {
|
269 |
+
$meta_value = is_array( $meta_value ) ? array_filter( $meta_value ) : $meta_value;
|
270 |
+
$meta_value = ! empty( $meta_value ) ? $meta_value : $default;
|
271 |
+
} else {
|
272 |
+
$meta_value = $default;
|
273 |
+
}
|
274 |
+
|
275 |
+
// Loop value array and add a row
|
276 |
+
if ( ! empty( $meta_value ) ) {
|
277 |
+
foreach ( (array) $meta_value as $val ) {
|
278 |
+
$this->field->escaped_value = $val;
|
279 |
+
$this->repeat_row();
|
280 |
+
$this->iterator++;
|
281 |
+
}
|
282 |
+
} else {
|
283 |
+
// Otherwise add one row
|
284 |
+
$this->repeat_row();
|
285 |
+
}
|
286 |
+
|
287 |
+
// Then add an empty row
|
288 |
+
$this->field->escaped_value = '';
|
289 |
+
$this->iterator = $this->iterator ? $this->iterator : 1;
|
290 |
+
$this->repeat_row( 'empty-row' );
|
291 |
+
}
|
292 |
+
|
293 |
+
/**
|
294 |
+
* Generates a repeatable row's markup
|
295 |
+
* @since 1.1.0
|
296 |
+
* @param string $class Repeatable table row's class
|
297 |
+
*/
|
298 |
+
protected function repeat_row( $class = 'repeat-row' ) {
|
299 |
+
?>
|
300 |
+
|
301 |
+
<tr class="<?php echo $class; ?>">
|
302 |
+
<td>
|
303 |
+
<?php $this->_render(); ?>
|
304 |
+
</td>
|
305 |
+
<td class="remove-row">
|
306 |
+
<a class="button remove-row-button" href="#"><?php _e( 'Remove', 'cmb' ); ?></a>
|
307 |
+
</td>
|
308 |
+
</tr>
|
309 |
+
|
310 |
+
<?php
|
311 |
+
}
|
312 |
+
|
313 |
+
/**
|
314 |
+
* Generates description markup
|
315 |
+
* @since 1.0.0
|
316 |
+
* @param boolean $paragraph Paragraph tag or span
|
317 |
+
* @param boolean $echo Whether to echo description or only return it
|
318 |
+
* @return string Field's description markup
|
319 |
+
*/
|
320 |
+
public function _desc( $paragraph = false, $echo = false ) {
|
321 |
+
// Prevent description from printing multiple times for repeatable fields
|
322 |
+
if ( $this->field->args( 'repeatable' ) || $this->iterator > 0 ) {
|
323 |
+
return '';
|
324 |
+
}
|
325 |
+
$tag = $paragraph ? 'p' : 'span';
|
326 |
+
$desc = "\n<$tag class=\"cmb_metabox_description\">{$this->field->args( 'description' )}</$tag>\n";
|
327 |
+
if ( $echo )
|
328 |
+
echo $desc;
|
329 |
+
return $desc;
|
330 |
+
}
|
331 |
+
|
332 |
+
/**
|
333 |
+
* Generate field name attribute
|
334 |
+
* @since 1.1.0
|
335 |
+
* @param string $suffix For multi-part fields
|
336 |
+
* @return string Name attribute
|
337 |
+
*/
|
338 |
+
public function _name( $suffix = '' ) {
|
339 |
+
return $this->field->args( '_name' ) . ( $this->field->args( 'repeatable' ) ? '['. $this->iterator .']' : '' ) . $suffix;
|
340 |
+
}
|
341 |
+
|
342 |
+
/**
|
343 |
+
* Generate field id attribute
|
344 |
+
* @since 1.1.0
|
345 |
+
* @param string $suffix For multi-part fields
|
346 |
+
* @return string Id attribute
|
347 |
+
*/
|
348 |
+
public function _id( $suffix = '' ) {
|
349 |
+
return $this->field->id() . $suffix . ( $this->field->args( 'repeatable' ) ? '_'. $this->iterator .'" data-iterator="'. $this->iterator : '' );
|
350 |
+
}
|
351 |
+
|
352 |
+
/**
|
353 |
+
* Handles outputting an 'input' element
|
354 |
+
* @since 1.1.0
|
355 |
+
* @param array $args Override arguments
|
356 |
+
* @return string Form input element
|
357 |
+
*/
|
358 |
+
public function input( $args = array() ) {
|
359 |
+
$args = $this->parse_args( $args, 'input', array(
|
360 |
+
'type' => 'text',
|
361 |
+
'class' => 'regular-text',
|
362 |
+
'name' => $this->_name(),
|
363 |
+
'id' => $this->_id(),
|
364 |
+
'value' => $this->field->escaped_value(),
|
365 |
+
'desc' => $this->_desc( true ),
|
366 |
+
) );
|
367 |
+
|
368 |
+
return sprintf( '<input%s/>%s', $this->concat_attrs( $args, 'desc' ), $args['desc'] );
|
369 |
+
}
|
370 |
+
|
371 |
+
/**
|
372 |
+
* Handles outputting an 'textarea' element
|
373 |
+
* @since 1.1.0
|
374 |
+
* @param array $args Override arguments
|
375 |
+
* @return string Form textarea element
|
376 |
+
*/
|
377 |
+
public function textarea( $args = array() ) {
|
378 |
+
$args = $this->parse_args( $args, 'textarea', array(
|
379 |
+
'class' => 'cmb_textarea',
|
380 |
+
'name' => $this->_name(),
|
381 |
+
'id' => $this->_id(),
|
382 |
+
'cols' => 60,
|
383 |
+
'rows' => 10,
|
384 |
+
'value' => $this->field->escaped_value( 'esc_textarea' ),
|
385 |
+
'desc' => $this->_desc( true ),
|
386 |
+
) );
|
387 |
+
return sprintf( '<textarea%s>%s</textarea>%s', $this->concat_attrs( $args, array( 'desc', 'value' ) ), $args['value'], $args['desc'] );
|
388 |
+
}
|
389 |
+
|
390 |
+
/**
|
391 |
+
* Begin Field Types
|
392 |
+
*/
|
393 |
+
|
394 |
+
public function text() {
|
395 |
+
return $this->input();
|
396 |
+
}
|
397 |
+
|
398 |
+
public function text_small() {
|
399 |
+
return $this->input( array( 'class' => 'cmb_text_small', 'desc' => $this->_desc() ) );
|
400 |
+
}
|
401 |
+
|
402 |
+
public function text_medium() {
|
403 |
+
return $this->input( array( 'class' => 'cmb_text_medium', 'desc' => $this->_desc() ) );
|
404 |
+
}
|
405 |
+
|
406 |
+
public function text_email() {
|
407 |
+
return $this->input( array( 'class' => 'cmb_text_email cmb_text_medium', 'type' => 'email' ) );
|
408 |
+
}
|
409 |
+
|
410 |
+
public function text_url() {
|
411 |
+
return $this->input( array( 'class' => 'cmb_text_url cmb_text_medium regular-text', 'value' => $this->field->escaped_value( 'esc_url' ) ) );
|
412 |
+
}
|
413 |
+
|
414 |
+
public function text_date() {
|
415 |
+
return $this->input( array( 'class' => 'cmb_text_small cmb_datepicker', 'desc' => $this->_desc() ) );
|
416 |
+
}
|
417 |
+
|
418 |
+
public function text_time() {
|
419 |
+
return $this->input( array( 'class' => 'cmb_timepicker text_time', 'desc' => $this->_desc() ) );
|
420 |
+
}
|
421 |
+
|
422 |
+
public function text_money() {
|
423 |
+
return ( ! $this->field->args( 'before' ) ? '$ ' : ' ' ) . $this->input( array( 'class' => 'cmb_text_money', 'desc' => $this->_desc() ) );
|
424 |
+
}
|
425 |
+
|
426 |
+
public function textarea_small() {
|
427 |
+
return $this->textarea( array( 'class' => 'cmb_textarea_small', 'rows' => 4 ) );
|
428 |
+
}
|
429 |
+
|
430 |
+
public function textarea_code() {
|
431 |
+
return sprintf( '<pre>%s</pre>', $this->textarea( array( 'class' => 'cmb_textarea_code' ) ) );
|
432 |
+
}
|
433 |
+
|
434 |
+
public function wysiwyg( $args = array() ) {
|
435 |
+
extract( $this->parse_args( $args, 'input', array(
|
436 |
+
'id' => $this->_id(),
|
437 |
+
'value' => $this->field->escaped_value( 'stripslashes' ),
|
438 |
+
'desc' => $this->_desc( true ),
|
439 |
+
'options' => $this->field->args( 'options' ),
|
440 |
+
) ) );
|
441 |
+
|
442 |
+
wp_editor( $value, $id, $options );
|
443 |
+
echo $desc;
|
444 |
+
}
|
445 |
+
|
446 |
+
public function text_date_timestamp() {
|
447 |
+
$meta_value = $this->field->escaped_value();
|
448 |
+
$value = ! empty( $meta_value ) ? date( $this->field->args( 'date_format' ), $meta_value ) : '';
|
449 |
+
return $this->input( array( 'class' => 'cmb_text_small cmb_datepicker', 'value' => $value ) );
|
450 |
+
}
|
451 |
+
|
452 |
+
public function text_datetime_timestamp( $meta_value = '' ) {
|
453 |
+
$desc = '';
|
454 |
+
if ( ! $meta_value ) {
|
455 |
+
$meta_value = $this->field->escaped_value();
|
456 |
+
// This will be used if there is a select_timezone set for this field
|
457 |
+
$tz_offset = $this->field->field_timezone_offset();
|
458 |
+
if ( ! empty( $tz_offset ) ) {
|
459 |
+
$meta_value -= $tz_offset;
|
460 |
+
}
|
461 |
+
$desc = $this->_desc();
|
462 |
+
}
|
463 |
+
|
464 |
+
$inputs = array(
|
465 |
+
$this->input( array(
|
466 |
+
'class' => 'cmb_text_small cmb_datepicker',
|
467 |
+
'name' => $this->_name( '[date]' ),
|
468 |
+
'id' => $this->_id( '_date' ),
|
469 |
+
'value' => ! empty( $meta_value ) ? date( $this->field->args( 'date_format' ), $meta_value ) : '',
|
470 |
+
'desc' => '',
|
471 |
+
) ),
|
472 |
+
$this->input( array(
|
473 |
+
'class' => 'cmb_timepicker text_time',
|
474 |
+
'name' => $this->_name( '[time]' ),
|
475 |
+
'id' => $this->_id( '_time' ),
|
476 |
+
'value' => ! empty( $meta_value ) ? date( $this->field->args( 'time_format' ), $meta_value ) : '',
|
477 |
+
'desc' => $desc,
|
478 |
+
) )
|
479 |
+
);
|
480 |
+
|
481 |
+
return implode( "\n", $inputs );
|
482 |
+
}
|
483 |
+
|
484 |
+
public function text_datetime_timestamp_timezone() {
|
485 |
+
$meta_value = $this->field->escaped_value();
|
486 |
+
$datetime = unserialize( $meta_value );
|
487 |
+
$meta_value = $tzstring = false;
|
488 |
+
|
489 |
+
if ( $datetime && $datetime instanceof DateTime ) {
|
490 |
+
$tz = $datetime->getTimezone();
|
491 |
+
$tzstring = $tz->getName();
|
492 |
+
$meta_value = $datetime->getTimestamp() + $tz->getOffset( new DateTime( 'NOW' ) );
|
493 |
+
}
|
494 |
+
|
495 |
+
$inputs = $this->text_datetime_timestamp( $meta_value );
|
496 |
+
$inputs .= '<select name="'. $this->_name( '[timezone]' ) .'" id="'. $this->_id( '_timezone' ) .'">';
|
497 |
+
$inputs .= wp_timezone_choice( $tzstring );
|
498 |
+
$inputs .= '</select>'. $this->_desc();
|
499 |
+
|
500 |
+
return $inputs;
|
501 |
+
}
|
502 |
+
|
503 |
+
public function select_timezone() {
|
504 |
+
$this->field->args['default'] = $this->field->args( 'default' )
|
505 |
+
? $this->field->args( 'default' )
|
506 |
+
: cmb_Meta_Box::timezone_string();
|
507 |
+
|
508 |
+
$meta_value = $this->field->escaped_value();
|
509 |
+
|
510 |
+
return '<select name="'. $this->_name() .'" id="'. $this->_id() .'">'. wp_timezone_choice( $meta_value ) .'</select>';
|
511 |
+
}
|
512 |
+
|
513 |
+
public function colorpicker() {
|
514 |
+
$meta_value = $this->field->escaped_value();
|
515 |
+
$hex_color = '(([a-fA-F0-9]){3}){1,2}$';
|
516 |
+
if ( preg_match( '/^' . $hex_color . '/i', $meta_value ) ) // Value is just 123abc, so prepend #.
|
517 |
+
$meta_value = '#' . $meta_value;
|
518 |
+
elseif ( ! preg_match( '/^#' . $hex_color . '/i', $meta_value ) ) // Value doesn't match #123abc, so sanitize to just #.
|
519 |
+
$meta_value = "#";
|
520 |
+
|
521 |
+
return $this->input( array( 'class' => 'cmb_colorpicker cmb_text_small', 'value' => $meta_value ) );
|
522 |
+
}
|
523 |
+
|
524 |
+
public function title() {
|
525 |
+
extract( $this->parse_args( array(), 'title', array(
|
526 |
+
'tag' => $this->field->object_type == 'post' ? 'h5' : 'h3',
|
527 |
+
'class' => 'cmb_metabox_title',
|
528 |
+
'name' => $this->field->args( 'name' ),
|
529 |
+
'desc' => $this->_desc( true ),
|
530 |
+
) ) );
|
531 |
+
|
532 |
+
return sprintf( '<%1$s class="%2$s">%3$s</%1$s>%4$s', $tag, $class, $name, $desc );
|
533 |
+
}
|
534 |
+
|
535 |
+
public function select( $args = array() ) {
|
536 |
+
$args = $this->parse_args( $args, 'select', array(
|
537 |
+
'class' => 'cmb_select',
|
538 |
+
'name' => $this->_name(),
|
539 |
+
'id' => $this->_id(),
|
540 |
+
'desc' => $this->_desc( true ),
|
541 |
+
'options' => $this->concat_options(),
|
542 |
+
) );
|
543 |
+
|
544 |
+
$attrs = $this->concat_attrs( $args, array( 'desc', 'options' ) );
|
545 |
+
return sprintf( '<select%s>%s</select>%s', $attrs, $args['options'], $args['desc'] );
|
546 |
+
}
|
547 |
+
|
548 |
+
public function taxonomy_select() {
|
549 |
+
|
550 |
+
$names = $this->get_object_terms();
|
551 |
+
$saved_term = is_wp_error( $names ) || empty( $names ) ? $this->field->args( 'default' ) : $names[0]->slug;
|
552 |
+
$terms = get_terms( $this->field->args( 'taxonomy' ), 'hide_empty=0' );
|
553 |
+
$options = '';
|
554 |
+
|
555 |
+
foreach ( $terms as $term ) {
|
556 |
+
$selected = $saved_term == $term->slug;
|
557 |
+
$options .= $this->option( $term->name, $term->slug, $selected );
|
558 |
+
}
|
559 |
+
|
560 |
+
return $this->select( array( 'options' => $options ) );
|
561 |
+
}
|
562 |
+
|
563 |
+
public function radio( $args = array(), $type = 'radio' ) {
|
564 |
+
extract( $this->parse_args( $args, $type, array(
|
565 |
+
'class' => 'cmb_radio_list cmb_list',
|
566 |
+
'options' => $this->concat_options( array( 'label' => 'test' ) ),
|
567 |
+
'desc' => $this->_desc( true ),
|
568 |
+
) ) );
|
569 |
+
|
570 |
+
return sprintf( '<ul class="%s">%s</ul>%s', $class, $options, $desc );
|
571 |
+
}
|
572 |
+
|
573 |
+
public function radio_inline() {
|
574 |
+
return $this->radio( array(), 'radio_inline' );
|
575 |
+
}
|
576 |
+
|
577 |
+
public function multicheck( $type = 'checkbox' ) {
|
578 |
+
return $this->radio( array( 'class' => 'cmb_checkbox_list cmb_list', 'options' => $this->concat_options( array( 'type' => 'checkbox', 'name' => $this->_name() .'[]' ), 'list_input_checkbox' ) ), $type );
|
579 |
+
}
|
580 |
+
|
581 |
+
public function multicheck_inline() {
|
582 |
+
$this->multicheck( 'multicheck_inline' );
|
583 |
+
}
|
584 |
+
|
585 |
+
public function checkbox() {
|
586 |
+
$meta_value = $this->field->escaped_value();
|
587 |
+
$args = array( 'type' => 'checkbox', 'class' => 'cmb_option cmb_list', 'value' => 'on', 'desc' => '' );
|
588 |
+
if ( ! empty( $meta_value ) ) {
|
589 |
+
$args['checked'] = 'checked';
|
590 |
+
}
|
591 |
+
return sprintf( '%s <label for="%s">%s</label>', $this->input( $args ), $this->_id(), $this->_desc() );
|
592 |
+
}
|
593 |
+
|
594 |
+
public function taxonomy_radio() {
|
595 |
+
$names = $this->get_object_terms();
|
596 |
+
$saved_term = is_wp_error( $names ) || empty( $names ) ? $this->field->args( 'default' ) : $names[0]->slug;
|
597 |
+
$terms = get_terms( $this->field->args( 'taxonomy' ), 'hide_empty=0' );
|
598 |
+
$options = ''; $i = 1;
|
599 |
+
|
600 |
+
if ( ! $terms ) {
|
601 |
+
$options .= '<li><label>'. __( 'No terms', 'cmb' ) .'</label></li>';
|
602 |
+
} else {
|
603 |
+
foreach ( $terms as $term ) {
|
604 |
+
$args = array(
|
605 |
+
'value' => $term->slug,
|
606 |
+
'label' => $term->name,
|
607 |
+
);
|
608 |
+
|
609 |
+
if ( $saved_term == $term->slug ) {
|
610 |
+
$args['checked'] = 'checked';
|
611 |
+
}
|
612 |
+
$options .= $this->list_input( $args, $i );
|
613 |
+
$i++;
|
614 |
+
}
|
615 |
+
}
|
616 |
+
|
617 |
+
return $this->radio( array( 'options' => $options ), 'taxonomy_radio' );
|
618 |
+
}
|
619 |
+
|
620 |
+
public function taxonomy_radio_inline() {
|
621 |
+
$this->taxonomy_radio();
|
622 |
+
}
|
623 |
+
|
624 |
+
public function taxonomy_multicheck() {
|
625 |
+
|
626 |
+
$names = $this->get_object_terms();
|
627 |
+
$saved_terms = is_wp_error( $names ) || empty( $names )
|
628 |
+
? $this->field->args( 'default' )
|
629 |
+
: wp_list_pluck( $names, 'slug' );
|
630 |
+
$terms = get_terms( $this->field->args( 'taxonomy' ), 'hide_empty=0' );
|
631 |
+
$name = $this->_name() .'[]';
|
632 |
+
$options = ''; $i = 1;
|
633 |
+
|
634 |
+
if ( ! $terms ) {
|
635 |
+
$options .= '<li><label>'. __( 'No terms', 'cmb' ) .'</label></li>';
|
636 |
+
} else {
|
637 |
+
|
638 |
+
foreach ( $terms as $term ) {
|
639 |
+
$args = array(
|
640 |
+
'value' => $term->slug,
|
641 |
+
'label' => $term->name,
|
642 |
+
'type' => 'checkbox',
|
643 |
+
'name' => $name,
|
644 |
+
);
|
645 |
+
|
646 |
+
if ( is_array( $saved_terms ) && in_array( $term->slug, $saved_terms ) ) {
|
647 |
+
$args['checked'] = 'checked';
|
648 |
+
}
|
649 |
+
$options .= $this->list_input( $args, $i );
|
650 |
+
$i++;
|
651 |
+
}
|
652 |
+
}
|
653 |
+
|
654 |
+
return $this->radio( array( 'class' => 'cmb_checkbox_list cmb_list', 'options' => $options ), 'taxonomy_multicheck' );
|
655 |
+
}
|
656 |
+
|
657 |
+
public function taxonomy_multicheck_inline() {
|
658 |
+
$this->taxonomy_multicheck();
|
659 |
+
}
|
660 |
+
|
661 |
+
public function file_list() {
|
662 |
+
$meta_value = $this->field->escaped_value();
|
663 |
+
|
664 |
+
$name = $this->_name();
|
665 |
+
|
666 |
+
echo $this->input( array(
|
667 |
+
'type' => 'hidden',
|
668 |
+
'class' => 'cmb_upload_file cmb_upload_list',
|
669 |
+
'size' => 45, 'desc' => '', 'value' => '',
|
670 |
+
) ),
|
671 |
+
$this->input( array(
|
672 |
+
'type' => 'button',
|
673 |
+
'class' => 'cmb_upload_button button cmb_upload_list',
|
674 |
+
'value' => __( 'Add or Upload File', 'cmb' ),
|
675 |
+
'name' => '', 'id' => '',
|
676 |
+
) );
|
677 |
+
|
678 |
+
echo '<ul id="', $this->_id( '_status' ) ,'" class="cmb_media_status attach_list">';
|
679 |
+
|
680 |
+
if ( $meta_value && is_array( $meta_value ) ) {
|
681 |
+
|
682 |
+
foreach ( $meta_value as $id => $fullurl ) {
|
683 |
+
$id_input = $this->input( array(
|
684 |
+
'type' => 'hidden',
|
685 |
+
'value' => $fullurl,
|
686 |
+
'name' => $name .'['. $id .']',
|
687 |
+
'id' => 'filelist-'. $id,
|
688 |
+
'desc' => '', 'class' => '',
|
689 |
+
) );
|
690 |
+
|
691 |
+
if ( $this->is_valid_img_ext( $fullurl ) ) {
|
692 |
+
echo
|
693 |
+
'<li class="img_status">',
|
694 |
+
wp_get_attachment_image( $id, $this->field->args( 'preview_size' ) ),
|
695 |
+
'<p class="cmb_remove_wrapper"><a href="#" class="cmb_remove_file_button">'. __( 'Remove Image', 'cmb' ) .'</a></p>
|
696 |
+
'. $id_input .'
|
697 |
+
</li>';
|
698 |
+
|
699 |
+
} else {
|
700 |
+
$parts = explode( '/', $fullurl );
|
701 |
+
for ( $i = 0; $i < count( $parts ); ++$i ) {
|
702 |
+
$title = $parts[$i];
|
703 |
+
}
|
704 |
+
echo
|
705 |
+
'<li>',
|
706 |
+
__( 'File:', 'cmb' ), ' <strong>', $title, '</strong> (<a href="', $fullurl, '" target="_blank" rel="external">'. __( 'Download', 'cmb' ) .'</a> / <a href="#" class="cmb_remove_file_button">'. __( 'Remove', 'cmb' ) .'</a>)
|
707 |
+
'. $id_input .'
|
708 |
+
</li>';
|
709 |
+
}
|
710 |
+
}
|
711 |
+
}
|
712 |
+
|
713 |
+
echo '</ul>';
|
714 |
+
}
|
715 |
+
|
716 |
+
public function file() {
|
717 |
+
$meta_value = $this->field->escaped_value();
|
718 |
+
$allow = $this->field->args( 'allow' );
|
719 |
+
$input_type = ( 'url' == $allow || ( is_array( $allow ) && in_array( 'url', $allow ) ) )
|
720 |
+
? 'text' : 'hidden';
|
721 |
+
|
722 |
+
echo $this->input( array(
|
723 |
+
'type' => $input_type,
|
724 |
+
'class' => 'cmb_upload_file',
|
725 |
+
'size' => 45,
|
726 |
+
'desc' => '',
|
727 |
+
) ),
|
728 |
+
'<input class="cmb_upload_button button" type="button" value="'. __( 'Add or Upload File', 'cmb' ) .'" />',
|
729 |
+
$this->_desc( true );
|
730 |
+
|
731 |
+
$cached_id = $this->_id();
|
732 |
+
// Reset field args for attachment ID
|
733 |
+
$args = $this->field->args();
|
734 |
+
$args['id'] = $args['_id'] . '_id';
|
735 |
+
unset( $args['_id'], $args['_name'] );
|
736 |
+
|
737 |
+
// And get new field object
|
738 |
+
$this->field = new cmb_Meta_Box_field( $args, $this->field->group );
|
739 |
+
|
740 |
+
// Get ID value
|
741 |
+
$_id_value = $this->field->escaped_value( 'absint' );
|
742 |
+
|
743 |
+
// If there is no ID saved yet, try to get it from the url
|
744 |
+
if ( $meta_value && ! $_id_value ) {
|
745 |
+
$_id_value = cmb_Meta_Box::image_id_from_url( esc_url_raw( $meta_value ) );
|
746 |
+
}
|
747 |
+
|
748 |
+
echo $this->input( array(
|
749 |
+
'type' => 'hidden',
|
750 |
+
'class' => 'cmb_upload_file_id',
|
751 |
+
'value' => $_id_value,
|
752 |
+
'desc' => '',
|
753 |
+
) ),
|
754 |
+
'<div id="', $this->_id( '_status' ) ,'" class="cmb_media_status">';
|
755 |
+
if ( ! empty( $meta_value ) ) {
|
756 |
+
|
757 |
+
if ( $this->is_valid_img_ext( $meta_value ) ) {
|
758 |
+
echo '<div class="img_status">';
|
759 |
+
echo '<img style="max-width: 350px; width: 100%; height: auto;" src="', $meta_value, '" alt="" />';
|
760 |
+
echo '<p class="cmb_remove_wrapper"><a href="#" class="cmb_remove_file_button" rel="', $cached_id, '">'. __( 'Remove Image', 'cmb' ) .'</a></p>';
|
761 |
+
echo '</div>';
|
762 |
+
} else {
|
763 |
+
// $file_ext = $this->get_file_ext( $meta_value );
|
764 |
+
$parts = explode( '/', $meta_value );
|
765 |
+
for ( $i = 0; $i < count( $parts ); ++$i ) {
|
766 |
+
$title = $parts[$i];
|
767 |
+
}
|
768 |
+
echo __( 'File:', 'cmb' ), ' <strong>', $title, '</strong> (<a href="', $meta_value, '" target="_blank" rel="external">'. __( 'Download', 'cmb' ) .'</a> / <a href="#" class="cmb_remove_file_button" rel="', $cached_id, '">'. __( 'Remove', 'cmb' ) .'</a>)';
|
769 |
+
}
|
770 |
+
}
|
771 |
+
echo '</div>';
|
772 |
+
}
|
773 |
+
|
774 |
+
public function oembed() {
|
775 |
+
echo $this->input( array(
|
776 |
+
'class' => 'cmb_oembed regular-text',
|
777 |
+
'data-objectid' => $this->field->object_id,
|
778 |
+
'data-objecttype' => $this->field->object_type
|
779 |
+
) ),
|
780 |
+
'<p class="cmb-spinner spinner" style="display:none;"><img src="'. admin_url( '/images/wpspin_light.gif' ) .'" alt="spinner"/></p>',
|
781 |
+
'<div id="',$this->_id( '_status' ) ,'" class="cmb_media_status ui-helper-clearfix embed_wrap">';
|
782 |
+
|
783 |
+
if ( $meta_value = $this->field->escaped_value() ) {
|
784 |
+
echo cmb_Meta_Box_ajax::get_oembed( $meta_value, $this->field->object_id, array(
|
785 |
+
'object_type' => $this->field->object_type,
|
786 |
+
'oembed_args' => array( 'width' => '640' ),
|
787 |
+
'field_id' => $this->_id(),
|
788 |
+
) );
|
789 |
+
}
|
790 |
+
|
791 |
+
echo '</div>';
|
792 |
+
}
|
793 |
+
|
794 |
+
}
|
lib/cmb_metaboxes/images/ico-delete.png
ADDED
Binary file
|
lib/cmb_metaboxes/images/ui-bg_flat_0_aaaaaa_40x100.png
ADDED
Binary file
|
lib/cmb_metaboxes/images/ui-bg_flat_75_ffffff_40x100.png
ADDED
Binary file
|
lib/cmb_metaboxes/images/ui-bg_glass_55_fbf9ee_1x400.png
ADDED
Binary file
|
lib/cmb_metaboxes/images/ui-bg_glass_65_ffffff_1x400.png
ADDED
Binary file
|
lib/cmb_metaboxes/images/ui-bg_glass_75_dadada_1x400.png
ADDED
Binary file
|
lib/cmb_metaboxes/images/ui-bg_glass_75_e6e6e6_1x400.png
ADDED
Binary file
|
lib/cmb_metaboxes/images/ui-bg_glass_95_fef1ec_1x400.png
ADDED
Binary file
|
lib/cmb_metaboxes/images/ui-bg_highlight-soft_75_cccccc_1x100.png
ADDED
Binary file
|
lib/cmb_metaboxes/images/ui-icons_222222_256x240.png
ADDED
Binary file
|
lib/cmb_metaboxes/images/ui-icons_2e83ff_256x240.png
ADDED
Binary file
|
lib/cmb_metaboxes/images/ui-icons_454545_256x240.png
ADDED
Binary file
|
lib/cmb_metaboxes/images/ui-icons_888888_256x240.png
ADDED
Binary file
|
lib/cmb_metaboxes/images/ui-icons_cd0a0a_256x240.png
ADDED
Binary file
|
lib/cmb_metaboxes/init.php
ADDED
@@ -0,0 +1,1185 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Script Name: Custom Metaboxes and Fields
|
4 |
+
Contributors: WebDevStudios (@webdevstudios / webdevstudios.com)
|
5 |
+
Justin Sternberg (@jtsternberg / dsgnwrks.pro)
|
6 |
+
Jared Atchison (@jaredatch / jaredatchison.com)
|
7 |
+
Bill Erickson (@billerickson / billerickson.net)
|
8 |
+
Andrew Norcross (@norcross / andrewnorcross.com)
|
9 |
+
Description: This will create metaboxes with custom fields that will blow your mind.
|
10 |
+
Version: 1.2.0
|
11 |
+
*/
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Released under the GPL license
|
15 |
+
* http://www.opensource.org/licenses/gpl-license.php
|
16 |
+
*
|
17 |
+
* This is an add-on for WordPress
|
18 |
+
* http://wordpress.org/
|
19 |
+
*
|
20 |
+
* **********************************************************************
|
21 |
+
* This program is free software; you can redistribute it and/or modify
|
22 |
+
* it under the terms of the GNU General Public License as published by
|
23 |
+
* the Free Software Foundation; either version 2 of the License, or
|
24 |
+
* (at your option) any later version.
|
25 |
+
*
|
26 |
+
* This program is distributed in the hope that it will be useful,
|
27 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
28 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
29 |
+
* GNU General Public License for more details.
|
30 |
+
* **********************************************************************
|
31 |
+
*/
|
32 |
+
|
33 |
+
/************************************************************************
|
34 |
+
You should not edit the code below or things might explode!
|
35 |
+
*************************************************************************/
|
36 |
+
|
37 |
+
// Autoload helper classes
|
38 |
+
spl_autoload_register('cmb_Meta_Box::autoload_helpers');
|
39 |
+
|
40 |
+
$meta_boxes = array();
|
41 |
+
$meta_boxes = apply_filters( 'cmb_meta_boxes', $meta_boxes );
|
42 |
+
foreach ( $meta_boxes as $meta_box ) {
|
43 |
+
$my_box = new cmb_Meta_Box( $meta_box );
|
44 |
+
}
|
45 |
+
|
46 |
+
define( 'CMB_META_BOX_URL', cmb_Meta_Box::get_meta_box_url() );
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Create meta boxes
|
50 |
+
*/
|
51 |
+
class cmb_Meta_Box {
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Current version number
|
55 |
+
* @var string
|
56 |
+
* @since 1.0.0
|
57 |
+
*/
|
58 |
+
const CMB_VERSION = '1.2.0';
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Metabox Config array
|
62 |
+
* @var array
|
63 |
+
* @since 0.9.0
|
64 |
+
*/
|
65 |
+
protected $_meta_box;
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Metabox Defaults
|
69 |
+
* @var array
|
70 |
+
* @since 1.0.1
|
71 |
+
*/
|
72 |
+
protected static $mb_defaults = array(
|
73 |
+
'id' => '',
|
74 |
+
'title' => '',
|
75 |
+
'type' => '',
|
76 |
+
'pages' => array(), // Post type
|
77 |
+
'context' => 'normal',
|
78 |
+
'priority' => 'high',
|
79 |
+
'show_names' => true, // Show field names on the left
|
80 |
+
'show_on' => array( 'key' => false, 'value' => false ), // Specific post IDs or page templates to display this metabox
|
81 |
+
'cmb_styles' => true, // Include cmb bundled stylesheet
|
82 |
+
'fields' => array(),
|
83 |
+
);
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Metabox Form ID
|
87 |
+
* @var string
|
88 |
+
* @since 0.9.4
|
89 |
+
*/
|
90 |
+
protected $form_id = 'post';
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Current field config array
|
94 |
+
* @var array
|
95 |
+
* @since 1.0.0
|
96 |
+
*/
|
97 |
+
public static $field = array();
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Object ID for metabox meta retrieving/saving
|
101 |
+
* @var int
|
102 |
+
* @since 1.0.0
|
103 |
+
*/
|
104 |
+
protected static $object_id = 0;
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Type of object being saved. (e.g., post, user, or comment)
|
108 |
+
* @var string
|
109 |
+
* @since 1.0.0
|
110 |
+
*/
|
111 |
+
protected static $object_type = '';
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Whether scripts/styles have been enqueued yet
|
115 |
+
* @var bool
|
116 |
+
* @since 1.0.0
|
117 |
+
*/
|
118 |
+
protected static $is_enqueued = false;
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Whether CMB nonce has been added to the page. (oly add once)
|
122 |
+
* @var bool
|
123 |
+
* @since 1.2.0
|
124 |
+
*/
|
125 |
+
protected static $nonce_added = false;
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Type of object specified by the metabox Config
|
129 |
+
* @var string
|
130 |
+
* @since 1.0.0
|
131 |
+
*/
|
132 |
+
protected static $mb_object_type = 'post';
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Array of all options from manage-options metaboxes
|
136 |
+
* @var array
|
137 |
+
* @since 1.0.0
|
138 |
+
*/
|
139 |
+
protected static $options = array();
|
140 |
+
|
141 |
+
/**
|
142 |
+
* List of fields that are changed/updated on save
|
143 |
+
* @var array
|
144 |
+
* @since 1.1.0
|
145 |
+
*/
|
146 |
+
protected static $updated = array();
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Get started
|
150 |
+
*/
|
151 |
+
function __construct( $meta_box ) {
|
152 |
+
|
153 |
+
$meta_box = self::set_mb_defaults( $meta_box );
|
154 |
+
|
155 |
+
$allow_frontend = apply_filters( 'cmb_allow_frontend', true, $meta_box );
|
156 |
+
|
157 |
+
if ( ! is_admin() && ! $allow_frontend )
|
158 |
+
return;
|
159 |
+
|
160 |
+
$this->_meta_box = $meta_box;
|
161 |
+
|
162 |
+
self::set_mb_type( $meta_box );
|
163 |
+
|
164 |
+
$types = wp_list_pluck( $meta_box['fields'], 'type' );
|
165 |
+
$upload = in_array( 'file', $types ) || in_array( 'file_list', $types );
|
166 |
+
|
167 |
+
global $pagenow;
|
168 |
+
|
169 |
+
$show_filters = 'cmb_Meta_Box_Show_Filters';
|
170 |
+
foreach ( get_class_methods( $show_filters ) as $filter ) {
|
171 |
+
add_filter( 'cmb_show_on', array( $show_filters, $filter ), 10, 2 );
|
172 |
+
}
|
173 |
+
|
174 |
+
// register our scripts and styles for cmb
|
175 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'register_scripts' ), 8 );
|
176 |
+
|
177 |
+
if ( self::get_object_type() == 'post' ) {
|
178 |
+
add_action( 'admin_menu', array( $this, 'add_metaboxes' ) );
|
179 |
+
add_action( 'add_attachment', array( $this, 'save_post' ) );
|
180 |
+
add_action( 'edit_attachment', array( $this, 'save_post' ) );
|
181 |
+
add_action( 'save_post', array( $this, 'save_post' ), 10, 2 );
|
182 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'do_scripts' ) );
|
183 |
+
|
184 |
+
if ( $upload && in_array( $pagenow, array( 'page.php', 'page-new.php', 'post.php', 'post-new.php' ) ) ) {
|
185 |
+
add_action( 'admin_head', array( $this, 'add_post_enctype' ) );
|
186 |
+
}
|
187 |
+
|
188 |
+
}
|
189 |
+
if ( self::get_object_type() == 'user' ) {
|
190 |
+
|
191 |
+
$priority = 10;
|
192 |
+
if ( isset( $meta_box['priority'] ) ) {
|
193 |
+
if ( is_numeric( $meta_box['priority'] ) )
|
194 |
+
$priority = $meta_box['priority'];
|
195 |
+
elseif ( $meta_box['priority'] == 'high' )
|
196 |
+
$priority = 5;
|
197 |
+
elseif ( $meta_box['priority'] == 'low' )
|
198 |
+
$priority = 20;
|
199 |
+
}
|
200 |
+
add_action( 'show_user_profile', array( $this, 'user_metabox' ), $priority );
|
201 |
+
add_action( 'edit_user_profile', array( $this, 'user_metabox' ), $priority );
|
202 |
+
|
203 |
+
add_action( 'personal_options_update', array( $this, 'save_user' ) );
|
204 |
+
add_action( 'edit_user_profile_update', array( $this, 'save_user' ) );
|
205 |
+
if ( $upload && in_array( $pagenow, array( 'profile.php', 'user-edit.php' ) ) ) {
|
206 |
+
$this->form_id = 'your-profile';
|
207 |
+
add_action( 'admin_head', array( $this, 'add_post_enctype' ) );
|
208 |
+
}
|
209 |
+
}
|
210 |
+
|
211 |
+
}
|
212 |
+
|
213 |
+
/**
|
214 |
+
* Autoloads files with classes when needed
|
215 |
+
* @since 1.0.0
|
216 |
+
* @param string $class_name Name of the class being requested
|
217 |
+
*/
|
218 |
+
public static function autoload_helpers( $class_name ) {
|
219 |
+
if ( class_exists( $class_name, false ) )
|
220 |
+
return;
|
221 |
+
|
222 |
+
// for PHP versions < 5.3
|
223 |
+
$dir = dirname( __FILE__ );
|
224 |
+
|
225 |
+
$file = "$dir/helpers/$class_name.php";
|
226 |
+
if ( file_exists( $file ) )
|
227 |
+
@include( $file );
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* Registers scripts and styles for CMB
|
232 |
+
* @since 1.0.0
|
233 |
+
*/
|
234 |
+
public function register_scripts() {
|
235 |
+
|
236 |
+
// Should only be run once
|
237 |
+
if ( self::$is_enqueued )
|
238 |
+
return;
|
239 |
+
|
240 |
+
global $wp_version;
|
241 |
+
// Only use minified files if SCRIPT_DEBUG is off
|
242 |
+
$min = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min';
|
243 |
+
|
244 |
+
// scripts required for cmb
|
245 |
+
$scripts = array( 'jquery', 'jquery-ui-core', 'cmb-datepicker', /*'media-upload', */'cmb-timepicker' );
|
246 |
+
// styles required for cmb
|
247 |
+
$styles = array();
|
248 |
+
|
249 |
+
// if we're 3.5 or later, user wp-color-picker
|
250 |
+
if ( 3.5 <= $wp_version ) {
|
251 |
+
$scripts[] = 'wp-color-picker';
|
252 |
+
$styles[] = 'wp-color-picker';
|
253 |
+
if ( ! is_admin() ) {
|
254 |
+
// we need to register colorpicker on the front-end
|
255 |
+
wp_register_script( 'iris', admin_url( 'js/iris.min.js' ), array( 'jquery-ui-draggable', 'jquery-ui-slider', 'jquery-touch-punch' ), self::CMB_VERSION );
|
256 |
+
wp_register_script( 'wp-color-picker', admin_url( 'js/color-picker.min.js' ), array( 'iris' ), self::CMB_VERSION );
|
257 |
+
wp_localize_script( 'wp-color-picker', 'wpColorPickerL10n', array(
|
258 |
+
'clear' => __( 'Clear' ),
|
259 |
+
'defaultString' => __( 'Default' ),
|
260 |
+
'pick' => __( 'Select Color' ),
|
261 |
+
'current' => __( 'Current Color' ),
|
262 |
+
) );
|
263 |
+
}
|
264 |
+
} else {
|
265 |
+
// otherwise use the older 'farbtastic'
|
266 |
+
$scripts[] = 'farbtastic';
|
267 |
+
$styles[] = 'farbtastic';
|
268 |
+
}
|
269 |
+
wp_register_script( 'cmb-datepicker', CMB_META_BOX_URL . 'js/jquery.datePicker.min.js' );
|
270 |
+
wp_register_script( 'cmb-timepicker', CMB_META_BOX_URL . 'js/jquery.timePicker.min.js' );
|
271 |
+
wp_register_script( 'cmb-scripts', CMB_META_BOX_URL .'js/cmb'. $min .'.js', $scripts, self::CMB_VERSION );
|
272 |
+
|
273 |
+
wp_enqueue_media();
|
274 |
+
|
275 |
+
wp_localize_script( 'cmb-scripts', 'cmb_l10', apply_filters( 'cmb_localized_data', array(
|
276 |
+
'ajax_nonce' => wp_create_nonce( 'ajax_nonce' ),
|
277 |
+
'script_debug' => defined('SCRIPT_DEBUG') && SCRIPT_DEBUG,
|
278 |
+
'new_admin_style' => version_compare( $wp_version, '3.7', '>' ),
|
279 |
+
'object_type' => self::get_object_type(),
|
280 |
+
'upload_file' => 'Use this file',
|
281 |
+
'remove_image' => 'Remove Image',
|
282 |
+
'remove_file' => 'Remove',
|
283 |
+
'file' => 'File:',
|
284 |
+
'download' => 'Download',
|
285 |
+
'ajaxurl' => admin_url( '/admin-ajax.php' ),
|
286 |
+
'up_arrow' => '[ ↑ ] ',
|
287 |
+
'down_arrow' => ' [ ↓ ]',
|
288 |
+
'check_toggle' => __( 'Select / Deselect All', 'cmb' ),
|
289 |
+
) ) );
|
290 |
+
|
291 |
+
wp_register_style( 'cmb-styles', CMB_META_BOX_URL . 'style'. $min .'.css', $styles );
|
292 |
+
|
293 |
+
// Ok, we've enqueued our scripts/styles
|
294 |
+
self::$is_enqueued = true;
|
295 |
+
}
|
296 |
+
|
297 |
+
/**
|
298 |
+
* Enqueues scripts and styles for CMB
|
299 |
+
* @since 1.0.0
|
300 |
+
*/
|
301 |
+
public function do_scripts( $hook ) {
|
302 |
+
// only enqueue our scripts/styles on the proper pages
|
303 |
+
if ( $hook == 'post.php' || $hook == 'post-new.php' || $hook == 'page-new.php' || $hook == 'page.php' ) {
|
304 |
+
wp_enqueue_script( 'cmb-scripts' );
|
305 |
+
|
306 |
+
// default is to show cmb styles on post pages
|
307 |
+
if ( $this->_meta_box['cmb_styles'] )
|
308 |
+
wp_enqueue_style( 'cmb-styles' );
|
309 |
+
}
|
310 |
+
}
|
311 |
+
|
312 |
+
/**
|
313 |
+
* Add encoding attribute
|
314 |
+
*/
|
315 |
+
public function add_post_enctype() {
|
316 |
+
echo '
|
317 |
+
<script type="text/javascript">
|
318 |
+
jQuery(document).ready(function(){
|
319 |
+
jQuery("#'. $this->form_id .'").attr("enctype", "multipart/form-data");
|
320 |
+
jQuery("#'. $this->form_id .'").attr("encoding", "multipart/form-data");
|
321 |
+
});
|
322 |
+
</script>';
|
323 |
+
}
|
324 |
+
|
325 |
+
/**
|
326 |
+
* Add metaboxes (to 'post' object type)
|
327 |
+
*/
|
328 |
+
public function add_metaboxes() {
|
329 |
+
|
330 |
+
foreach ( $this->_meta_box['pages'] as $page ) {
|
331 |
+
if ( apply_filters( 'cmb_show_on', true, $this->_meta_box ) )
|
332 |
+
add_meta_box( $this->_meta_box['id'], $this->_meta_box['title'], array( $this, 'post_metabox' ), $page, $this->_meta_box['context'], $this->_meta_box['priority']) ;
|
333 |
+
}
|
334 |
+
}
|
335 |
+
|
336 |
+
/**
|
337 |
+
* Display metaboxes for a post object
|
338 |
+
* @since 1.0.0
|
339 |
+
*/
|
340 |
+
public function post_metabox() {
|
341 |
+
if ( ! $this->_meta_box )
|
342 |
+
return;
|
343 |
+
|
344 |
+
self::show_form( $this->_meta_box, get_the_ID(), 'post' );
|
345 |
+
|
346 |
+
}
|
347 |
+
|
348 |
+
/**
|
349 |
+
* Display metaboxes for a user object
|
350 |
+
* @since 1.0.0
|
351 |
+
*/
|
352 |
+
public function user_metabox() {
|
353 |
+
if ( ! $this->_meta_box )
|
354 |
+
return;
|
355 |
+
|
356 |
+
if ( 'user' != self::set_mb_type( $this->_meta_box ) )
|
357 |
+
return;
|
358 |
+
|
359 |
+
if ( ! apply_filters( 'cmb_show_on', true, $this->_meta_box ) )
|
360 |
+
return;
|
361 |
+
|
362 |
+
wp_enqueue_script( 'cmb-scripts' );
|
363 |
+
|
364 |
+
// default is to NOT show cmb styles on user profile page
|
365 |
+
if ( $this->_meta_box['cmb_styles'] != false )
|
366 |
+
wp_enqueue_style( 'cmb-styles' );
|
367 |
+
|
368 |
+
self::show_form( $this->_meta_box );
|
369 |
+
|
370 |
+
}
|
371 |
+
|
372 |
+
/**
|
373 |
+
* Loops through and displays fields
|
374 |
+
* @since 1.0.0
|
375 |
+
* @param array $meta_box Metabox config array
|
376 |
+
* @param int $object_id Object ID
|
377 |
+
* @param string $object_type Type of object being saved. (e.g., post, user, or comment)
|
378 |
+
*/
|
379 |
+
public static function show_form( $meta_box, $object_id = 0, $object_type = '' ) {
|
380 |
+
$meta_box = self::set_mb_defaults( $meta_box );
|
381 |
+
// Set/get type
|
382 |
+
$object_type = self::set_object_type( $object_type ? $object_type : self::set_mb_type( $meta_box ) );
|
383 |
+
// Set/get ID
|
384 |
+
$object_id = self::set_object_id( $object_id ? $object_id : self::get_object_id() );
|
385 |
+
|
386 |
+
// Add nonce only once per page.
|
387 |
+
if ( ! self::$nonce_added ) {
|
388 |
+
wp_nonce_field( self::nonce(), 'wp_meta_box_nonce', false, true );
|
389 |
+
self::$nonce_added = true;
|
390 |
+
}
|
391 |
+
|
392 |
+
// Use nonce for verification
|
393 |
+
echo "\n<!-- Begin CMB Fields -->\n";
|
394 |
+
do_action( 'cmb_before_table', $meta_box, $object_id, $object_type );
|
395 |
+
echo '<table class="form-table cmb_metabox">';
|
396 |
+
|
397 |
+
foreach ( $meta_box['fields'] as $field_args ) {
|
398 |
+
|
399 |
+
$field_args['context'] = $meta_box['context'];
|
400 |
+
|
401 |
+
if ( 'group' == $field_args['type'] ) {
|
402 |
+
|
403 |
+
if ( ! isset( $field_args['show_names'] ) ) {
|
404 |
+
$field_args['show_names'] = $meta_box['show_names'];
|
405 |
+
}
|
406 |
+
self::render_group( $field_args );
|
407 |
+
} else {
|
408 |
+
|
409 |
+
$field_args['show_names'] = $meta_box['show_names'];
|
410 |
+
// Render default fields
|
411 |
+
$field = new cmb_Meta_Box_field( $field_args );
|
412 |
+
$field->render_field();
|
413 |
+
}
|
414 |
+
}
|
415 |
+
echo '</table>';
|
416 |
+
do_action( 'cmb_after_table', $meta_box, $object_id, $object_type );
|
417 |
+
echo "\n<!-- End CMB Fields -->\n";
|
418 |
+
|
419 |
+
}
|
420 |
+
|
421 |
+
/**
|
422 |
+
* Render a repeatable group
|
423 |
+
*/
|
424 |
+
public static function render_group( $args ) {
|
425 |
+
if ( ! isset( $args['id'], $args['fields'] ) || ! is_array( $args['fields'] ) )
|
426 |
+
return;
|
427 |
+
|
428 |
+
$args['count'] = 0;
|
429 |
+
$field_group = new cmb_Meta_Box_field( $args );
|
430 |
+
$desc = $field_group->args( 'description' );
|
431 |
+
$label = $field_group->args( 'name' );
|
432 |
+
$sortable = $field_group->options( 'sortable' ) ? ' sortable' : '';
|
433 |
+
$group_val = (array) $field_group->value();
|
434 |
+
$nrows = count( $group_val );
|
435 |
+
$remove_disabled = $nrows <= 1 ? 'disabled="disabled" ' : '';
|
436 |
+
|
437 |
+
echo '<tr><td colspan="2"><table id="', $field_group->id(), '_repeat" class="repeatable-group'. $sortable .'" style="width:100%;">';
|
438 |
+
if ( $desc || $label ) {
|
439 |
+
echo '<tr><th>';
|
440 |
+
if ( $label )
|
441 |
+
echo '<h2 class="cmb-group-name">'. $label .'</h2>';
|
442 |
+
if ( $desc )
|
443 |
+
echo '<p class="cmb_metabox_description">'. $desc .'</p>';
|
444 |
+
echo '</th></tr>';
|
445 |
+
}
|
446 |
+
|
447 |
+
if ( ! empty( $group_val ) ) {
|
448 |
+
|
449 |
+
foreach ( $group_val as $iterator => $field_id ) {
|
450 |
+
self::render_group_row( $field_group, $remove_disabled );
|
451 |
+
}
|
452 |
+
} else {
|
453 |
+
self::render_group_row( $field_group, $remove_disabled );
|
454 |
+
}
|
455 |
+
|
456 |
+
echo '<tr><td><p class="add-row"><button data-selector="', $field_group->id() ,'_repeat" data-grouptitle="', $field_group->options( 'group_title' ) ,'" class="add-group-row button">'. $field_group->options( 'add_button' ) .'</button></p></td></tr>';
|
457 |
+
|
458 |
+
echo '</table></td></tr>';
|
459 |
+
|
460 |
+
}
|
461 |
+
|
462 |
+
public static function render_group_row( $field_group, $remove_disabled ) {
|
463 |
+
|
464 |
+
echo '
|
465 |
+
<tr class="repeatable-grouping" data-iterator="'. $field_group->count() .'">
|
466 |
+
<td>
|
467 |
+
<table class="cmb-nested-table" style="width: 100%;">';
|
468 |
+
if ( $field_group->options( 'group_title' ) ) {
|
469 |
+
echo '
|
470 |
+
<tr class="cmb-group-title">
|
471 |
+
<th colspan="2">
|
472 |
+
', sprintf( '<h4>%1$s</h4>', $field_group->replace_hash( $field_group->options( 'group_title' ) ) ), '
|
473 |
+
<th>
|
474 |
+
</tr>
|
475 |
+
';
|
476 |
+
}
|
477 |
+
// Render repeatable group fields
|
478 |
+
foreach ( array_values( $field_group->args( 'fields' ) ) as $field_args ) {
|
479 |
+
$field_args['show_names'] = $field_group->args( 'show_names' );
|
480 |
+
$field_args['context'] = $field_group->args( 'context' );
|
481 |
+
$field = new cmb_Meta_Box_field( $field_args, $field_group );
|
482 |
+
$field->render_field();
|
483 |
+
}
|
484 |
+
echo '
|
485 |
+
<tr>
|
486 |
+
<td class="remove-row" colspan="2">
|
487 |
+
<button '. $remove_disabled .'data-selector="'. $field_group->id() .'_repeat" class="button remove-group-row alignright">'. $field_group->options( 'remove_button' ) .'</button>
|
488 |
+
</td>
|
489 |
+
</tr>
|
490 |
+
</table>
|
491 |
+
</td>
|
492 |
+
</tr>
|
493 |
+
';
|
494 |
+
|
495 |
+
$field_group->args['count']++;
|
496 |
+
}
|
497 |
+
|
498 |
+
/**
|
499 |
+
* Save data from metabox
|
500 |
+
*/
|
501 |
+
public function save_post( $post_id, $post = false ) {
|
502 |
+
|
503 |
+
$post_type = $post ? $post->post_type : get_post_type( $post_id );
|
504 |
+
|
505 |
+
// check permissions
|
506 |
+
if (
|
507 |
+
// check nonce
|
508 |
+
! isset( $_POST['wp_meta_box_nonce'] )
|
509 |
+
|| ! wp_verify_nonce( $_POST['wp_meta_box_nonce'], self::nonce() )
|
510 |
+
// check if autosave
|
511 |
+
|| defined('DOING_AUTOSAVE' ) && DOING_AUTOSAVE
|
512 |
+
// check user editing permissions
|
513 |
+
|| ( 'page' == $_POST['post_type'] && ! current_user_can( 'edit_page', $post_id ) )
|
514 |
+
|| ! current_user_can( 'edit_post', $post_id )
|
515 |
+
// get the metabox post_types & compare it to this post_type
|
516 |
+
|| ! in_array( $post_type, $this->_meta_box['pages'] )
|
517 |
+
)
|
518 |
+
return $post_id;
|
519 |
+
|
520 |
+
self::save_fields( $this->_meta_box, $post_id, 'post' );
|
521 |
+
}
|
522 |
+
|
523 |
+
/**
|
524 |
+
* Save data from metabox
|
525 |
+
*/
|
526 |
+
public function save_user( $user_id ) {
|
527 |
+
|
528 |
+
// check permissions
|
529 |
+
// @todo more hardening?
|
530 |
+
if (
|
531 |
+
// check nonce
|
532 |
+
! isset( $_POST['wp_meta_box_nonce'] )
|
533 |
+
|| ! wp_verify_nonce( $_POST['wp_meta_box_nonce'], self::nonce() )
|
534 |
+
)
|
535 |
+
return $user_id;
|
536 |
+
|
537 |
+
self::save_fields( $this->_meta_box, $user_id, 'user' );
|
538 |
+
}
|
539 |
+
|
540 |
+
/**
|
541 |
+
* Loops through and saves field data
|
542 |
+
* @since 1.0.0
|
543 |
+
* @param array $meta_box Metabox config array
|
544 |
+
* @param int $object_id Object ID
|
545 |
+
* @param string $object_type Type of object being saved. (e.g., post, user, or comment)
|
546 |
+
*/
|
547 |
+
public static function save_fields( $meta_box, $object_id, $object_type = '' ) {
|
548 |
+
$meta_box = self::set_mb_defaults( $meta_box );
|
549 |
+
|
550 |
+
$meta_box['show_on'] = empty( $meta_box['show_on'] ) ? array( 'key' => false, 'value' => false ) : $meta_box['show_on'];
|
551 |
+
|
552 |
+
self::set_object_id( $object_id );
|
553 |
+
// Set/get type
|
554 |
+
$object_type = self::set_object_type( $object_type ? $object_type : self::set_mb_type( $meta_box ) );
|
555 |
+
|
556 |
+
if ( ! apply_filters( 'cmb_show_on', true, $meta_box ) )
|
557 |
+
return;
|
558 |
+
|
559 |
+
// save field ids of those that are updated
|
560 |
+
self::$updated = array();
|
561 |
+
|
562 |
+
foreach ( $meta_box['fields'] as $field_args ) {
|
563 |
+
|
564 |
+
if ( 'group' == $field_args['type'] ) {
|
565 |
+
self::save_group( $field_args );
|
566 |
+
} else {
|
567 |
+
// Save default fields
|
568 |
+
$field = new cmb_Meta_Box_field( $field_args );
|
569 |
+
self::save_field( self::sanitize_field( $field ), $field );
|
570 |
+
}
|
571 |
+
|
572 |
+
}
|
573 |
+
|
574 |
+
// If options page, save the updated options
|
575 |
+
if ( $object_type == 'options-page' )
|
576 |
+
self::save_option( $object_id );
|
577 |
+
|
578 |
+
do_action( "cmb_save_{$object_type}_fields", $object_id, $meta_box['id'], self::$updated, $meta_box );
|
579 |
+
|
580 |
+
}
|
581 |
+
|
582 |
+
/**
|
583 |
+
* Save a repeatable group
|
584 |
+
*/
|
585 |
+
public static function save_group( $args ) {
|
586 |
+
if ( ! isset( $args['id'], $args['fields'], $_POST[ $args['id'] ] ) || ! is_array( $args['fields'] ) )
|
587 |
+
return;
|
588 |
+
|
589 |
+
$field_group = new cmb_Meta_Box_field( $args );
|
590 |
+
$base_id = $field_group->id();
|
591 |
+
$old = $field_group->get_data();
|
592 |
+
$group_vals = $_POST[ $base_id ];
|
593 |
+
$saved = array();
|
594 |
+
$is_updated = false;
|
595 |
+
$field_group->index = 0;
|
596 |
+
|
597 |
+
// $group_vals[0]['color'] = '333';
|
598 |
+
foreach ( array_values( $field_group->fields() ) as $field_args ) {
|
599 |
+
$field = new cmb_Meta_Box_field( $field_args, $field_group );
|
600 |
+
$sub_id = $field->id( true );
|
601 |
+
|
602 |
+
foreach ( (array) $group_vals as $field_group->index => $post_vals ) {
|
603 |
+
|
604 |
+
// Get value
|
605 |
+
$new_val = isset( $group_vals[ $field_group->index ][ $sub_id ] )
|
606 |
+
? $group_vals[ $field_group->index ][ $sub_id ]
|
607 |
+
: false;
|
608 |
+
|
609 |
+
// Sanitize
|
610 |
+
$new_val = self::sanitize_field( $field, $new_val, $field_group->index );
|
611 |
+
|
612 |
+
if ( 'file' == $field->type() && is_array( $new_val ) ) {
|
613 |
+
// Add image ID to the array stack
|
614 |
+
$saved[ $field_group->index ][ $new_val['field_id'] ] = $new_val['attach_id'];
|
615 |
+
// Reset var to url string
|
616 |
+
$new_val = $new_val['url'];
|
617 |
+
}
|
618 |
+
|
619 |
+
// Get old value
|
620 |
+
$old_val = is_array( $old ) && isset( $old[ $field_group->index ][ $sub_id ] )
|
621 |
+
? $old[ $field_group->index ][ $sub_id ]
|
622 |
+
: false;
|
623 |
+
|
624 |
+
$is_updated = ( ! empty( $new_val ) && $new_val != $old_val );
|
625 |
+
$is_removed = ( empty( $new_val ) && ! empty( $old_val ) );
|
626 |
+
// Compare values and add to `$updated` array
|
627 |
+
if ( $is_updated || $is_removed )
|
628 |
+
self::$updated[] = $base_id .'::'. $field_group->index .'::'. $sub_id;
|
629 |
+
|
630 |
+
// Add to `$saved` array
|
631 |
+
$saved[ $field_group->index ][ $sub_id ] = $new_val;
|
632 |
+
|
633 |
+
}
|
634 |
+
$saved[ $field_group->index ] = array_filter( $saved[ $field_group->index ] );
|
635 |
+
}
|
636 |
+
$saved = array_filter( $saved );
|
637 |
+
|
638 |
+
$field_group->update_data( $saved, true );
|
639 |
+
}
|
640 |
+
|
641 |
+
public static function sanitize_field( $field, $new_value = null ) {
|
642 |
+
|
643 |
+
$new_value = null !== $new_value
|
644 |
+
? $new_value
|
645 |
+
: ( isset( $_POST[ $field->id( true ) ] ) ? $_POST[ $field->id( true ) ] : null );
|
646 |
+
|
647 |
+
if ( $field->args( 'repeatable' ) && is_array( $new_value ) ) {
|
648 |
+
// Remove empties
|
649 |
+
$new_value = array_filter( $new_value );
|
650 |
+
}
|
651 |
+
|
652 |
+
// Check if this metabox field has a registered validation callback, or perform default sanitization
|
653 |
+
return $field->sanitization_cb( $new_value );
|
654 |
+
}
|
655 |
+
|
656 |
+
public static function save_field( $new_value, $field ) {
|
657 |
+
$name = $field->id();
|
658 |
+
$old = $field->get_data();
|
659 |
+
|
660 |
+
// if ( $field->args( 'multiple' ) && ! $field->args( 'repeatable' ) && ! $field->group ) {
|
661 |
+
// $field->remove_data();
|
662 |
+
// if ( ! empty( $new_value ) ) {
|
663 |
+
// foreach ( $new_value as $add_new ) {
|
664 |
+
// self::$updated[] = $name;
|
665 |
+
// $field->update_data( $add_new, $name, false );
|
666 |
+
// }
|
667 |
+
// }
|
668 |
+
// } else
|
669 |
+
if ( ! empty( $new_value ) && $new_value != $old ) {
|
670 |
+
self::$updated[] = $name;
|
671 |
+
return $field->update_data( $new_value );
|
672 |
+
} elseif ( empty( $new_value ) ) {
|
673 |
+
if ( ! empty( $old ) )
|
674 |
+
self::$updated[] = $name;
|
675 |
+
return $field->remove_data();
|
676 |
+
}
|
677 |
+
}
|
678 |
+
|
679 |
+
/**
|
680 |
+
* Get object id from global space if no id is provided
|
681 |
+
* @since 1.0.0
|
682 |
+
* @param integer $object_id Object ID
|
683 |
+
* @return integer $object_id Object ID
|
684 |
+
*/
|
685 |
+
public static function get_object_id( $object_id = 0 ) {
|
686 |
+
|
687 |
+
if ( $object_id )
|
688 |
+
return $object_id;
|
689 |
+
|
690 |
+
if ( self::$object_id )
|
691 |
+
return self::$object_id;
|
692 |
+
|
693 |
+
// Try to get our object ID from the global space
|
694 |
+
switch ( self::get_object_type() ) {
|
695 |
+
case 'user':
|
696 |
+
$object_id = isset( $GLOBALS['user_ID'] ) ? $GLOBALS['user_ID'] : $object_id;
|
697 |
+
$object_id = isset( $_REQUEST['user_id'] ) ? $_REQUEST['user_id'] : $object_id;
|
698 |
+
break;
|
699 |
+
|
700 |
+
default:
|
701 |
+
$object_id = isset( $GLOBALS['post']->ID ) ? $GLOBALS['post']->ID : $object_id;
|
702 |
+
$object_id = isset( $_REQUEST['post'] ) ? $_REQUEST['post'] : $object_id;
|
703 |
+
break;
|
704 |
+
}
|
705 |
+
|
706 |
+
// reset to id or 0
|
707 |
+
self::set_object_id( $object_id ? $object_id : 0 );
|
708 |
+
|
709 |
+
return self::$object_id;
|
710 |
+
}
|
711 |
+
|
712 |
+
/**
|
713 |
+
* Explicitly Set object id
|
714 |
+
* @since 1.0.0
|
715 |
+
* @param integer $object_id Object ID
|
716 |
+
* @return integer $object_id Object ID
|
717 |
+
*/
|
718 |
+
public static function set_object_id( $object_id ) {
|
719 |
+
return self::$object_id = $object_id;
|
720 |
+
}
|
721 |
+
|
722 |
+
/**
|
723 |
+
* Sets the $object_type based on metabox settings
|
724 |
+
* @since 1.0.0
|
725 |
+
* @param array|string $meta_box Metabox config array or explicit setting
|
726 |
+
* @return string Object type
|
727 |
+
*/
|
728 |
+
public static function set_mb_type( $meta_box ) {
|
729 |
+
|
730 |
+
if ( is_string( $meta_box ) ) {
|
731 |
+
self::$mb_object_type = $meta_box;
|
732 |
+
return self::get_mb_type();
|
733 |
+
}
|
734 |
+
|
735 |
+
if ( ! isset( $meta_box['pages'] ) )
|
736 |
+
return self::get_mb_type();
|
737 |
+
|
738 |
+
$type = false;
|
739 |
+
// check if 'pages' is a string
|
740 |
+
if ( self::is_options_page_mb( $meta_box ) )
|
741 |
+
$type = 'options-page';
|
742 |
+
// check if 'pages' is a string
|
743 |
+
elseif ( is_string( $meta_box['pages'] ) )
|
744 |
+
$type = $meta_box['pages'];
|
745 |
+
// if it's an array of one, extract it
|
746 |
+
elseif ( is_array( $meta_box['pages'] ) && count( $meta_box['pages'] === 1 ) )
|
747 |
+
$type = is_string( end( $meta_box['pages'] ) ) ? end( $meta_box['pages'] ) : false;
|
748 |
+
|
749 |
+
if ( !$type )
|
750 |
+
return self::get_mb_type();
|
751 |
+
|
752 |
+
// Get our object type
|
753 |
+
if ( 'user' == $type )
|
754 |
+
self::$mb_object_type = 'user';
|
755 |
+
elseif ( 'comment' == $type )
|
756 |
+
self::$mb_object_type = 'comment';
|
757 |
+
elseif ( 'options-page' == $type )
|
758 |
+
self::$mb_object_type = 'options-page';
|
759 |
+
else
|
760 |
+
self::$mb_object_type = 'post';
|
761 |
+
|
762 |
+
return self::get_mb_type();
|
763 |
+
}
|
764 |
+
|
765 |
+
/**
|
766 |
+
* Determines if metabox is for an options page
|
767 |
+
* @since 1.0.1
|
768 |
+
* @param array $meta_box Metabox config array
|
769 |
+
* @return boolean True/False
|
770 |
+
*/
|
771 |
+
public static function is_options_page_mb( $meta_box ) {
|
772 |
+
return ( isset( $meta_box['show_on']['key'] ) && 'options-page' === $meta_box['show_on']['key'] );
|
773 |
+
}
|
774 |
+
|
775 |
+
/**
|
776 |
+
* Returns the object type
|
777 |
+
* @since 1.0.0
|
778 |
+
* @return string Object type
|
779 |
+
*/
|
780 |
+
public static function get_object_type() {
|
781 |
+
if ( self::$object_type )
|
782 |
+
return self::$object_type;
|
783 |
+
|
784 |
+
global $pagenow;
|
785 |
+
|
786 |
+
if (
|
787 |
+
$pagenow == 'user-edit.php'
|
788 |
+
|| $pagenow == 'profile.php'
|
789 |
+
)
|
790 |
+
self::set_object_type( 'user' );
|
791 |
+
|
792 |
+
elseif (
|
793 |
+
$pagenow == 'edit-comments.php'
|
794 |
+
|| $pagenow == 'comment.php'
|
795 |
+
)
|
796 |
+
self::set_object_type( 'comment' );
|
797 |
+
else
|
798 |
+
self::set_object_type( 'post' );
|
799 |
+
|
800 |
+
return self::$object_type;
|
801 |
+
}
|
802 |
+
|
803 |
+
/**
|
804 |
+
* Sets the object type
|
805 |
+
* @since 1.0.0
|
806 |
+
* @return string Object type
|
807 |
+
*/
|
808 |
+
public static function set_object_type( $object_type ) {
|
809 |
+
return self::$object_type = $object_type;
|
810 |
+
}
|
811 |
+
|
812 |
+
/**
|
813 |
+
* Returns the object type
|
814 |
+
* @since 1.0.0
|
815 |
+
* @return string Object type
|
816 |
+
*/
|
817 |
+
public static function get_mb_type() {
|
818 |
+
return self::$mb_object_type;
|
819 |
+
}
|
820 |
+
|
821 |
+
/**
|
822 |
+
* Returns the nonce value for wp_meta_box_nonce
|
823 |
+
* @since 1.0.0
|
824 |
+
* @return string Nonce value
|
825 |
+
*/
|
826 |
+
public static function nonce() {
|
827 |
+
return basename( __FILE__ );
|
828 |
+
}
|
829 |
+
|
830 |
+
/**
|
831 |
+
* Defines the url which is used to load local resources.
|
832 |
+
* This may need to be filtered for local Window installations.
|
833 |
+
* If resources do not load, please check the wiki for details.
|
834 |
+
* @since 1.0.1
|
835 |
+
* @return string URL to CMB resources
|
836 |
+
*/
|
837 |
+
public static function get_meta_box_url() {
|
838 |
+
|
839 |
+
if ( strtoupper( substr( PHP_OS, 0, 3 ) ) === 'WIN' ) {
|
840 |
+
// Windows
|
841 |
+
$content_dir = str_replace( '/', DIRECTORY_SEPARATOR, WP_CONTENT_DIR );
|
842 |
+
$content_url = str_replace( $content_dir, WP_CONTENT_URL, dirname(__FILE__) );
|
843 |
+
$cmb_url = str_replace( DIRECTORY_SEPARATOR, '/', $content_url );
|
844 |
+
|
845 |
+
} else {
|
846 |
+
$cmb_url = str_replace(
|
847 |
+
array(WP_CONTENT_DIR, WP_PLUGIN_DIR),
|
848 |
+
array(WP_CONTENT_URL, WP_PLUGIN_URL),
|
849 |
+
dirname( __FILE__ )
|
850 |
+
);
|
851 |
+
}
|
852 |
+
|
853 |
+
return trailingslashit( apply_filters('cmb_meta_box_url', $cmb_url ) );
|
854 |
+
}
|
855 |
+
|
856 |
+
/**
|
857 |
+
* Fills in empty metabox parameters with defaults
|
858 |
+
* @since 1.0.1
|
859 |
+
* @param array $meta_box Metabox config array
|
860 |
+
* @return array Modified Metabox config array
|
861 |
+
*/
|
862 |
+
public static function set_mb_defaults( $meta_box ) {
|
863 |
+
return wp_parse_args( $meta_box, self::$mb_defaults );
|
864 |
+
}
|
865 |
+
|
866 |
+
/**
|
867 |
+
* Removes an option from an option array
|
868 |
+
* @since 1.0.1
|
869 |
+
* @param string $option_key Option key
|
870 |
+
* @param string $field_id Option array field key
|
871 |
+
* @return array Modified options
|
872 |
+
*/
|
873 |
+
public static function remove_option( $option_key, $field_id ) {
|
874 |
+
|
875 |
+
self::$options[ $option_key ] = ! isset( self::$options[ $option_key ] ) || empty( self::$options[ $option_key ] ) ? self::_get_option( $option_key ) : self::$options[ $option_key ];
|
876 |
+
|
877 |
+
if ( isset( self::$options[ $option_key ][ $field_id ] ) )
|
878 |
+
unset( self::$options[ $option_key ][ $field_id ] );
|
879 |
+
|
880 |
+
return self::$options[ $option_key ];
|
881 |
+
}
|
882 |
+
|
883 |
+
/**
|
884 |
+
* Retrieves an option from an option array
|
885 |
+
* @since 1.0.1
|
886 |
+
* @param string $option_key Option key
|
887 |
+
* @param string $field_id Option array field key
|
888 |
+
* @return array Options array or specific field
|
889 |
+
*/
|
890 |
+
public static function get_option( $option_key, $field_id = '' ) {
|
891 |
+
|
892 |
+
self::$options[ $option_key ] = ! isset( self::$options[ $option_key ] ) || empty( self::$options[ $option_key ] ) ? self::_get_option( $option_key ) : self::$options[ $option_key ];
|
893 |
+
|
894 |
+
if ( $field_id ) {
|
895 |
+
return isset( self::$options[ $option_key ][ $field_id ] ) ? self::$options[ $option_key ][ $field_id ] : false;
|
896 |
+
}
|
897 |
+
|
898 |
+
return self::$options[ $option_key ];
|
899 |
+
}
|
900 |
+
|
901 |
+
/**
|
902 |
+
* Updates Option data
|
903 |
+
* @since 1.0.1
|
904 |
+
* @param string $option_key Option key
|
905 |
+
* @param string $field_id Option array field key
|
906 |
+
* @param mixed $value Value to update data with
|
907 |
+
* @param bool $single Whether data should be an array
|
908 |
+
* @return array Modified options
|
909 |
+
*/
|
910 |
+
public static function update_option( $option_key, $field_id, $value, $single = true ) {
|
911 |
+
|
912 |
+
if ( ! $single ) {
|
913 |
+
// If multiple, add to array
|
914 |
+
self::$options[ $option_key ][ $field_id ][] = $value;
|
915 |
+
} else {
|
916 |
+
self::$options[ $option_key ][ $field_id ] = $value;
|
917 |
+
}
|
918 |
+
|
919 |
+
return self::$options[ $option_key ];
|
920 |
+
}
|
921 |
+
|
922 |
+
/**
|
923 |
+
* Retrieve option value based on name of option.
|
924 |
+
* @uses apply_filters() Calls 'cmb_override_option_get_$option_key' hook to allow
|
925 |
+
* overwriting the option value to be retrieved.
|
926 |
+
*
|
927 |
+
* @since 1.0.1
|
928 |
+
* @param string $option Name of option to retrieve. Expected to not be SQL-escaped.
|
929 |
+
* @param mixed $default Optional. Default value to return if the option does not exist.
|
930 |
+
* @return mixed Value set for the option.
|
931 |
+
*/
|
932 |
+
public static function _get_option( $option_key, $default = false ) {
|
933 |
+
|
934 |
+
$test_get = apply_filters( "cmb_override_option_get_$option_key", 'cmb_no_override_option_get', $default );
|
935 |
+
|
936 |
+
if ( $test_get !== 'cmb_no_override_option_get' )
|
937 |
+
return $test_get;
|
938 |
+
|
939 |
+
// If no override, get the option
|
940 |
+
return get_option( $option_key, $default );
|
941 |
+
}
|
942 |
+
|
943 |
+
/**
|
944 |
+
* Saves the option array
|
945 |
+
* Needs to be run after finished using remove/update_option
|
946 |
+
* @uses apply_filters() Calls 'cmb_override_option_save_$option_key' hook to allow
|
947 |
+
* overwriting the option value to be stored.
|
948 |
+
*
|
949 |
+
* @since 1.0.1
|
950 |
+
* @param string $option_key Option key
|
951 |
+
* @return boolean Success/Failure
|
952 |
+
*/
|
953 |
+
public static function save_option( $option_key ) {
|
954 |
+
|
955 |
+
$to_save = self::get_option( $option_key );
|
956 |
+
|
957 |
+
$test_save = apply_filters( "cmb_override_option_save_$option_key", 'cmb_no_override_option_save', $to_save );
|
958 |
+
|
959 |
+
if ( $test_save !== 'cmb_no_override_option_save' )
|
960 |
+
return $test_save;
|
961 |
+
|
962 |
+
// If no override, update the option
|
963 |
+
return update_option( $option_key, $to_save );
|
964 |
+
}
|
965 |
+
|
966 |
+
/**
|
967 |
+
* Utility method that returns a timezone string representing the default timezone for the site.
|
968 |
+
*
|
969 |
+
* Roughly copied from WordPress, as get_option('timezone_string') will return
|
970 |
+
* and empty string if no value has beens set on the options page.
|
971 |
+
* A timezone string is required by the wp_timezone_choice() used by the
|
972 |
+
* select_timezone field.
|
973 |
+
*
|
974 |
+
* @since 1.0.0
|
975 |
+
* @return string Timezone string
|
976 |
+
*/
|
977 |
+
public static function timezone_string() {
|
978 |
+
$current_offset = get_option( 'gmt_offset' );
|
979 |
+
$tzstring = get_option( 'timezone_string' );
|
980 |
+
|
981 |
+
if ( empty( $tzstring ) ) { // Create a UTC+- zone if no timezone string exists
|
982 |
+
if ( 0 == $current_offset )
|
983 |
+
$tzstring = 'UTC+0';
|
984 |
+
elseif ( $current_offset < 0 )
|
985 |
+
$tzstring = 'UTC' . $current_offset;
|
986 |
+
else
|
987 |
+
$tzstring = 'UTC+' . $current_offset;
|
988 |
+
}
|
989 |
+
|
990 |
+
return $tzstring;
|
991 |
+
}
|
992 |
+
|
993 |
+
/**
|
994 |
+
* Utility method that returns time string offset by timezone
|
995 |
+
* @since 1.0.0
|
996 |
+
* @param string $tzstring Time string
|
997 |
+
* @return string Offset time string
|
998 |
+
*/
|
999 |
+
public static function timezone_offset( $tzstring ) {
|
1000 |
+
if ( ! empty( $tzstring ) && is_string( $tzstring ) ) {
|
1001 |
+
if ( substr( $tzstring, 0, 3 ) === 'UTC' ) {
|
1002 |
+
$tzstring = str_replace( array( ':15',':30',':45' ), array( '.25','.5','.75' ), $tzstring );
|
1003 |
+
return intval( floatval( substr( $tzstring, 3 ) ) * HOUR_IN_SECONDS );
|
1004 |
+
}
|
1005 |
+
|
1006 |
+
$date_time_zone_selected = new DateTimeZone( $tzstring );
|
1007 |
+
$tz_offset = timezone_offset_get( $date_time_zone_selected, date_create() );
|
1008 |
+
|
1009 |
+
return $tz_offset;
|
1010 |
+
}
|
1011 |
+
|
1012 |
+
return 0;
|
1013 |
+
}
|
1014 |
+
|
1015 |
+
/**
|
1016 |
+
* Utility method that attempts to get an attachment's ID by it's url
|
1017 |
+
* @since 1.0.0
|
1018 |
+
* @param string $img_url Attachment url
|
1019 |
+
* @return mixed Attachment ID or false
|
1020 |
+
*/
|
1021 |
+
public static function image_id_from_url( $img_url ) {
|
1022 |
+
global $wpdb;
|
1023 |
+
|
1024 |
+
$img_url = esc_url_raw( $img_url );
|
1025 |
+
// Get just the file name
|
1026 |
+
if ( false !== strpos( $img_url, '/' ) ) {
|
1027 |
+
$explode = explode( '/', $img_url );
|
1028 |
+
$img_url = end( $explode );
|
1029 |
+
}
|
1030 |
+
|
1031 |
+
// And search for a fuzzy match of the file name
|
1032 |
+
$attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid LIKE '%%%s%%' LIMIT 1;", $img_url ) );
|
1033 |
+
|
1034 |
+
// If we found an attachement ID, return it
|
1035 |
+
if ( !empty( $attachment ) && is_array( $attachment ) )
|
1036 |
+
return $attachment[0];
|
1037 |
+
|
1038 |
+
// No luck
|
1039 |
+
return false;
|
1040 |
+
}
|
1041 |
+
|
1042 |
+
}
|
1043 |
+
|
1044 |
+
// Handle oembed Ajax
|
1045 |
+
add_action( 'wp_ajax_cmb_oembed_handler', array( 'cmb_Meta_Box_ajax', 'oembed_handler' ) );
|
1046 |
+
add_action( 'wp_ajax_nopriv_cmb_oembed_handler', array( 'cmb_Meta_Box_ajax', 'oembed_handler' ) );
|
1047 |
+
|
1048 |
+
/**
|
1049 |
+
* A helper function to get an option from a CMB options array
|
1050 |
+
* @since 1.0.1
|
1051 |
+
* @param string $option_key Option key
|
1052 |
+
* @param string $field_id Option array field key
|
1053 |
+
* @return array Options array or specific field
|
1054 |
+
*/
|
1055 |
+
function cmb_get_option( $option_key, $field_id = '' ) {
|
1056 |
+
return cmb_Meta_Box::get_option( $option_key, $field_id );
|
1057 |
+
}
|
1058 |
+
|
1059 |
+
/**
|
1060 |
+
* Get a CMB field object.
|
1061 |
+
* @since 1.1.0
|
1062 |
+
* @param array $field_args Field arguments
|
1063 |
+
* @param int $object_id Object ID
|
1064 |
+
* @param string $object_type Type of object being saved. (e.g., post, user, or comment)
|
1065 |
+
* @return object cmb_Meta_Box_field object
|
1066 |
+
*/
|
1067 |
+
function cmb_get_field( $field_args, $object_id = 0, $object_type = 'post' ) {
|
1068 |
+
// Default to the loop post ID
|
1069 |
+
$object_id = $object_id ? $object_id : get_the_ID();
|
1070 |
+
cmb_Meta_Box::set_object_id( $object_id );
|
1071 |
+
cmb_Meta_Box::set_object_type( $object_type );
|
1072 |
+
// Send back field object
|
1073 |
+
return new cmb_Meta_Box_field( $field_args );
|
1074 |
+
}
|
1075 |
+
|
1076 |
+
/**
|
1077 |
+
* Get a field's value.
|
1078 |
+
* @since 1.1.0
|
1079 |
+
* @param array $field_args Field arguments
|
1080 |
+
* @param int $object_id Object ID
|
1081 |
+
* @param string $object_type Type of object being saved. (e.g., post, user, comment, or options-page)
|
1082 |
+
* @return mixed Maybe escaped value
|
1083 |
+
*/
|
1084 |
+
function cmb_get_field_value( $field_args, $object_id = 0, $object_type = 'post' ) {
|
1085 |
+
$field = cmb_get_field( $field_args, $object_id, $object_type );
|
1086 |
+
return $field->escaped_value();
|
1087 |
+
}
|
1088 |
+
|
1089 |
+
/**
|
1090 |
+
* Loop and output multiple metaboxes
|
1091 |
+
* @since 1.0.0
|
1092 |
+
* @param array $meta_boxes Metaboxes config array
|
1093 |
+
* @param int $object_id Object ID
|
1094 |
+
*/
|
1095 |
+
function cmb_print_metaboxes( $meta_boxes, $object_id ) {
|
1096 |
+
foreach ( (array) $meta_boxes as $meta_box ) {
|
1097 |
+
cmb_print_metabox( $meta_box, $object_id );
|
1098 |
+
}
|
1099 |
+
}
|
1100 |
+
|
1101 |
+
/**
|
1102 |
+
* Output a metabox
|
1103 |
+
* @since 1.0.0
|
1104 |
+
* @param array $meta_box Metabox config array
|
1105 |
+
* @param int $object_id Object ID
|
1106 |
+
*/
|
1107 |
+
function cmb_print_metabox( $meta_box, $object_id ) {
|
1108 |
+
$cmb = new cmb_Meta_Box( $meta_box );
|
1109 |
+
if ( $cmb ) {
|
1110 |
+
|
1111 |
+
cmb_Meta_Box::set_object_id( $object_id );
|
1112 |
+
|
1113 |
+
if ( ! wp_script_is( 'cmb-scripts', 'registered' ) )
|
1114 |
+
$cmb->register_scripts();
|
1115 |
+
|
1116 |
+
wp_enqueue_script( 'cmb-scripts' );
|
1117 |
+
|
1118 |
+
// default is to show cmb styles
|
1119 |
+
if ( $meta_box['cmb_styles'] != false )
|
1120 |
+
wp_enqueue_style( 'cmb-styles' );
|
1121 |
+
|
1122 |
+
cmb_Meta_Box::show_form( $meta_box );
|
1123 |
+
}
|
1124 |
+
|
1125 |
+
}
|
1126 |
+
|
1127 |
+
/**
|
1128 |
+
* Saves a particular metabox's fields
|
1129 |
+
* @since 1.0.0
|
1130 |
+
* @param array $meta_box Metabox config array
|
1131 |
+
* @param int $object_id Object ID
|
1132 |
+
*/
|
1133 |
+
function cmb_save_metabox_fields( $meta_box, $object_id ) {
|
1134 |
+
cmb_Meta_Box::save_fields( $meta_box, $object_id );
|
1135 |
+
}
|
1136 |
+
|
1137 |
+
/**
|
1138 |
+
* Display a metabox form & save it on submission
|
1139 |
+
* @since 1.0.0
|
1140 |
+
* @param array $meta_box Metabox config array
|
1141 |
+
* @param int $object_id Object ID
|
1142 |
+
* @param boolean $return Whether to return or echo form
|
1143 |
+
* @return string CMB html form markup
|
1144 |
+
*/
|
1145 |
+
function cmb_metabox_form( $meta_box, $object_id, $echo = true ) {
|
1146 |
+
|
1147 |
+
$meta_box = cmb_Meta_Box::set_mb_defaults( $meta_box );
|
1148 |
+
|
1149 |
+
// Make sure form should be shown
|
1150 |
+
if ( ! apply_filters( 'cmb_show_on', true, $meta_box ) )
|
1151 |
+
return '';
|
1152 |
+
|
1153 |
+
// Make sure that our object type is explicitly set by the metabox config
|
1154 |
+
cmb_Meta_Box::set_object_type( cmb_Meta_Box::set_mb_type( $meta_box ) );
|
1155 |
+
|
1156 |
+
// Save the metabox if it's been submitted
|
1157 |
+
// check permissions
|
1158 |
+
// @todo more hardening?
|
1159 |
+
if (
|
1160 |
+
// check nonce
|
1161 |
+
isset( $_POST['submit-cmb'], $_POST['object_id'], $_POST['wp_meta_box_nonce'] )
|
1162 |
+
&& wp_verify_nonce( $_POST['wp_meta_box_nonce'], cmb_Meta_Box::nonce() )
|
1163 |
+
&& $_POST['object_id'] == $object_id
|
1164 |
+
)
|
1165 |
+
cmb_save_metabox_fields( $meta_box, $object_id );
|
1166 |
+
|
1167 |
+
// Show specific metabox form
|
1168 |
+
|
1169 |
+
// Get cmb form
|
1170 |
+
ob_start();
|
1171 |
+
cmb_print_metabox( $meta_box, $object_id );
|
1172 |
+
$form = ob_get_contents();
|
1173 |
+
ob_end_clean();
|
1174 |
+
|
1175 |
+
$form_format = apply_filters( 'cmb_frontend_form_format', '<form class="cmb-form" method="post" id="%s" enctype="multipart/form-data" encoding="multipart/form-data"><input type="hidden" name="object_id" value="%s">%s<input type="submit" name="submit-cmb" value="%s" class="button-primary"></form>', $object_id, $meta_box, $form );
|
1176 |
+
|
1177 |
+
$form = sprintf( $form_format, $meta_box['id'], $object_id, $form, __( 'Save' ) );
|
1178 |
+
|
1179 |
+
if ( $echo )
|
1180 |
+
echo $form;
|
1181 |
+
|
1182 |
+
return $form;
|
1183 |
+
}
|
1184 |
+
|
1185 |
+
// End. That's it, folks! //
|
lib/cmb_metaboxes/js/cmb.js
ADDED
@@ -0,0 +1,797 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* Controls the behaviours of custom metabox fields.
|
3 |
+
*
|
4 |
+
* @author Andrew Norcross
|
5 |
+
* @author Jared Atchison
|
6 |
+
* @author Bill Erickson
|
7 |
+
* @author Justin Sternberg
|
8 |
+
* @see https://github.com/webdevstudios/Custom-Metaboxes-and-Fields-for-WordPress
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Custom jQuery for Custom Metaboxes and Fields
|
13 |
+
*/
|
14 |
+
window.CMB = (function(window, document, $, undefined){
|
15 |
+
'use strict';
|
16 |
+
|
17 |
+
// localization strings
|
18 |
+
var l10n = window.cmb_l10;
|
19 |
+
var setTimeout = window.setTimeout;
|
20 |
+
|
21 |
+
// CMB functionality object
|
22 |
+
var cmb = {
|
23 |
+
formfield : '',
|
24 |
+
idNumber : false,
|
25 |
+
file_frames : {},
|
26 |
+
repeatEls : 'input:not([type="button"]),select,textarea,.cmb_media_status'
|
27 |
+
};
|
28 |
+
|
29 |
+
cmb.metabox = function() {
|
30 |
+
if ( cmb.$metabox ) {
|
31 |
+
return cmb.$metabox;
|
32 |
+
}
|
33 |
+
cmb.$metabox = $('table.cmb_metabox');
|
34 |
+
return cmb.$metabox;
|
35 |
+
};
|
36 |
+
|
37 |
+
cmb.init = function() {
|
38 |
+
|
39 |
+
var $metabox = cmb.metabox();
|
40 |
+
var $repeatGroup = $metabox.find('.repeatable-group');
|
41 |
+
|
42 |
+
// hide our spinner gif if we're on a MP6 dashboard
|
43 |
+
if ( l10n.new_admin_style ) {
|
44 |
+
$metabox.find('.cmb-spinner img').hide();
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Initialize time/date/color pickers
|
49 |
+
*/
|
50 |
+
cmb.initPickers( $metabox.find('input:text.cmb_timepicker'), $metabox.find('input:text.cmb_datepicker'), $metabox.find('input:text.cmb_colorpicker') );
|
51 |
+
|
52 |
+
// Wrap date picker in class to narrow the scope of jQuery UI CSS and prevent conflicts
|
53 |
+
$("#ui-datepicker-div").wrap('<div class="cmb_element" />');
|
54 |
+
|
55 |
+
// Insert toggle button into DOM wherever there is multicheck. credit: Genesis Framework
|
56 |
+
$( '<p><span class="button cmb-multicheck-toggle">' + l10n.check_toggle + '</span></p>' ).insertBefore( 'ul.cmb_checkbox_list' );
|
57 |
+
|
58 |
+
$metabox
|
59 |
+
.on( 'change', '.cmb_upload_file', function() {
|
60 |
+
cmb.formfield = $(this).attr('id');
|
61 |
+
$('#' + cmb.formfield + '_id').val('');
|
62 |
+
})
|
63 |
+
// Media/file management
|
64 |
+
.on( 'click', '.cmb-multicheck-toggle', cmb.toggleCheckBoxes )
|
65 |
+
.on( 'click', '.cmb_upload_button', cmb.handleMedia )
|
66 |
+
.on( 'click', '.cmb_remove_file_button', cmb.handleRemoveMedia )
|
67 |
+
// Repeatable content
|
68 |
+
.on( 'click', '.add-group-row', cmb.addGroupRow )
|
69 |
+
.on( 'click', '.add-row-button', cmb.addAjaxRow )
|
70 |
+
.on( 'click', '.remove-group-row', cmb.removeGroupRow )
|
71 |
+
.on( 'click', '.remove-row-button', cmb.removeAjaxRow )
|
72 |
+
// Ajax oEmbed display
|
73 |
+
.on( 'keyup paste focusout', '.cmb_oembed', cmb.maybeOembed )
|
74 |
+
// Reset titles when removing a row
|
75 |
+
.on( 'cmb_remove_row', '.repeatable-group', cmb.resetTitlesAndIterator );
|
76 |
+
|
77 |
+
if ( $repeatGroup.length ) {
|
78 |
+
$repeatGroup
|
79 |
+
.filter('.sortable').each( function() {
|
80 |
+
// Add sorting arrows
|
81 |
+
$(this).find( '.remove-group-row' ).before( '<a class="shift-rows move-up alignleft" href="#">'+ l10n.up_arrow +'</a> <a class="shift-rows move-down alignleft" href="#">'+ l10n.down_arrow +'</a>' );
|
82 |
+
})
|
83 |
+
.on( 'click', '.shift-rows', cmb.shiftRows )
|
84 |
+
.on( 'cmb_add_row', cmb.emptyValue );
|
85 |
+
}
|
86 |
+
|
87 |
+
// on pageload
|
88 |
+
setTimeout( cmb.resizeoEmbeds, 500);
|
89 |
+
// and on window resize
|
90 |
+
$(window).on( 'resize', cmb.resizeoEmbeds );
|
91 |
+
|
92 |
+
};
|
93 |
+
|
94 |
+
cmb.resetTitlesAndIterator = function() {
|
95 |
+
// Loop repeatable group tables
|
96 |
+
$( '.repeatable-group' ).each( function() {
|
97 |
+
var $table = $(this);
|
98 |
+
// Loop repeatable group table rows
|
99 |
+
$table.find( '.repeatable-grouping' ).each( function( rowindex ) {
|
100 |
+
var $row = $(this);
|
101 |
+
// Reset rows iterator
|
102 |
+
$row.data( 'iterator', rowindex );
|
103 |
+
// Reset rows title
|
104 |
+
$row.find( '.cmb-group-title h4' ).text( $table.find( '.add-group-row' ).data( 'grouptitle' ).replace( '{#}', ( rowindex + 1 ) ) );
|
105 |
+
});
|
106 |
+
});
|
107 |
+
};
|
108 |
+
|
109 |
+
cmb.toggleCheckBoxes = function( event ) {
|
110 |
+
event.preventDefault();
|
111 |
+
var $self = $(this);
|
112 |
+
var $multicheck = $self.parents( 'td' ).find( 'input[type=checkbox]' );
|
113 |
+
|
114 |
+
// If the button has already been clicked once...
|
115 |
+
if ( $self.data( 'checked' ) ) {
|
116 |
+
// clear the checkboxes and remove the flag
|
117 |
+
$multicheck.prop( 'checked', false );
|
118 |
+
$self.data( 'checked', false );
|
119 |
+
}
|
120 |
+
// Otherwise mark the checkboxes and add a flag
|
121 |
+
else {
|
122 |
+
$multicheck.prop( 'checked', true );
|
123 |
+
$self.data( 'checked', true );
|
124 |
+
}
|
125 |
+
};
|
126 |
+
|
127 |
+
cmb.handleMedia = function(event) {
|
128 |
+
|
129 |
+
if ( ! wp ) {
|
130 |
+
return;
|
131 |
+
}
|
132 |
+
|
133 |
+
event.preventDefault();
|
134 |
+
|
135 |
+
var $metabox = cmb.metabox();
|
136 |
+
var $self = $(this);
|
137 |
+
cmb.formfield = $self.prev('input').attr('id');
|
138 |
+
var $formfield = $('#'+cmb.formfield);
|
139 |
+
var formName = $formfield.attr('name');
|
140 |
+
var uploadStatus = true;
|
141 |
+
var attachment = true;
|
142 |
+
var isList = $self.hasClass( 'cmb_upload_list' );
|
143 |
+
|
144 |
+
// If this field's media frame already exists, reopen it.
|
145 |
+
if ( cmb.formfield in cmb.file_frames ) {
|
146 |
+
cmb.file_frames[cmb.formfield].open();
|
147 |
+
return;
|
148 |
+
}
|
149 |
+
|
150 |
+
// Create the media frame.
|
151 |
+
cmb.file_frames[cmb.formfield] = wp.media.frames.file_frame = wp.media({
|
152 |
+
title: $metabox.find('label[for=' + cmb.formfield + ']').text(),
|
153 |
+
button: {
|
154 |
+
text: l10n.upload_file
|
155 |
+
},
|
156 |
+
multiple: isList ? true : false
|
157 |
+
});
|
158 |
+
|
159 |
+
var handlers = {
|
160 |
+
list : function( selection ) {
|
161 |
+
// Get all of our selected files
|
162 |
+
attachment = selection.toJSON();
|
163 |
+
|
164 |
+
$formfield.val(attachment.url);
|
165 |
+
$('#'+ cmb.formfield +'_id').val(attachment.id);
|
166 |
+
|
167 |
+
// Setup our fileGroup array
|
168 |
+
var fileGroup = [];
|
169 |
+
|
170 |
+
// Loop through each attachment
|
171 |
+
$( attachment ).each( function() {
|
172 |
+
if ( this.type && this.type === 'image' ) {
|
173 |
+
// image preview
|
174 |
+
uploadStatus = '<li class="img_status">'+
|
175 |
+
'<img width="50" height="50" src="' + this.url + '" class="attachment-50x50" alt="'+ this.filename +'">'+
|
176 |
+
'<p><a href="#" class="cmb_remove_file_button" rel="'+ cmb.formfield +'['+ this.id +']">'+ l10n.remove_image +'</a></p>'+
|
177 |
+
'<input type="hidden" id="filelist-'+ this.id +'" name="'+ formName +'['+ this.id +']" value="' + this.url + '">'+
|
178 |
+
'</li>';
|
179 |
+
|
180 |
+
} else {
|
181 |
+
// Standard generic output if it's not an image.
|
182 |
+
uploadStatus = '<li>'+ l10n.file +' <strong>'+ this.filename +'</strong> (<a href="' + this.url + '" target="_blank" rel="external">'+ l10n.download +'</a> / <a href="#" class="cmb_remove_file_button" rel="'+ cmb.formfield +'['+ this.id +']">'+ l10n.remove_file +'</a>)'+
|
183 |
+
'<input type="hidden" id="filelist-'+ this.id +'" name="'+ formName +'['+ this.id +']" value="' + this.url + '">'+
|
184 |
+
'</li>';
|
185 |
+
|
186 |
+
}
|
187 |
+
|
188 |
+
// Add our file to our fileGroup array
|
189 |
+
fileGroup.push( uploadStatus );
|
190 |
+
});
|
191 |
+
|
192 |
+
// Append each item from our fileGroup array to .cmb_media_status
|
193 |
+
$( fileGroup ).each( function() {
|
194 |
+
$formfield.siblings('.cmb_media_status').slideDown().append(this);
|
195 |
+
});
|
196 |
+
},
|
197 |
+
single : function( selection ) {
|
198 |
+
// Only get one file from the uploader
|
199 |
+
attachment = selection.first().toJSON();
|
200 |
+
|
201 |
+
$formfield.val(attachment.url);
|
202 |
+
$('#'+ cmb.formfield +'_id').val(attachment.id);
|
203 |
+
|
204 |
+
if ( attachment.type && attachment.type === 'image' ) {
|
205 |
+
// image preview
|
206 |
+
uploadStatus = '<div class="img_status"><img style="max-width: 350px; width: 100%; height: auto;" src="' + attachment.url + '" alt="'+ attachment.filename +'" title="'+ attachment.filename +'" /><p><a href="#" class="cmb_remove_file_button" rel="' + cmb.formfield + '">'+ l10n.remove_image +'</a></p></div>';
|
207 |
+
} else {
|
208 |
+
// Standard generic output if it's not an image.
|
209 |
+
uploadStatus = l10n.file +' <strong>'+ attachment.filename +'</strong> (<a href="'+ attachment.url +'" target="_blank" rel="external">'+ l10n.download +'</a> / <a href="#" class="cmb_remove_file_button" rel="'+ cmb.formfield +'">'+ l10n.remove_file +'</a>)';
|
210 |
+
}
|
211 |
+
|
212 |
+
// add/display our output
|
213 |
+
$formfield.siblings('.cmb_media_status').slideDown().html(uploadStatus);
|
214 |
+
}
|
215 |
+
};
|
216 |
+
|
217 |
+
// When an file is selected, run a callback.
|
218 |
+
cmb.file_frames[cmb.formfield].on( 'select', function() {
|
219 |
+
var selection = cmb.file_frames[cmb.formfield].state().get('selection');
|
220 |
+
var type = isList ? 'list' : 'single';
|
221 |
+
handlers[type]( selection );
|
222 |
+
});
|
223 |
+
|
224 |
+
// Finally, open the modal
|
225 |
+
cmb.file_frames[cmb.formfield].open();
|
226 |
+
};
|
227 |
+
|
228 |
+
cmb.handleRemoveMedia = function( event ) {
|
229 |
+
event.preventDefault();
|
230 |
+
var $self = $(this);
|
231 |
+
if ( $self.is( '.attach_list .cmb_remove_file_button' ) ){
|
232 |
+
$self.parents('li').remove();
|
233 |
+
return false;
|
234 |
+
}
|
235 |
+
cmb.formfield = $self.attr('rel');
|
236 |
+
var $container = $self.parents('.img_status');
|
237 |
+
|
238 |
+
cmb.metabox().find('input#' + cmb.formfield).val('');
|
239 |
+
cmb.metabox().find('input#' + cmb.formfield + '_id').val('');
|
240 |
+
if ( ! $container.length ) {
|
241 |
+
$self.parents('.cmb_media_status').html('');
|
242 |
+
} else {
|
243 |
+
$container.html('');
|
244 |
+
}
|
245 |
+
return false;
|
246 |
+
};
|
247 |
+
|
248 |
+
// src: http://www.benalman.com/projects/jquery-replacetext-plugin/
|
249 |
+
$.fn.replaceText = function(b, a, c) {
|
250 |
+
return this.each(function() {
|
251 |
+
var f = this.firstChild, g, e, d = [];
|
252 |
+
if (f) {
|
253 |
+
do {
|
254 |
+
if (f.nodeType === 3) {
|
255 |
+
g = f.nodeValue;
|
256 |
+
e = g.replace(b, a);
|
257 |
+
if (e !== g) {
|
258 |
+
if (!c && /</.test(e)) {
|
259 |
+
$(f).before(e);
|
260 |
+
d.push(f);
|
261 |
+
} else {
|
262 |
+
f.nodeValue = e;
|
263 |
+
}
|
264 |
+
}
|
265 |
+
}
|
266 |
+
} while (f = f.nextSibling);
|
267 |
+
}
|
268 |
+
if ( d.length ) { $(d).remove(); }
|
269 |
+
});
|
270 |
+
};
|
271 |
+
|
272 |
+
$.fn.cleanRow = function( prevNum, group ) {
|
273 |
+
var $self = $(this);
|
274 |
+
var $inputs = $self.find('input:not([type="button"]), select, textarea, label');
|
275 |
+
if ( group ) {
|
276 |
+
// Remove extra ajaxed rows
|
277 |
+
$self.find('.cmb-repeat-table .repeat-row:not(:first-child)').remove();
|
278 |
+
}
|
279 |
+
cmb.$focus = false;
|
280 |
+
cmb.neweditor_id = [];
|
281 |
+
|
282 |
+
$inputs.filter(':checked').removeAttr( 'checked' );
|
283 |
+
$inputs.filter(':selected').removeAttr( 'selected' );
|
284 |
+
|
285 |
+
if ( $self.find('.cmb-group-title') ) {
|
286 |
+
$self.find( '.cmb-group-title h4' ).text( $self.data( 'title' ).replace( '{#}', ( cmb.idNumber + 1 ) ) );
|
287 |
+
}
|
288 |
+
|
289 |
+
$inputs.each( function(){
|
290 |
+
var $newInput = $(this);
|
291 |
+
var isEditor = $newInput.hasClass( 'wp-editor-area' );
|
292 |
+
var oldFor = $newInput.attr( 'for' );
|
293 |
+
// var $next = $newInput.next();
|
294 |
+
var attrs = {};
|
295 |
+
var newID, oldID;
|
296 |
+
if ( oldFor ) {
|
297 |
+
attrs = { 'for' : oldFor.replace( '_'+ prevNum, '_'+ cmb.idNumber ) };
|
298 |
+
} else {
|
299 |
+
var oldName = $newInput.attr( 'name' );
|
300 |
+
// Replace 'name' attribute key
|
301 |
+
var newName = oldName ? oldName.replace( '['+ prevNum +']', '['+ cmb.idNumber +']' ) : '';
|
302 |
+
oldID = $newInput.attr( 'id' );
|
303 |
+
newID = oldID ? oldID.replace( '_'+ prevNum, '_'+ cmb.idNumber ) : '';
|
304 |
+
attrs = {
|
305 |
+
id: newID,
|
306 |
+
name: newName,
|
307 |
+
// value: '',
|
308 |
+
'data-iterator': cmb.idNumber,
|
309 |
+
};
|
310 |
+
}
|
311 |
+
|
312 |
+
$newInput
|
313 |
+
.removeClass( 'hasDatepicker' )
|
314 |
+
.attr( attrs ).val('');
|
315 |
+
|
316 |
+
// wysiwyg field
|
317 |
+
if ( isEditor ) {
|
318 |
+
// Get new wysiwyg ID
|
319 |
+
newID = newID ? oldID.replace( 'zx'+ prevNum, 'zx'+ cmb.idNumber ) : '';
|
320 |
+
// Empty the contents
|
321 |
+
$newInput.html('');
|
322 |
+
// Get wysiwyg field
|
323 |
+
var $wysiwyg = $newInput.parents( '.cmb-type-wysiwyg' );
|
324 |
+
// Remove extra mce divs
|
325 |
+
$wysiwyg.find('.mce-tinymce:not(:first-child)').remove();
|
326 |
+
// Replace id instances
|
327 |
+
var html = $wysiwyg.html().replace( new RegExp( oldID, 'g' ), newID );
|
328 |
+
// Update field html
|
329 |
+
$wysiwyg.html( html );
|
330 |
+
// Save ids for later to re-init tinymce
|
331 |
+
cmb.neweditor_id.push( { 'id': newID, 'old': oldID } );
|
332 |
+
}
|
333 |
+
|
334 |
+
cmb.$focus = cmb.$focus ? cmb.$focus : $newInput;
|
335 |
+
});
|
336 |
+
|
337 |
+
return this;
|
338 |
+
};
|
339 |
+
|
340 |
+
$.fn.newRowHousekeeping = function() {
|
341 |
+
var $row = $(this);
|
342 |
+
var $colorPicker = $row.find( '.wp-picker-container' );
|
343 |
+
var $list = $row.find( '.cmb_media_status' );
|
344 |
+
|
345 |
+
if ( $colorPicker.length ) {
|
346 |
+
// Need to clean-up colorpicker before appending
|
347 |
+
$colorPicker.each( function() {
|
348 |
+
var $td = $(this).parent();
|
349 |
+
$td.html( $td.find( 'input:text.cmb_colorpicker' ).attr('style', '') );
|
350 |
+
});
|
351 |
+
}
|
352 |
+
|
353 |
+
// Need to clean-up colorpicker before appending
|
354 |
+
if ( $list.length ) {
|
355 |
+
$list.empty();
|
356 |
+
}
|
357 |
+
|
358 |
+
return this;
|
359 |
+
};
|
360 |
+
|
361 |
+
cmb.afterRowInsert = function( $row ) {
|
362 |
+
if ( cmb.$focus ) {
|
363 |
+
cmb.$focus.focus();
|
364 |
+
}
|
365 |
+
|
366 |
+
var _prop;
|
367 |
+
|
368 |
+
// Need to re-init wp_editor instances
|
369 |
+
if ( cmb.neweditor_id.length ) {
|
370 |
+
var i;
|
371 |
+
for ( i = cmb.neweditor_id.length - 1; i >= 0; i-- ) {
|
372 |
+
var id = cmb.neweditor_id[i].id;
|
373 |
+
var old = cmb.neweditor_id[i].old;
|
374 |
+
|
375 |
+
if ( typeof( tinyMCEPreInit.mceInit[ id ] ) === 'undefined' ) {
|
376 |
+
var newSettings = jQuery.extend( {}, tinyMCEPreInit.mceInit[ old ] );
|
377 |
+
|
378 |
+
for ( _prop in newSettings ) {
|
379 |
+
if ( 'string' === typeof( newSettings[_prop] ) ) {
|
380 |
+
newSettings[_prop] = newSettings[_prop].replace( new RegExp( old, 'g' ), id );
|
381 |
+
}
|
382 |
+
}
|
383 |
+
tinyMCEPreInit.mceInit[ id ] = newSettings;
|
384 |
+
}
|
385 |
+
if ( typeof( tinyMCEPreInit.qtInit[ id ] ) === 'undefined' ) {
|
386 |
+
var newQTS = jQuery.extend( {}, tinyMCEPreInit.qtInit[ old ] );
|
387 |
+
for ( _prop in newQTS ) {
|
388 |
+
if ( 'string' === typeof( newQTS[_prop] ) ) {
|
389 |
+
newQTS[_prop] = newQTS[_prop].replace( new RegExp( old, 'g' ), id );
|
390 |
+
}
|
391 |
+
}
|
392 |
+
tinyMCEPreInit.qtInit[ id ] = newQTS;
|
393 |
+
}
|
394 |
+
tinyMCE.init({
|
395 |
+
id : tinyMCEPreInit.mceInit[ id ],
|
396 |
+
});
|
397 |
+
|
398 |
+
}
|
399 |
+
}
|
400 |
+
|
401 |
+
// Init pickers from new row
|
402 |
+
cmb.initPickers( $row.find('input:text.cmb_timepicker'), $row.find('input:text.cmb_datepicker'), $row.find('input:text.cmb_colorpicker') );
|
403 |
+
};
|
404 |
+
|
405 |
+
cmb.updateNameAttr = function () {
|
406 |
+
|
407 |
+
var $this = $(this);
|
408 |
+
var name = $this.attr( 'name' ); // get current name
|
409 |
+
|
410 |
+
// No name? bail
|
411 |
+
if ( typeof name === 'undefined' ) {
|
412 |
+
return false;
|
413 |
+
}
|
414 |
+
|
415 |
+
var prevNum = parseInt( $this.parents( '.repeatable-grouping' ).data( 'iterator' ) );
|
416 |
+
var newNum = prevNum - 1; // Subtract 1 to get new iterator number
|
417 |
+
|
418 |
+
// Update field name attributes so data is not orphaned when a row is removed and post is saved
|
419 |
+
var $newName = name.replace( '[' + prevNum + ']', '[' + newNum + ']' );
|
420 |
+
|
421 |
+
// New name with replaced iterator
|
422 |
+
$this.attr( 'name', $newName );
|
423 |
+
|
424 |
+
};
|
425 |
+
|
426 |
+
cmb.emptyValue = function( event, row ) {
|
427 |
+
$('input:not([type="button"]), textarea', row).val('');
|
428 |
+
};
|
429 |
+
|
430 |
+
cmb.addGroupRow = function( event ) {
|
431 |
+
|
432 |
+
event.preventDefault();
|
433 |
+
|
434 |
+
var $self = $(this);
|
435 |
+
var $table = $('#'+ $self.data('selector'));
|
436 |
+
var $oldRow = $table.find('.repeatable-grouping').last();
|
437 |
+
var prevNum = parseInt( $oldRow.data('iterator') );
|
438 |
+
cmb.idNumber = prevNum + 1;
|
439 |
+
var $row = $oldRow.clone();
|
440 |
+
|
441 |
+
$row.data( 'title', $self.data( 'grouptitle' ) ).newRowHousekeeping().cleanRow( prevNum, true );
|
442 |
+
|
443 |
+
// console.log( '$row.html()', $row.html() );
|
444 |
+
var $newRow = $( '<tr class="repeatable-grouping" data-iterator="'+ cmb.idNumber +'">'+ $row.html() +'</tr>' );
|
445 |
+
$oldRow.after( $newRow );
|
446 |
+
// console.log( '$newRow.html()', $row.html() );
|
447 |
+
|
448 |
+
cmb.afterRowInsert( $newRow );
|
449 |
+
|
450 |
+
if ( $table.find('.repeatable-grouping').length <= 1 ) {
|
451 |
+
$table.find('.remove-group-row').prop('disabled', true);
|
452 |
+
} else {
|
453 |
+
$table.find('.remove-group-row').removeAttr( 'disabled' );
|
454 |
+
}
|
455 |
+
|
456 |
+
$table.trigger( 'cmb_add_row', $newRow );
|
457 |
+
};
|
458 |
+
|
459 |
+
cmb.addAjaxRow = function( event ) {
|
460 |
+
|
461 |
+
event.preventDefault();
|
462 |
+
|
463 |
+
var $self = $(this);
|
464 |
+
var tableselector = '#'+ $self.data('selector');
|
465 |
+
var $table = $(tableselector);
|
466 |
+
var $emptyrow = $table.find('.empty-row');
|
467 |
+
var prevNum = parseInt( $emptyrow.find('[data-iterator]').data('iterator') );
|
468 |
+
cmb.idNumber = prevNum + 1;
|
469 |
+
var $row = $emptyrow.clone();
|
470 |
+
|
471 |
+
$row.newRowHousekeeping().cleanRow( prevNum );
|
472 |
+
|
473 |
+
$emptyrow.removeClass('empty-row').addClass('repeat-row');
|
474 |
+
$emptyrow.after( $row );
|
475 |
+
|
476 |
+
cmb.afterRowInsert( $row );
|
477 |
+
$table.trigger( 'cmb_add_row', $row );
|
478 |
+
};
|
479 |
+
|
480 |
+
cmb.removeGroupRow = function( event ) {
|
481 |
+
event.preventDefault();
|
482 |
+
var $self = $(this);
|
483 |
+
var $table = $('#'+ $self.data('selector'));
|
484 |
+
var $parent = $self.parents('.repeatable-grouping');
|
485 |
+
var noRows = $table.find('.repeatable-grouping').length;
|
486 |
+
|
487 |
+
// when a group is removed loop through all next groups and update fields names
|
488 |
+
$parent.nextAll( '.repeatable-grouping' ).find( cmb.repeatEls ).each( cmb.updateNameAttr );
|
489 |
+
|
490 |
+
if ( noRows > 1 ) {
|
491 |
+
$parent.remove();
|
492 |
+
if ( noRows < 3 ) {
|
493 |
+
$table.find('.remove-group-row').prop('disabled', true);
|
494 |
+
} else {
|
495 |
+
$table.find('.remove-group-row').prop('disabled', false);
|
496 |
+
}
|
497 |
+
$table.trigger( 'cmb_remove_row' );
|
498 |
+
}
|
499 |
+
};
|
500 |
+
|
501 |
+
cmb.removeAjaxRow = function( event ) {
|
502 |
+
event.preventDefault();
|
503 |
+
var $self = $(this);
|
504 |
+
var $parent = $self.parents('tr');
|
505 |
+
var $table = $self.parents('.cmb-repeat-table');
|
506 |
+
|
507 |
+
// cmb.log( 'number of tbodys', $table.length );
|
508 |
+
// cmb.log( 'number of trs', $('tr', $table).length );
|
509 |
+
if ( $table.find('tr').length > 1 ) {
|
510 |
+
if ( $parent.hasClass('empty-row') ) {
|
511 |
+
$parent.prev().addClass( 'empty-row' ).removeClass('repeat-row');
|
512 |
+
}
|
513 |
+
$self.parents('.cmb-repeat-table tr').remove();
|
514 |
+
$table.trigger( 'cmb_remove_row' );
|
515 |
+
}
|
516 |
+
};
|
517 |
+
|
518 |
+
cmb.shiftRows = function( event ) {
|
519 |
+
|
520 |
+
event.preventDefault();
|
521 |
+
|
522 |
+
var $self = $(this);
|
523 |
+
var $parent = $self.parents( '.repeatable-grouping' );
|
524 |
+
var $goto = $self.hasClass( 'move-up' ) ? $parent.prev( '.repeatable-grouping' ) : $parent.next( '.repeatable-grouping' );
|
525 |
+
|
526 |
+
if ( ! $goto.length ) {
|
527 |
+
return;
|
528 |
+
}
|
529 |
+
|
530 |
+
var inputVals = [];
|
531 |
+
// Loop this items fields
|
532 |
+
$parent.find( cmb.repeatEls ).each( function() {
|
533 |
+
var $element = $(this);
|
534 |
+
var val;
|
535 |
+
if ( $element.hasClass('cmb_media_status') ) {
|
536 |
+
// special case for image previews
|
537 |
+
val = $element.html();
|
538 |
+
} else if ( 'checkbox' === $element.attr('type') ) {
|
539 |
+
val = $element.is(':checked');
|
540 |
+
cmb.log( 'checked', val );
|
541 |
+
} else if ( 'select' === $element.prop('tagName') ) {
|
542 |
+
val = $element.is(':selected');
|
543 |
+
cmb.log( 'checked', val );
|
544 |
+
} else {
|
545 |
+
val = $element.val();
|
546 |
+
}
|
547 |
+
// Get all the current values per element
|
548 |
+
inputVals.push( { val: val, $: $element } );
|
549 |
+
});
|
550 |
+
// And swap them all
|
551 |
+
$goto.find( cmb.repeatEls ).each( function( index ) {
|
552 |
+
var $element = $(this);
|
553 |
+
var val;
|
554 |
+
|
555 |
+
if ( $element.hasClass('cmb_media_status') ) {
|
556 |
+
// special case for image previews
|
557 |
+
val = $element.html();
|
558 |
+
$element.html( inputVals[ index ]['val'] );
|
559 |
+
inputVals[ index ]['$'].html( val );
|
560 |
+
|
561 |
+
}
|
562 |
+
// handle checkbox swapping
|
563 |
+
else if ( 'checkbox' === $element.attr('type') ) {
|
564 |
+
inputVals[ index ]['$'].prop( 'checked', $element.is(':checked') );
|
565 |
+
$element.prop( 'checked', inputVals[ index ]['val'] );
|
566 |
+
}
|
567 |
+
// handle select swapping
|
568 |
+
else if ( 'select' === $element.prop('tagName') ) {
|
569 |
+
inputVals[ index ]['$'].prop( 'selected', $element.is(':selected') );
|
570 |
+
$element.prop( 'selected', inputVals[ index ]['val'] );
|
571 |
+
}
|
572 |
+
// handle normal input swapping
|
573 |
+
else {
|
574 |
+
inputVals[ index ]['$'].val( $element.val() );
|
575 |
+
$element.val( inputVals[ index ]['val'] );
|
576 |
+
}
|
577 |
+
});
|
578 |
+
};
|
579 |
+
|
580 |
+
/**
|
581 |
+
* @todo make work, always
|
582 |
+
*/
|
583 |
+
cmb.initPickers = function( $timePickers, $datePickers, $colorPickers ) {
|
584 |
+
// Initialize timepicker
|
585 |
+
cmb.initTimePickers( $timePickers );
|
586 |
+
|
587 |
+
// Initialize jQuery UI datepicker
|
588 |
+
cmb.initDatePickers( $datePickers );
|
589 |
+
|
590 |
+
// Initialize color picker
|
591 |
+
cmb.initColorPickers( $colorPickers );
|
592 |
+
};
|
593 |
+
|
594 |
+
cmb.initTimePickers = function( $selector ) {
|
595 |
+
if ( ! $selector.length ) {
|
596 |
+
return;
|
597 |
+
}
|
598 |
+
|
599 |
+
$selector.timePicker({
|
600 |
+
startTime: "00:00",
|
601 |
+
endTime: "23:59",
|
602 |
+
show24Hours: false,
|
603 |
+
separator: ':',
|
604 |
+
step: 30
|
605 |
+
});
|
606 |
+
};
|
607 |
+
|
608 |
+
cmb.initDatePickers = function( $selector ) {
|
609 |
+
if ( ! $selector.length ) {
|
610 |
+
return;
|
611 |
+
}
|
612 |
+
|
613 |
+
$selector.datepicker( "destroy" );
|
614 |
+
$selector.datepicker();
|
615 |
+
};
|
616 |
+
|
617 |
+
cmb.initColorPickers = function( $selector ) {
|
618 |
+
if ( ! $selector.length ) {
|
619 |
+
return;
|
620 |
+
}
|
621 |
+
if (typeof jQuery.wp === 'object' && typeof jQuery.wp.wpColorPicker === 'function') {
|
622 |
+
|
623 |
+
$selector.wpColorPicker();
|
624 |
+
|
625 |
+
} else {
|
626 |
+
$selector.each( function(i) {
|
627 |
+
$(this).after('<div id="picker-' + i + '" style="z-index: 1000; background: #EEE; border: 1px solid #CCC; position: absolute; display: block;"></div>');
|
628 |
+
$('#picker-' + i).hide().farbtastic($(this));
|
629 |
+
})
|
630 |
+
.focus( function() {
|
631 |
+
$(this).next().show();
|
632 |
+
})
|
633 |
+
.blur( function() {
|
634 |
+
$(this).next().hide();
|
635 |
+
});
|
636 |
+
}
|
637 |
+
};
|
638 |
+
|
639 |
+
cmb.maybeOembed = function( evt ) {
|
640 |
+
var $self = $(this);
|
641 |
+
var type = evt.type;
|
642 |
+
|
643 |
+
var m = {
|
644 |
+
focusout : function() {
|
645 |
+
setTimeout( function() {
|
646 |
+
// if it's been 2 seconds, hide our spinner
|
647 |
+
cmb.spinner( '.postbox table.cmb_metabox', true );
|
648 |
+
}, 2000);
|
649 |
+
},
|
650 |
+
keyup : function() {
|
651 |
+
var betw = function( min, max ) {
|
652 |
+
return ( evt.which <= max && evt.which >= min );
|
653 |
+
};
|
654 |
+
// Only Ajax on normal keystrokes
|
655 |
+
if ( betw( 48, 90 ) || betw( 96, 111 ) || betw( 8, 9 ) || evt.which === 187 || evt.which === 190 ) {
|
656 |
+
// fire our ajax function
|
657 |
+
cmb.doAjax( $self, evt);
|
658 |
+
}
|
659 |
+
},
|
660 |
+
paste : function() {
|
661 |
+
// paste event is fired before the value is filled, so wait a bit
|
662 |
+
setTimeout( function() { cmb.doAjax( $self ); }, 100);
|
663 |
+
}
|
664 |
+
};
|
665 |
+
m[type]();
|
666 |
+
|
667 |
+
};
|
668 |
+
|
669 |
+
/**
|
670 |
+
* Resize oEmbed videos to fit in their respective metaboxes
|
671 |
+
*/
|
672 |
+
cmb.resizeoEmbeds = function() {
|
673 |
+
cmb.metabox().each( function() {
|
674 |
+
var $self = $(this);
|
675 |
+
var $tableWrap = $self.parents('.inside');
|
676 |
+
if ( ! $tableWrap.length ) {
|
677 |
+
return true; // continue
|
678 |
+
}
|
679 |
+
|
680 |
+
// Calculate new width
|
681 |
+
var newWidth = Math.round(($tableWrap.width() * 0.82)*0.97) - 30;
|
682 |
+
if ( newWidth > 639 ) {
|
683 |
+
return true; // continue
|
684 |
+
}
|
685 |
+
|
686 |
+
var $embeds = $self.find('.cmb-type-oembed .embed_status');
|
687 |
+
var $children = $embeds.children().not('.cmb_remove_wrapper');
|
688 |
+
if ( ! $children.length ) {
|
689 |
+
return true; // continue
|
690 |
+
}
|
691 |
+
|
692 |
+
$children.each( function() {
|
693 |
+
var $self = $(this);
|
694 |
+
var iwidth = $self.width();
|
695 |
+
var iheight = $self.height();
|
696 |
+
var _newWidth = newWidth;
|
697 |
+
if ( $self.parents( '.repeat-row' ).length ) {
|
698 |
+
// Make room for our repeatable "remove" button column
|
699 |
+
_newWidth = newWidth - 91;
|
700 |
+
}
|
701 |
+
// Calc new height
|
702 |
+
var newHeight = Math.round((_newWidth * iheight)/iwidth);
|
703 |
+
$self.width(_newWidth).height(newHeight);
|
704 |
+
});
|
705 |
+
|
706 |
+
});
|
707 |
+
};
|
708 |
+
|
709 |
+
/**
|
710 |
+
* Safely log things if query var is set
|
711 |
+
* @since 1.0.0
|
712 |
+
*/
|
713 |
+
cmb.log = function() {
|
714 |
+
if ( l10n.script_debug && console && typeof console.log === 'function' ) {
|
715 |
+
console.log.apply(console, arguments);
|
716 |
+
}
|
717 |
+
};
|
718 |
+
|
719 |
+
cmb.spinner = function( $context, hide ) {
|
720 |
+
if ( hide ) {
|
721 |
+
$('.cmb-spinner', $context ).hide();
|
722 |
+
}
|
723 |
+
else {
|
724 |
+
$('.cmb-spinner', $context ).show();
|
725 |
+
}
|
726 |
+
};
|
727 |
+
|
728 |
+
// function for running our ajax
|
729 |
+
cmb.doAjax = function($obj) {
|
730 |
+
// get typed value
|
731 |
+
var oembed_url = $obj.val();
|
732 |
+
// only proceed if the field contains more than 6 characters
|
733 |
+
if ( oembed_url.length < 6 ) {
|
734 |
+
return;
|
735 |
+
}
|
736 |
+
|
737 |
+
// only proceed if the user has pasted, pressed a number, letter, or whitelisted characters
|
738 |
+
|
739 |
+
// get field id
|
740 |
+
var field_id = $obj.attr('id');
|
741 |
+
// get our inputs $context for pinpointing
|
742 |
+
var $context = $obj.parents('.cmb-repeat-table tr td');
|
743 |
+
$context = $context.length ? $context : $obj.parents('.cmb_metabox tr td');
|
744 |
+
|
745 |
+
var embed_container = $('.embed_status', $context);
|
746 |
+
var oembed_width = $obj.width();
|
747 |
+
var child_el = $(':first-child', embed_container);
|
748 |
+
|
749 |
+
// http://www.youtube.com/watch?v=dGG7aru2S6U
|
750 |
+
cmb.log( 'oembed_url', oembed_url, field_id );
|
751 |
+
oembed_width = ( embed_container.length && child_el.length ) ? child_el.width() : $obj.width();
|
752 |
+
|
753 |
+
// show our spinner
|
754 |
+
cmb.spinner( $context );
|
755 |
+
// clear out previous results
|
756 |
+
$('.embed_wrap', $context).html('');
|
757 |
+
// and run our ajax function
|
758 |
+
setTimeout( function() {
|
759 |
+
// if they haven't typed in 500 ms
|
760 |
+
if ( $('.cmb_oembed:focus').val() !== oembed_url ) {
|
761 |
+
return;
|
762 |
+
}
|
763 |
+
$.ajax({
|
764 |
+
type : 'post',
|
765 |
+
dataType : 'json',
|
766 |
+
url : l10n.ajaxurl,
|
767 |
+
data : {
|
768 |
+
'action': 'cmb_oembed_handler',
|
769 |
+
'oembed_url': oembed_url,
|
770 |
+
'oembed_width': oembed_width > 300 ? oembed_width : 300,
|
771 |
+
'field_id': field_id,
|
772 |
+
'object_id': $obj.data('objectid'),
|
773 |
+
'object_type': $obj.data('objecttype'),
|
774 |
+
'cmb_ajax_nonce': l10n.ajax_nonce
|
775 |
+
},
|
776 |
+
success: function(response) {
|
777 |
+
cmb.log( response );
|
778 |
+
// Make sure we have a response id
|
779 |
+
if ( typeof response.id === 'undefined' ) {
|
780 |
+
return;
|
781 |
+
}
|
782 |
+
|
783 |
+
// hide our spinner
|
784 |
+
cmb.spinner( $context, true );
|
785 |
+
// and populate our results from ajax response
|
786 |
+
$('.embed_wrap', $context).html(response.result);
|
787 |
+
}
|
788 |
+
});
|
789 |
+
|
790 |
+
}, 500);
|
791 |
+
};
|
792 |
+
|
793 |
+
$(document).ready(cmb.init);
|
794 |
+
|
795 |
+
return cmb;
|
796 |
+
|
797 |
+
})(window, document, jQuery);
|
lib/cmb_metaboxes/js/cmb.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
window.CMB=function(window,document,$){"use strict";var l10n=window.cmb_l10,setTimeout=window.setTimeout,cmb={formfield:"",idNumber:!1,file_frames:{},repeatEls:'input:not([type="button"]),select,textarea,.cmb_media_status'};return cmb.metabox=function(){return cmb.$metabox?cmb.$metabox:(cmb.$metabox=$("table.cmb_metabox"),cmb.$metabox)},cmb.init=function(){var $metabox=cmb.metabox(),$repeatGroup=$metabox.find(".repeatable-group");l10n.new_admin_style&&$metabox.find(".cmb-spinner img").hide(),cmb.initPickers($metabox.find("input:text.cmb_timepicker"),$metabox.find("input:text.cmb_datepicker"),$metabox.find("input:text.cmb_colorpicker")),$("#ui-datepicker-div").wrap('<div class="cmb_element" />'),$('<p><span class="button cmb-multicheck-toggle">'+l10n.check_toggle+"</span></p>").insertBefore("ul.cmb_checkbox_list"),$metabox.on("change",".cmb_upload_file",function(){cmb.formfield=$(this).attr("id"),$("#"+cmb.formfield+"_id").val("")}).on("click",".cmb-multicheck-toggle",cmb.toggleCheckBoxes).on("click",".cmb_upload_button",cmb.handleMedia).on("click",".cmb_remove_file_button",cmb.handleRemoveMedia).on("click",".add-group-row",cmb.addGroupRow).on("click",".add-row-button",cmb.addAjaxRow).on("click",".remove-group-row",cmb.removeGroupRow).on("click",".remove-row-button",cmb.removeAjaxRow).on("keyup paste focusout",".cmb_oembed",cmb.maybeOembed).on("cmb_remove_row",".repeatable-group",cmb.resetTitlesAndIterator),$repeatGroup.length&&$repeatGroup.filter(".sortable").each(function(){$(this).find(".remove-group-row").before('<a class="shift-rows move-up alignleft" href="#">'+l10n.up_arrow+'</a> <a class="shift-rows move-down alignleft" href="#">'+l10n.down_arrow+"</a>")}).on("click",".shift-rows",cmb.shiftRows).on("cmb_add_row",cmb.emptyValue),setTimeout(cmb.resizeoEmbeds,500),$(window).on("resize",cmb.resizeoEmbeds)},cmb.resetTitlesAndIterator=function(){$(".repeatable-group").each(function(){var $table=$(this);$table.find(".repeatable-grouping").each(function(rowindex){var $row=$(this);$row.data("iterator",rowindex),$row.find(".cmb-group-title h4").text($table.find(".add-group-row").data("grouptitle").replace("{#}",rowindex+1))})})},cmb.toggleCheckBoxes=function(event){event.preventDefault();var $self=$(this),$multicheck=$self.parents("td").find("input[type=checkbox]");$self.data("checked")?($multicheck.prop("checked",!1),$self.data("checked",!1)):($multicheck.prop("checked",!0),$self.data("checked",!0))},cmb.handleMedia=function(event){if(wp){event.preventDefault();var $metabox=cmb.metabox(),$self=$(this);cmb.formfield=$self.prev("input").attr("id");var $formfield=$("#"+cmb.formfield),formName=$formfield.attr("name"),uploadStatus=!0,attachment=!0,isList=$self.hasClass("cmb_upload_list");if(cmb.formfield in cmb.file_frames)return void cmb.file_frames[cmb.formfield].open();cmb.file_frames[cmb.formfield]=wp.media.frames.file_frame=wp.media({title:$metabox.find("label[for="+cmb.formfield+"]").text(),button:{text:l10n.upload_file},multiple:isList?!0:!1});var handlers={list:function(selection){attachment=selection.toJSON(),$formfield.val(attachment.url),$("#"+cmb.formfield+"_id").val(attachment.id);var fileGroup=[];$(attachment).each(function(){uploadStatus=this.type&&"image"===this.type?'<li class="img_status"><img width="50" height="50" src="'+this.url+'" class="attachment-50x50" alt="'+this.filename+'"><p><a href="#" class="cmb_remove_file_button" rel="'+cmb.formfield+"["+this.id+']">'+l10n.remove_image+'</a></p><input type="hidden" id="filelist-'+this.id+'" name="'+formName+"["+this.id+']" value="'+this.url+'"></li>':"<li>"+l10n.file+" <strong>"+this.filename+'</strong> (<a href="'+this.url+'" target="_blank" rel="external">'+l10n.download+'</a> / <a href="#" class="cmb_remove_file_button" rel="'+cmb.formfield+"["+this.id+']">'+l10n.remove_file+'</a>)<input type="hidden" id="filelist-'+this.id+'" name="'+formName+"["+this.id+']" value="'+this.url+'"></li>',fileGroup.push(uploadStatus)}),$(fileGroup).each(function(){$formfield.siblings(".cmb_media_status").slideDown().append(this)})},single:function(selection){attachment=selection.first().toJSON(),$formfield.val(attachment.url),$("#"+cmb.formfield+"_id").val(attachment.id),uploadStatus=attachment.type&&"image"===attachment.type?'<div class="img_status"><img style="max-width: 350px; width: 100%; height: auto;" src="'+attachment.url+'" alt="'+attachment.filename+'" title="'+attachment.filename+'" /><p><a href="#" class="cmb_remove_file_button" rel="'+cmb.formfield+'">'+l10n.remove_image+"</a></p></div>":l10n.file+" <strong>"+attachment.filename+'</strong> (<a href="'+attachment.url+'" target="_blank" rel="external">'+l10n.download+'</a> / <a href="#" class="cmb_remove_file_button" rel="'+cmb.formfield+'">'+l10n.remove_file+"</a>)",$formfield.siblings(".cmb_media_status").slideDown().html(uploadStatus)}};cmb.file_frames[cmb.formfield].on("select",function(){var selection=cmb.file_frames[cmb.formfield].state().get("selection"),type=isList?"list":"single";handlers[type](selection)}),cmb.file_frames[cmb.formfield].open()}},cmb.handleRemoveMedia=function(event){event.preventDefault();var $self=$(this);if($self.is(".attach_list .cmb_remove_file_button"))return $self.parents("li").remove(),!1;cmb.formfield=$self.attr("rel");var $container=$self.parents(".img_status");return cmb.metabox().find("input#"+cmb.formfield).val(""),cmb.metabox().find("input#"+cmb.formfield+"_id").val(""),$container.length?$container.html(""):$self.parents(".cmb_media_status").html(""),!1},$.fn.replaceText=function(b,a,c){return this.each(function(){var g,e,f=this.firstChild,d=[];if(f)do 3===f.nodeType&&(g=f.nodeValue,e=g.replace(b,a),e!==g&&(!c&&/</.test(e)?($(f).before(e),d.push(f)):f.nodeValue=e));while(f=f.nextSibling);d.length&&$(d).remove()})},$.fn.cleanRow=function(prevNum,group){var $self=$(this),$inputs=$self.find('input:not([type="button"]), select, textarea, label');return group&&$self.find(".cmb-repeat-table .repeat-row:not(:first-child)").remove(),cmb.$focus=!1,cmb.neweditor_id=[],$inputs.filter(":checked").removeAttr("checked"),$inputs.filter(":selected").removeAttr("selected"),$self.find(".cmb-group-title")&&$self.find(".cmb-group-title h4").text($self.data("title").replace("{#}",cmb.idNumber+1)),$inputs.each(function(){var newID,oldID,$newInput=$(this),isEditor=$newInput.hasClass("wp-editor-area"),oldFor=$newInput.attr("for"),attrs={};if(oldFor)attrs={"for":oldFor.replace("_"+prevNum,"_"+cmb.idNumber)};else{var oldName=$newInput.attr("name"),newName=oldName?oldName.replace("["+prevNum+"]","["+cmb.idNumber+"]"):"";oldID=$newInput.attr("id"),newID=oldID?oldID.replace("_"+prevNum,"_"+cmb.idNumber):"",attrs={id:newID,name:newName,"data-iterator":cmb.idNumber}}if($newInput.removeClass("hasDatepicker").attr(attrs).val(""),isEditor){newID=newID?oldID.replace("zx"+prevNum,"zx"+cmb.idNumber):"",$newInput.html("");var $wysiwyg=$newInput.parents(".cmb-type-wysiwyg");$wysiwyg.find(".mce-tinymce:not(:first-child)").remove();var html=$wysiwyg.html().replace(new RegExp(oldID,"g"),newID);$wysiwyg.html(html),cmb.neweditor_id.push({id:newID,old:oldID})}cmb.$focus=cmb.$focus?cmb.$focus:$newInput}),this},$.fn.newRowHousekeeping=function(){var $row=$(this),$colorPicker=$row.find(".wp-picker-container"),$list=$row.find(".cmb_media_status");return $colorPicker.length&&$colorPicker.each(function(){var $td=$(this).parent();$td.html($td.find("input:text.cmb_colorpicker").attr("style",""))}),$list.length&&$list.empty(),this},cmb.afterRowInsert=function($row){cmb.$focus&&cmb.$focus.focus();var _prop;if(cmb.neweditor_id.length){var i;for(i=cmb.neweditor_id.length-1;i>=0;i--){var id=cmb.neweditor_id[i].id,old=cmb.neweditor_id[i].old;if("undefined"==typeof tinyMCEPreInit.mceInit[id]){var newSettings=jQuery.extend({},tinyMCEPreInit.mceInit[old]);for(_prop in newSettings)"string"==typeof newSettings[_prop]&&(newSettings[_prop]=newSettings[_prop].replace(new RegExp(old,"g"),id));tinyMCEPreInit.mceInit[id]=newSettings}if("undefined"==typeof tinyMCEPreInit.qtInit[id]){var newQTS=jQuery.extend({},tinyMCEPreInit.qtInit[old]);for(_prop in newQTS)"string"==typeof newQTS[_prop]&&(newQTS[_prop]=newQTS[_prop].replace(new RegExp(old,"g"),id));tinyMCEPreInit.qtInit[id]=newQTS}tinyMCE.init({id:tinyMCEPreInit.mceInit[id]})}}cmb.initPickers($row.find("input:text.cmb_timepicker"),$row.find("input:text.cmb_datepicker"),$row.find("input:text.cmb_colorpicker"))},cmb.updateNameAttr=function(){var $this=$(this),name=$this.attr("name");if("undefined"==typeof name)return!1;var prevNum=parseInt($this.parents(".repeatable-grouping").data("iterator")),newNum=prevNum-1,$newName=name.replace("["+prevNum+"]","["+newNum+"]");$this.attr("name",$newName)},cmb.emptyValue=function(event,row){$('input:not([type="button"]), textarea',row).val("")},cmb.addGroupRow=function(event){event.preventDefault();var $self=$(this),$table=$("#"+$self.data("selector")),$oldRow=$table.find(".repeatable-grouping").last(),prevNum=parseInt($oldRow.data("iterator"));cmb.idNumber=prevNum+1;var $row=$oldRow.clone();$row.data("title",$self.data("grouptitle")).newRowHousekeeping().cleanRow(prevNum,!0);var $newRow=$('<tr class="repeatable-grouping" data-iterator="'+cmb.idNumber+'">'+$row.html()+"</tr>");$oldRow.after($newRow),cmb.afterRowInsert($newRow),$table.find(".repeatable-grouping").length<=1?$table.find(".remove-group-row").prop("disabled",!0):$table.find(".remove-group-row").removeAttr("disabled"),$table.trigger("cmb_add_row",$newRow)},cmb.addAjaxRow=function(event){event.preventDefault();var $self=$(this),tableselector="#"+$self.data("selector"),$table=$(tableselector),$emptyrow=$table.find(".empty-row"),prevNum=parseInt($emptyrow.find("[data-iterator]").data("iterator"));cmb.idNumber=prevNum+1;var $row=$emptyrow.clone();$row.newRowHousekeeping().cleanRow(prevNum),$emptyrow.removeClass("empty-row").addClass("repeat-row"),$emptyrow.after($row),cmb.afterRowInsert($row),$table.trigger("cmb_add_row",$row)},cmb.removeGroupRow=function(event){event.preventDefault();var $self=$(this),$table=$("#"+$self.data("selector")),$parent=$self.parents(".repeatable-grouping"),noRows=$table.find(".repeatable-grouping").length;$parent.nextAll(".repeatable-grouping").find(cmb.repeatEls).each(cmb.updateNameAttr),noRows>1&&($parent.remove(),3>noRows?$table.find(".remove-group-row").prop("disabled",!0):$table.find(".remove-group-row").prop("disabled",!1),$table.trigger("cmb_remove_row"))},cmb.removeAjaxRow=function(event){event.preventDefault();var $self=$(this),$parent=$self.parents("tr"),$table=$self.parents(".cmb-repeat-table");$table.find("tr").length>1&&($parent.hasClass("empty-row")&&$parent.prev().addClass("empty-row").removeClass("repeat-row"),$self.parents(".cmb-repeat-table tr").remove(),$table.trigger("cmb_remove_row"))},cmb.shiftRows=function(event){event.preventDefault();var $self=$(this),$parent=$self.parents(".repeatable-grouping"),$goto=$self.hasClass("move-up")?$parent.prev(".repeatable-grouping"):$parent.next(".repeatable-grouping");if($goto.length){var inputVals=[];$parent.find(cmb.repeatEls).each(function(){var val,$element=$(this);$element.hasClass("cmb_media_status")?val=$element.html():"checkbox"===$element.attr("type")?(val=$element.is(":checked"),cmb.log("checked",val)):"select"===$element.prop("tagName")?(val=$element.is(":selected"),cmb.log("checked",val)):val=$element.val(),inputVals.push({val:val,$:$element})}),$goto.find(cmb.repeatEls).each(function(index){var val,$element=$(this);$element.hasClass("cmb_media_status")?(val=$element.html(),$element.html(inputVals[index].val),inputVals[index].$.html(val)):"checkbox"===$element.attr("type")?(inputVals[index].$.prop("checked",$element.is(":checked")),$element.prop("checked",inputVals[index].val)):"select"===$element.prop("tagName")?(inputVals[index].$.prop("selected",$element.is(":selected")),$element.prop("selected",inputVals[index].val)):(inputVals[index].$.val($element.val()),$element.val(inputVals[index].val))})}},cmb.initPickers=function($timePickers,$datePickers,$colorPickers){cmb.initTimePickers($timePickers),cmb.initDatePickers($datePickers),cmb.initColorPickers($colorPickers)},cmb.initTimePickers=function($selector){$selector.length&&$selector.timePicker({startTime:"00:00",endTime:"23:59",show24Hours:!1,separator:":",step:30})},cmb.initDatePickers=function($selector){$selector.length&&($selector.datepicker("destroy"),$selector.datepicker())},cmb.initColorPickers=function($selector){$selector.length&&("object"==typeof jQuery.wp&&"function"==typeof jQuery.wp.wpColorPicker?$selector.wpColorPicker():$selector.each(function(i){$(this).after('<div id="picker-'+i+'" style="z-index: 1000; background: #EEE; border: 1px solid #CCC; position: absolute; display: block;"></div>'),$("#picker-"+i).hide().farbtastic($(this))}).focus(function(){$(this).next().show()}).blur(function(){$(this).next().hide()}))},cmb.maybeOembed=function(evt){var $self=$(this),type=evt.type,m={focusout:function(){setTimeout(function(){cmb.spinner(".postbox table.cmb_metabox",!0)},2e3)},keyup:function(){var betw=function(min,max){return evt.which<=max&&evt.which>=min};(betw(48,90)||betw(96,111)||betw(8,9)||187===evt.which||190===evt.which)&&cmb.doAjax($self,evt)},paste:function(){setTimeout(function(){cmb.doAjax($self)},100)}};m[type]()},cmb.resizeoEmbeds=function(){cmb.metabox().each(function(){var $self=$(this),$tableWrap=$self.parents(".inside");if(!$tableWrap.length)return!0;var newWidth=Math.round(.82*$tableWrap.width()*.97)-30;if(newWidth>639)return!0;var $embeds=$self.find(".cmb-type-oembed .embed_status"),$children=$embeds.children().not(".cmb_remove_wrapper");return $children.length?void $children.each(function(){var $self=$(this),iwidth=$self.width(),iheight=$self.height(),_newWidth=newWidth;$self.parents(".repeat-row").length&&(_newWidth=newWidth-91);var newHeight=Math.round(_newWidth*iheight/iwidth);$self.width(_newWidth).height(newHeight)}):!0})},cmb.log=function(){l10n.script_debug&&console&&"function"==typeof console.log&&console.log.apply(console,arguments)},cmb.spinner=function($context,hide){hide?$(".cmb-spinner",$context).hide():$(".cmb-spinner",$context).show()},cmb.doAjax=function($obj){var oembed_url=$obj.val();if(!(oembed_url.length<6)){var field_id=$obj.attr("id"),$context=$obj.parents(".cmb-repeat-table tr td");$context=$context.length?$context:$obj.parents(".cmb_metabox tr td");var embed_container=$(".embed_status",$context),oembed_width=$obj.width(),child_el=$(":first-child",embed_container);cmb.log("oembed_url",oembed_url,field_id),oembed_width=embed_container.length&&child_el.length?child_el.width():$obj.width(),cmb.spinner($context),$(".embed_wrap",$context).html(""),setTimeout(function(){$(".cmb_oembed:focus").val()===oembed_url&&$.ajax({type:"post",dataType:"json",url:l10n.ajaxurl,data:{action:"cmb_oembed_handler",oembed_url:oembed_url,oembed_width:oembed_width>300?oembed_width:300,field_id:field_id,object_id:$obj.data("objectid"),object_type:$obj.data("objecttype"),cmb_ajax_nonce:l10n.ajax_nonce},success:function(response){cmb.log(response),"undefined"!=typeof response.id&&(cmb.spinner($context,!0),$(".embed_wrap",$context).html(response.result))}})},500)}},$(document).ready(cmb.init),cmb}(window,document,jQuery);
|
lib/cmb_metaboxes/js/jquery.datePicker.min.js
ADDED
@@ -0,0 +1,2038 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*!
|
2 |
+
* jQuery UI Datepicker 1.10.4
|
3 |
+
* http://jqueryui.com
|
4 |
+
*
|
5 |
+
* Copyright 2014 jQuery Foundation and other contributors
|
6 |
+
* Released under the MIT license.
|
7 |
+
* http://jquery.org/license
|
8 |
+
*
|
9 |
+
* http://api.jqueryui.com/datepicker/
|
10 |
+
*
|
11 |
+
* Depends:
|
12 |
+
* jquery.ui.core.js
|
13 |
+
*/
|
14 |
+
(function( $, undefined ) {
|
15 |
+
|
16 |
+
$.extend($.ui, { datepicker: { version: "1.10.4" } });
|
17 |
+
|
18 |
+
var PROP_NAME = "datepicker",
|
19 |
+
instActive;
|
20 |
+
|
21 |
+
/* Date picker manager.
|
22 |
+
Use the singleton instance of this class, $.datepicker, to interact with the date picker.
|
23 |
+
Settings for (groups of) date pickers are maintained in an instance object,
|
24 |
+
allowing multiple different settings on the same page. */
|
25 |
+
|
26 |
+
function Datepicker() {
|
27 |
+
this._curInst = null; // The current instance in use
|
28 |
+
this._keyEvent = false; // If the last event was a key event
|
29 |
+
this._disabledInputs = []; // List of date picker inputs that have been disabled
|
30 |
+
this._datepickerShowing = false; // True if the popup picker is showing , false if not
|
31 |
+
this._inDialog = false; // True if showing within a "dialog", false if not
|
32 |
+
this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
|
33 |
+
this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
|
34 |
+
this._appendClass = "ui-datepicker-append"; // The name of the append marker class
|
35 |
+
this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
|
36 |
+
this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
|
37 |
+
this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
|
38 |
+
this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
|
39 |
+
this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
|
40 |
+
this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
|
41 |
+
this.regional = []; // Available regional settings, indexed by language code
|
42 |
+
this.regional[""] = { // Default regional settings
|
43 |
+
closeText: "Done", // Display text for close link
|
44 |
+
prevText: "Prev", // Display text for previous month link
|
45 |
+
nextText: "Next", // Display text for next month link
|
46 |
+
currentText: "Today", // Display text for current month link
|
47 |
+
monthNames: ["January","February","March","April","May","June",
|
48 |
+
"July","August","September","October","November","December"], // Names of months for drop-down and formatting
|
49 |
+
monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
|
50 |
+
dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
|
51 |
+
dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
|
52 |
+
dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
|
53 |
+
weekHeader: "Wk", // Column header for week of the year
|
54 |
+
dateFormat: "mm/dd/yy", // See format options on parseDate
|
55 |
+
firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
|
56 |
+
isRTL: false, // True if right-to-left language, false if left-to-right
|
57 |
+
showMonthAfterYear: false, // True if the year select precedes month, false for month then year
|
58 |
+
yearSuffix: "" // Additional text to append to the year in the month headers
|
59 |
+
};
|
60 |
+
this._defaults = { // Global defaults for all the date picker instances
|
61 |
+
showOn: "focus", // "focus" for popup on focus,
|
62 |
+
// "button" for trigger button, or "both" for either
|
63 |
+
showAnim: "fadeIn", // Name of jQuery animation for popup
|
64 |
+
showOptions: {}, // Options for enhanced animations
|
65 |
+
defaultDate: null, // Used when field is blank: actual date,
|
66 |
+
// +/-number for offset from today, null for today
|
67 |
+
appendText: "", // Display text following the input box, e.g. showing the format
|
68 |
+
buttonText: "...", // Text for trigger button
|
69 |
+
buttonImage: "", // URL for trigger button image
|
70 |
+
buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
|
71 |
+
hideIfNoPrevNext: false, // True to hide next/previous month links
|
72 |
+
// if not applicable, false to just disable them
|
73 |
+
navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
|
74 |
+
gotoCurrent: false, // True if today link goes back to current selection instead
|
75 |
+
changeMonth: false, // True if month can be selected directly, false if only prev/next
|
76 |
+
changeYear: false, // True if year can be selected directly, false if only prev/next
|
77 |
+
yearRange: "c-10:c+10", // Range of years to display in drop-down,
|
78 |
+
// either relative to today's year (-nn:+nn), relative to currently displayed year
|
79 |
+
// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
|
80 |
+
showOtherMonths: false, // True to show dates in other months, false to leave blank
|
81 |
+
selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
|
82 |
+
showWeek: false, // True to show week of the year, false to not show it
|
83 |
+
calculateWeek: this.iso8601Week, // How to calculate the week of the year,
|
84 |
+
// takes a Date and returns the number of the week for it
|
85 |
+
shortYearCutoff: "+10", // Short year values < this are in the current century,
|
86 |
+
// > this are in the previous century,
|
87 |
+
// string value starting with "+" for current year + value
|
88 |
+
minDate: null, // The earliest selectable date, or null for no limit
|
89 |
+
maxDate: null, // The latest selectable date, or null for no limit
|
90 |
+
duration: "fast", // Duration of display/closure
|
91 |
+
beforeShowDay: null, // Function that takes a date and returns an array with
|
92 |
+
// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
|
93 |
+
// [2] = cell title (optional), e.g. $.datepicker.noWeekends
|
94 |
+
beforeShow: null, // Function that takes an input field and
|
95 |
+
// returns a set of custom settings for the date picker
|
96 |
+
onSelect: null, // Define a callback function when a date is selected
|
97 |
+
onChangeMonthYear: null, // Define a callback function when the month or year is changed
|
98 |
+
onClose: null, // Define a callback function when the datepicker is closed
|
99 |
+
numberOfMonths: 1, // Number of months to show at a time
|
100 |
+
showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
|
101 |
+
stepMonths: 1, // Number of months to step back/forward
|
102 |
+
stepBigMonths: 12, // Number of months to step back/forward for the big links
|
103 |
+
altField: "", // Selector for an alternate field to store selected dates into
|
104 |
+
altFormat: "", // The date format to use for the alternate field
|
105 |
+
constrainInput: true, // The input is constrained by the current date format
|
106 |
+
showButtonPanel: false, // True to show button panel, false to not show it
|
107 |
+
autoSize: false, // True to size the input for the date format, false to leave as is
|
108 |
+
disabled: false // The initial disabled state
|
109 |
+
};
|
110 |
+
$.extend(this._defaults, this.regional[""]);
|
111 |
+
this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
|
112 |
+
}
|
113 |
+
|
114 |
+
$.extend(Datepicker.prototype, {
|
115 |
+
/* Class name added to elements to indicate already configured with a date picker. */
|
116 |
+
markerClassName: "hasDatepicker",
|
117 |
+
|
118 |
+
//Keep track of the maximum number of rows displayed (see #7043)
|
119 |
+
maxRows: 4,
|
120 |
+
|
121 |
+
// TODO rename to "widget" when switching to widget factory
|
122 |
+
_widgetDatepicker: function() {
|
123 |
+
return this.dpDiv;
|
124 |
+
},
|
125 |
+
|
126 |
+
/* Override the default settings for all instances of the date picker.
|
127 |
+
* @param settings object - the new settings to use as defaults (anonymous object)
|
128 |
+
* @return the manager object
|
129 |
+
*/
|
130 |
+
setDefaults: function(settings) {
|
131 |
+
extendRemove(this._defaults, settings || {});
|
132 |
+
return this;
|
133 |
+
},
|
134 |
+
|
135 |
+
/* Attach the date picker to a jQuery selection.
|
136 |
+
* @param target element - the target input field or division or span
|
137 |
+
* @param settings object - the new settings to use for this date picker instance (anonymous)
|
138 |
+
*/
|
139 |
+
_attachDatepicker: function(target, settings) {
|
140 |
+
var nodeName, inline, inst;
|
141 |
+
nodeName = target.nodeName.toLowerCase();
|
142 |
+
inline = (nodeName === "div" || nodeName === "span");
|
143 |
+
if (!target.id) {
|
144 |
+
this.uuid += 1;
|
145 |
+
target.id = "dp" + this.uuid;
|
146 |
+
}
|
147 |
+
inst = this._newInst($(target), inline);
|
148 |
+
inst.settings = $.extend({}, settings || {});
|
149 |
+
if (nodeName === "input") {
|
150 |
+
this._connectDatepicker(target, inst);
|
151 |
+
} else if (inline) {
|
152 |
+
this._inlineDatepicker(target, inst);
|
153 |
+
}
|
154 |
+
},
|
155 |
+
|
156 |
+
/* Create a new instance object. */
|
157 |
+
_newInst: function(target, inline) {
|
158 |
+
var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
|
159 |
+
return {id: id, input: target, // associated target
|
160 |
+
selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
|
161 |
+
drawMonth: 0, drawYear: 0, // month being drawn
|
162 |
+
inline: inline, // is datepicker inline or not
|
163 |
+
dpDiv: (!inline ? this.dpDiv : // presentation div
|
164 |
+
bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
|
165 |
+
},
|
166 |
+
|
167 |
+
/* Attach the date picker to an input field. */
|
168 |
+
_connectDatepicker: function(target, inst) {
|
169 |
+
var input = $(target);
|
170 |
+
inst.append = $([]);
|
171 |
+
inst.trigger = $([]);
|
172 |
+
if (input.hasClass(this.markerClassName)) {
|
173 |
+
return;
|
174 |
+
}
|
175 |
+
this._attachments(input, inst);
|
176 |
+
input.addClass(this.markerClassName).keydown(this._doKeyDown).
|
177 |
+
keypress(this._doKeyPress).keyup(this._doKeyUp);
|
178 |
+
this._autoSize(inst);
|
179 |
+
$.data(target, PROP_NAME, inst);
|
180 |
+
//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
|
181 |
+
if( inst.settings.disabled ) {
|
182 |
+
this._disableDatepicker( target );
|
183 |
+
}
|
184 |
+
},
|
185 |
+
|
186 |
+
/* Make attachments based on settings. */
|
187 |
+
_attachments: function(input, inst) {
|
188 |
+
var showOn, buttonText, buttonImage,
|
189 |
+
appendText = this._get(inst, "appendText"),
|
190 |
+
isRTL = this._get(inst, "isRTL");
|
191 |
+
|
192 |
+
if (inst.append) {
|
193 |
+
inst.append.remove();
|
194 |
+
}
|
195 |
+
if (appendText) {
|
196 |
+
inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
|
197 |
+
input[isRTL ? "before" : "after"](inst.append);
|
198 |
+
}
|
199 |
+
|
200 |
+
input.unbind("focus", this._showDatepicker);
|
201 |
+
|
202 |
+
if (inst.trigger) {
|
203 |
+
inst.trigger.remove();
|
204 |
+
}
|
205 |
+
|
206 |
+
showOn = this._get(inst, "showOn");
|
207 |
+
if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
|
208 |
+
input.focus(this._showDatepicker);
|
209 |
+
}
|
210 |
+
if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
|
211 |
+
buttonText = this._get(inst, "buttonText");
|
212 |
+
buttonImage = this._get(inst, "buttonImage");
|
213 |
+
inst.trigger = $(this._get(inst, "buttonImageOnly") ?
|
214 |
+
$("<img/>").addClass(this._triggerClass).
|
215 |
+
attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
|
216 |
+
$("<button type='button'></button>").addClass(this._triggerClass).
|
217 |
+
html(!buttonImage ? buttonText : $("<img/>").attr(
|
218 |
+
{ src:buttonImage, alt:buttonText, title:buttonText })));
|
219 |
+
input[isRTL ? "before" : "after"](inst.trigger);
|
220 |
+
inst.trigger.click(function() {
|
221 |
+
if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
|
222 |
+
$.datepicker._hideDatepicker();
|
223 |
+
} else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
|
224 |
+
$.datepicker._hideDatepicker();
|
225 |
+
$.datepicker._showDatepicker(input[0]);
|
226 |
+
} else {
|
227 |
+
$.datepicker._showDatepicker(input[0]);
|
228 |
+
}
|
229 |
+
return false;
|
230 |
+
});
|
231 |
+
}
|
232 |
+
},
|
233 |
+
|
234 |
+
/* Apply the maximum length for the date format. */
|
235 |
+
_autoSize: function(inst) {
|
236 |
+
if (this._get(inst, "autoSize") && !inst.inline) {
|
237 |
+
var findMax, max, maxI, i,
|
238 |
+
date = new Date(2009, 12 - 1, 20), // Ensure double digits
|
239 |
+
dateFormat = this._get(inst, "dateFormat");
|
240 |
+
|
241 |
+
if (dateFormat.match(/[DM]/)) {
|
242 |
+
findMax = function(names) {
|
243 |
+
max = 0;
|
244 |
+
maxI = 0;
|
245 |
+
for (i = 0; i < names.length; i++) {
|
246 |
+
if (names[i].length > max) {
|
247 |
+
max = names[i].length;
|
248 |
+
maxI = i;
|
249 |
+
}
|
250 |
+
}
|
251 |
+
return maxI;
|
252 |
+
};
|
253 |
+
date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
|
254 |
+
"monthNames" : "monthNamesShort"))));
|
255 |
+
date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
|
256 |
+
"dayNames" : "dayNamesShort"))) + 20 - date.getDay());
|
257 |
+
}
|
258 |
+
inst.input.attr("size", this._formatDate(inst, date).length);
|
259 |
+
}
|
260 |
+
},
|
261 |
+
|
262 |
+
/* Attach an inline date picker to a div. */
|
263 |
+
_inlineDatepicker: function(target, inst) {
|
264 |
+
var divSpan = $(target);
|
265 |
+
if (divSpan.hasClass(this.markerClassName)) {
|
266 |
+
return;
|
267 |
+
}
|
268 |
+
divSpan.addClass(this.markerClassName).append(inst.dpDiv);
|
269 |
+
$.data(target, PROP_NAME, inst);
|
270 |
+
this._setDate(inst, this._getDefaultDate(inst), true);
|
271 |
+
this._updateDatepicker(inst);
|
272 |
+
this._updateAlternate(inst);
|
273 |
+
//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
|
274 |
+
if( inst.settings.disabled ) {
|
275 |
+
this._disableDatepicker( target );
|
276 |
+
}
|
277 |
+
// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
|
278 |
+
// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
|
279 |
+
inst.dpDiv.css( "display", "block" );
|
280 |
+
},
|
281 |
+
|
282 |
+
/* Pop-up the date picker in a "dialog" box.
|
283 |
+
* @param input element - ignored
|
284 |
+
* @param date string or Date - the initial date to display
|
285 |
+
* @param onSelect function - the function to call when a date is selected
|
286 |
+
* @param settings object - update the dialog date picker instance's settings (anonymous object)
|
287 |
+
* @param pos int[2] - coordinates for the dialog's position within the screen or
|
288 |
+
* event - with x/y coordinates or
|
289 |
+
* leave empty for default (screen centre)
|
290 |
+
* @return the manager object
|
291 |
+
*/
|
292 |
+
_dialogDatepicker: function(input, date, onSelect, settings, pos) {
|
293 |
+
var id, browserWidth, browserHeight, scrollX, scrollY,
|
294 |
+
inst = this._dialogInst; // internal instance
|
295 |
+
|
296 |
+
if (!inst) {
|
297 |
+
this.uuid += 1;
|
298 |
+
id = "dp" + this.uuid;
|
299 |
+
this._dialogInput = $("<input type='text' id='" + id +
|
300 |
+
"' style='position: absolute; top: -100px; width: 0px;'/>");
|
301 |
+
this._dialogInput.keydown(this._doKeyDown);
|
302 |
+
$("body").append(this._dialogInput);
|
303 |
+
inst = this._dialogInst = this._newInst(this._dialogInput, false);
|
304 |
+
inst.settings = {};
|
305 |
+
$.data(this._dialogInput[0], PROP_NAME, inst);
|
306 |
+
}
|
307 |
+
extendRemove(inst.settings, settings || {});
|
308 |
+
date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
|
309 |
+
this._dialogInput.val(date);
|
310 |
+
|
311 |
+
this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
|
312 |
+
if (!this._pos) {
|
313 |
+
browserWidth = document.documentElement.clientWidth;
|
314 |
+
browserHeight = document.documentElement.clientHeight;
|
315 |
+
scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
|
316 |
+
scrollY = document.documentElement.scrollTop || document.body.scrollTop;
|
317 |
+
this._pos = // should use actual width/height below
|
318 |
+
[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
|
319 |
+
}
|
320 |
+
|
321 |
+
// move input on screen for focus, but hidden behind dialog
|
322 |
+
this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
|
323 |
+
inst.settings.onSelect = onSelect;
|
324 |
+
this._inDialog = true;
|
325 |
+
this.dpDiv.addClass(this._dialogClass);
|
326 |
+
this._showDatepicker(this._dialogInput[0]);
|
327 |
+
if ($.blockUI) {
|
328 |
+
$.blockUI(this.dpDiv);
|
329 |
+
}
|
330 |
+
$.data(this._dialogInput[0], PROP_NAME, inst);
|
331 |
+
return this;
|
332 |
+
},
|
333 |
+
|
334 |
+
/* Detach a datepicker from its control.
|
335 |
+
* @param target element - the target input field or division or span
|
336 |
+
*/
|
337 |
+
_destroyDatepicker: function(target) {
|
338 |
+
var nodeName,
|
339 |
+
$target = $(target),
|
340 |
+
inst = $.data(target, PROP_NAME);
|
341 |
+
|
342 |
+
if (!$target.hasClass(this.markerClassName)) {
|
343 |
+
return;
|
344 |
+
}
|
345 |
+
|
346 |
+
nodeName = target.nodeName.toLowerCase();
|
347 |
+
$.removeData(target, PROP_NAME);
|
348 |
+
if (nodeName === "input") {
|
349 |
+
inst.append.remove();
|
350 |
+
inst.trigger.remove();
|
351 |
+
$target.removeClass(this.markerClassName).
|
352 |
+
unbind("focus", this._showDatepicker).
|
353 |
+
unbind("keydown", this._doKeyDown).
|
354 |
+
unbind("keypress", this._doKeyPress).
|
355 |
+
unbind("keyup", this._doKeyUp);
|
356 |
+
} else if (nodeName === "div" || nodeName === "span") {
|
357 |
+
$target.removeClass(this.markerClassName).empty();
|
358 |
+
}
|
359 |
+
},
|
360 |
+
|
361 |
+
/* Enable the date picker to a jQuery selection.
|
362 |
+
* @param target element - the target input field or division or span
|
363 |
+
*/
|
364 |
+
_enableDatepicker: function(target) {
|
365 |
+
var nodeName, inline,
|
366 |
+
$target = $(target),
|
367 |
+
inst = $.data(target, PROP_NAME);
|
368 |
+
|
369 |
+
if (!$target.hasClass(this.markerClassName)) {
|
370 |
+
return;
|
371 |
+
}
|
372 |
+
|
373 |
+
nodeName = target.nodeName.toLowerCase();
|
374 |
+
if (nodeName === "input") {
|
375 |
+
target.disabled = false;
|
376 |
+
inst.trigger.filter("button").
|
377 |
+
each(function() { this.disabled = false; }).end().
|
378 |
+
filter("img").css({opacity: "1.0", cursor: ""});
|
379 |
+
} else if (nodeName === "div" || nodeName === "span") {
|
380 |
+
inline = $target.children("." + this._inlineClass);
|
381 |
+
inline.children().removeClass("ui-state-disabled");
|
382 |
+
inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
|
383 |
+
prop("disabled", false);
|
384 |
+
}
|
385 |
+
this._disabledInputs = $.map(this._disabledInputs,
|
386 |
+
function(value) { return (value === target ? null : value); }); // delete entry
|
387 |
+
},
|
388 |
+
|
389 |
+
/* Disable the date picker to a jQuery selection.
|
390 |
+
* @param target element - the target input field or division or span
|
391 |
+
*/
|
392 |
+
_disableDatepicker: function(target) {
|
393 |
+
var nodeName, inline,
|
394 |
+
$target = $(target),
|
395 |
+
inst = $.data(target, PROP_NAME);
|
396 |
+
|
397 |
+
if (!$target.hasClass(this.markerClassName)) {
|
398 |
+
return;
|
399 |
+
}
|
400 |
+
|
401 |
+
nodeName = target.nodeName.toLowerCase();
|
402 |
+
if (nodeName === "input") {
|
403 |
+
target.disabled = true;
|
404 |
+
inst.trigger.filter("button").
|
405 |
+
each(function() { this.disabled = true; }).end().
|
406 |
+
filter("img").css({opacity: "0.5", cursor: "default"});
|
407 |
+
} else if (nodeName === "div" || nodeName === "span") {
|
408 |
+
inline = $target.children("." + this._inlineClass);
|
409 |
+
inline.children().addClass("ui-state-disabled");
|
410 |
+
inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
|
411 |
+
prop("disabled", true);
|
412 |
+
}
|
413 |
+
this._disabledInputs = $.map(this._disabledInputs,
|
414 |
+
function(value) { return (value === target ? null : value); }); // delete entry
|
415 |
+
this._disabledInputs[this._disabledInputs.length] = target;
|
416 |
+
},
|
417 |
+
|
418 |
+
/* Is the first field in a jQuery collection disabled as a datepicker?
|
419 |
+
* @param target element - the target input field or division or span
|
420 |
+
* @return boolean - true if disabled, false if enabled
|
421 |
+
*/
|
422 |
+
_isDisabledDatepicker: function(target) {
|
423 |
+
if (!target) {
|
424 |
+
return false;
|
425 |
+
}
|
426 |
+
for (var i = 0; i < this._disabledInputs.length; i++) {
|
427 |
+
if (this._disabledInputs[i] === target) {
|
428 |
+
return true;
|
429 |
+
}
|
430 |
+
}
|
431 |
+
return false;
|
432 |
+
},
|
433 |
+
|
434 |
+
/* Retrieve the instance data for the target control.
|
435 |
+
* @param target element - the target input field or division or span
|
436 |
+
* @return object - the associated instance data
|
437 |
+
* @throws error if a jQuery problem getting data
|
438 |
+
*/
|
439 |
+
_getInst: function(target) {
|
440 |
+
try {
|
441 |
+
return $.data(target, PROP_NAME);
|
442 |
+
}
|
443 |
+
catch (err) {
|
444 |
+
throw "Missing instance data for this datepicker";
|
445 |
+
}
|
446 |
+
},
|
447 |
+
|
448 |
+
/* Update or retrieve the settings for a date picker attached to an input field or division.
|
449 |
+
* @param target element - the target input field or division or span
|
450 |
+
* @param name object - the new settings to update or
|
451 |
+
* string - the name of the setting to change or retrieve,
|
452 |
+
* when retrieving also "all" for all instance settings or
|
453 |
+
* "defaults" for all global defaults
|
454 |
+
* @param value any - the new value for the setting
|
455 |
+
* (omit if above is an object or to retrieve a value)
|
456 |
+
*/
|
457 |
+
_optionDatepicker: function(target, name, value) {
|
458 |
+
var settings, date, minDate, maxDate,
|
459 |
+
inst = this._getInst(target);
|
460 |
+
|
461 |
+
if (arguments.length === 2 && typeof name === "string") {
|
462 |
+
return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
|
463 |
+
(inst ? (name === "all" ? $.extend({}, inst.settings) :
|
464 |
+
this._get(inst, name)) : null));
|
465 |
+
}
|
466 |
+
|
467 |
+
settings = name || {};
|
468 |
+
if (typeof name === "string") {
|
469 |
+
settings = {};
|
470 |
+
settings[name] = value;
|
471 |
+
}
|
472 |
+
|
473 |
+
if (inst) {
|
474 |
+
if (this._curInst === inst) {
|
475 |
+
this._hideDatepicker();
|
476 |
+
}
|
477 |
+
|
478 |
+
date = this._getDateDatepicker(target, true);
|
479 |
+
minDate = this._getMinMaxDate(inst, "min");
|
480 |
+
maxDate = this._getMinMaxDate(inst, "max");
|
481 |
+
extendRemove(inst.settings, settings);
|
482 |
+
// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
|
483 |
+
if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
|
484 |
+
inst.settings.minDate = this._formatDate(inst, minDate);
|
485 |
+
}
|
486 |
+
if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
|
487 |
+
inst.settings.maxDate = this._formatDate(inst, maxDate);
|
488 |
+
}
|
489 |
+
if ( "disabled" in settings ) {
|
490 |
+
if ( settings.disabled ) {
|
491 |
+
this._disableDatepicker(target);
|
492 |
+
} else {
|
493 |
+
this._enableDatepicker(target);
|
494 |
+
}
|
495 |
+
}
|
496 |
+
this._attachments($(target), inst);
|
497 |
+
this._autoSize(inst);
|
498 |
+
this._setDate(inst, date);
|
499 |
+
this._updateAlternate(inst);
|
500 |
+
this._updateDatepicker(inst);
|
501 |
+
}
|
502 |
+
},
|
503 |
+
|
504 |
+
// change method deprecated
|
505 |
+
_changeDatepicker: function(target, name, value) {
|
506 |
+
this._optionDatepicker(target, name, value);
|
507 |
+
},
|
508 |
+
|
509 |
+
/* Redraw the date picker attached to an input field or division.
|
510 |
+
* @param target element - the target input field or division or span
|
511 |
+
*/
|
512 |
+
_refreshDatepicker: function(target) {
|
513 |
+
var inst = this._getInst(target);
|
514 |
+
if (inst) {
|
515 |
+
this._updateDatepicker(inst);
|
516 |
+
}
|
517 |
+
},
|
518 |
+
|
519 |
+
/* Set the dates for a jQuery selection.
|
520 |
+
* @param target element - the target input field or division or span
|
521 |
+
* @param date Date - the new date
|
522 |
+
*/
|
523 |
+
_setDateDatepicker: function(target, date) {
|
524 |
+
var inst = this._getInst(target);
|
525 |
+
if (inst) {
|
526 |
+
this._setDate(inst, date);
|
527 |
+
this._updateDatepicker(inst);
|
528 |
+
this._updateAlternate(inst);
|
529 |
+
}
|
530 |
+
},
|
531 |
+
|
532 |
+
/* Get the date(s) for the first entry in a jQuery selection.
|
533 |
+
* @param target element - the target input field or division or span
|
534 |
+
* @param noDefault boolean - true if no default date is to be used
|
535 |
+
* @return Date - the current date
|
536 |
+
*/
|
537 |
+
_getDateDatepicker: function(target, noDefault) {
|
538 |
+
var inst = this._getInst(target);
|
539 |
+
if (inst && !inst.inline) {
|
540 |
+
this._setDateFromField(inst, noDefault);
|
541 |
+
}
|
542 |
+
return (inst ? this._getDate(inst) : null);
|
543 |
+
},
|
544 |
+
|
545 |
+
/* Handle keystrokes. */
|
546 |
+
_doKeyDown: function(event) {
|
547 |
+
var onSelect, dateStr, sel,
|
548 |
+
inst = $.datepicker._getInst(event.target),
|
549 |
+
handled = true,
|
550 |
+
isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
|
551 |
+
|
552 |
+
inst._keyEvent = true;
|
553 |
+
if ($.datepicker._datepickerShowing) {
|
554 |
+
switch (event.keyCode) {
|
555 |
+
case 9: $.datepicker._hideDatepicker();
|
556 |
+
handled = false;
|
557 |
+
break; // hide on tab out
|
558 |
+
case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
|
559 |
+
$.datepicker._currentClass + ")", inst.dpDiv);
|
560 |
+
if (sel[0]) {
|
561 |
+
$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
|
562 |
+
}
|
563 |
+
|
564 |
+
onSelect = $.datepicker._get(inst, "onSelect");
|
565 |
+
if (onSelect) {
|
566 |
+
dateStr = $.datepicker._formatDate(inst);
|
567 |
+
|
568 |
+
// trigger custom callback
|
569 |
+
onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
|
570 |
+
} else {
|
571 |
+
$.datepicker._hideDatepicker();
|
572 |
+
}
|
573 |
+
|
574 |
+
return false; // don't submit the form
|
575 |
+
case 27: $.datepicker._hideDatepicker();
|
576 |
+
break; // hide on escape
|
577 |
+
case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
|
578 |
+
-$.datepicker._get(inst, "stepBigMonths") :
|
579 |
+
-$.datepicker._get(inst, "stepMonths")), "M");
|
580 |
+
break; // previous month/year on page up/+ ctrl
|
581 |
+
case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
|
582 |
+
+$.datepicker._get(inst, "stepBigMonths") :
|
583 |
+
+$.datepicker._get(inst, "stepMonths")), "M");
|
584 |
+
break; // next month/year on page down/+ ctrl
|
585 |
+
case 35: if (event.ctrlKey || event.metaKey) {
|
586 |
+
$.datepicker._clearDate(event.target);
|
587 |
+
}
|
588 |
+
handled = event.ctrlKey || event.metaKey;
|
589 |
+
break; // clear on ctrl or command +end
|
590 |
+
case 36: if (event.ctrlKey || event.metaKey) {
|
591 |
+
$.datepicker._gotoToday(event.target);
|
592 |
+
}
|
593 |
+
handled = event.ctrlKey || event.metaKey;
|
594 |
+
break; // current on ctrl or command +home
|
595 |
+
case 37: if (event.ctrlKey || event.metaKey) {
|
596 |
+
$.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
|
597 |
+
}
|
598 |
+
handled = event.ctrlKey || event.metaKey;
|
599 |
+
// -1 day on ctrl or command +left
|
600 |
+
if (event.originalEvent.altKey) {
|
601 |
+
$.datepicker._adjustDate(event.target, (event.ctrlKey ?
|
602 |
+
-$.datepicker._get(inst, "stepBigMonths") :
|
603 |
+
-$.datepicker._get(inst, "stepMonths")), "M");
|
604 |
+
}
|
605 |
+
// next month/year on alt +left on Mac
|
606 |
+
break;
|
607 |
+
case 38: if (event.ctrlKey || event.metaKey) {
|
608 |
+
$.datepicker._adjustDate(event.target, -7, "D");
|
609 |
+
}
|
610 |
+
handled = event.ctrlKey || event.metaKey;
|
611 |
+
break; // -1 week on ctrl or command +up
|
612 |
+
case 39: if (event.ctrlKey || event.metaKey) {
|
613 |
+
$.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
|
614 |
+
}
|
615 |
+
handled = event.ctrlKey || event.metaKey;
|
616 |
+
// +1 day on ctrl or command +right
|
617 |
+
if (event.originalEvent.altKey) {
|
618 |
+
$.datepicker._adjustDate(event.target, (event.ctrlKey ?
|
619 |
+
+$.datepicker._get(inst, "stepBigMonths") :
|
620 |
+
+$.datepicker._get(inst, "stepMonths")), "M");
|
621 |
+
}
|
622 |
+
// next month/year on alt +right
|
623 |
+
break;
|
624 |
+
case 40: if (event.ctrlKey || event.metaKey) {
|
625 |
+
$.datepicker._adjustDate(event.target, +7, "D");
|
626 |
+
}
|
627 |
+
handled = event.ctrlKey || event.metaKey;
|
628 |
+
break; // +1 week on ctrl or command +down
|
629 |
+
default: handled = false;
|
630 |
+
}
|
631 |
+
} else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
|
632 |
+
$.datepicker._showDatepicker(this);
|
633 |
+
} else {
|
634 |
+
handled = false;
|
635 |
+
}
|
636 |
+
|
637 |
+
if (handled) {
|
638 |
+
event.preventDefault();
|
639 |
+
event.stopPropagation();
|
640 |
+
}
|
641 |
+
},
|
642 |
+
|
643 |
+
/* Filter entered characters - based on date format. */
|
644 |
+
_doKeyPress: function(event) {
|
645 |
+
var chars, chr,
|
646 |
+
inst = $.datepicker._getInst(event.target);
|
647 |
+
|
648 |
+
if ($.datepicker._get(inst, "constrainInput")) {
|
649 |
+
chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
|
650 |
+
chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
|
651 |
+
return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
|
652 |
+
}
|
653 |
+
},
|
654 |
+
|
655 |
+
/* Synchronise manual entry and field/alternate field. */
|
656 |
+
_doKeyUp: function(event) {
|
657 |
+
var date,
|
658 |
+
inst = $.datepicker._getInst(event.target);
|
659 |
+
|
660 |
+
if (inst.input.val() !== inst.lastVal) {
|
661 |
+
try {
|
662 |
+
date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
|
663 |
+
(inst.input ? inst.input.val() : null),
|
664 |
+
$.datepicker._getFormatConfig(inst));
|
665 |
+
|
666 |
+
if (date) { // only if valid
|
667 |
+
$.datepicker._setDateFromField(inst);
|
668 |
+
$.datepicker._updateAlternate(inst);
|
669 |
+
$.datepicker._updateDatepicker(inst);
|
670 |
+
}
|
671 |
+
}
|
672 |
+
catch (err) {
|
673 |
+
}
|
674 |
+
}
|
675 |
+
return true;
|
676 |
+
},
|
677 |
+
|
678 |
+
/* Pop-up the date picker for a given input field.
|
679 |
+
* If false returned from beforeShow event handler do not show.
|
680 |
+
* @param input element - the input field attached to the date picker or
|
681 |
+
* event - if triggered by focus
|
682 |
+
*/
|
683 |
+
_showDatepicker: function(input) {
|
684 |
+
input = input.target || input;
|
685 |
+
if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
|
686 |
+
input = $("input", input.parentNode)[0];
|
687 |
+
}
|
688 |
+
|
689 |
+
if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
|
690 |
+
return;
|
691 |
+
}
|
692 |
+
|
693 |
+
var inst, beforeShow, beforeShowSettings, isFixed,
|
694 |
+
offset, showAnim, duration;
|
695 |
+
|
696 |
+
inst = $.datepicker._getInst(input);
|
697 |
+
if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
|
698 |
+
$.datepicker._curInst.dpDiv.stop(true, true);
|
699 |
+
if ( inst && $.datepicker._datepickerShowing ) {
|
700 |
+
$.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
|
701 |
+
}
|
702 |
+
}
|
703 |
+
|
704 |
+
beforeShow = $.datepicker._get(inst, "beforeShow");
|
705 |
+
beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
|
706 |
+
if(beforeShowSettings === false){
|
707 |
+
return;
|
708 |
+
}
|
709 |
+
extendRemove(inst.settings, beforeShowSettings);
|
710 |
+
|
711 |
+
inst.lastVal = null;
|
712 |
+
$.datepicker._lastInput = input;
|
713 |
+
$.datepicker._setDateFromField(inst);
|
714 |
+
|
715 |
+
if ($.datepicker._inDialog) { // hide cursor
|
716 |
+
input.value = "";
|
717 |
+
}
|
718 |
+
if (!$.datepicker._pos) { // position below input
|
719 |
+
$.datepicker._pos = $.datepicker._findPos(input);
|
720 |
+
$.datepicker._pos[1] += input.offsetHeight; // add the height
|
721 |
+
}
|
722 |
+
|
723 |
+
isFixed = false;
|
724 |
+
$(input).parents().each(function() {
|
725 |
+
isFixed |= $(this).css("position") === "fixed";
|
726 |
+
return !isFixed;
|
727 |
+
});
|
728 |
+
|
729 |
+
offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
|
730 |
+
$.datepicker._pos = null;
|
731 |
+
//to avoid flashes on Firefox
|
732 |
+
inst.dpDiv.empty();
|
733 |
+
// determine sizing offscreen
|
734 |
+
inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
|
735 |
+
$.datepicker._updateDatepicker(inst);
|
736 |
+
// fix width for dynamic number of date pickers
|
737 |
+
// and adjust position before showing
|
738 |
+
offset = $.datepicker._checkOffset(inst, offset, isFixed);
|
739 |
+
inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
|
740 |
+
"static" : (isFixed ? "fixed" : "absolute")), display: "none",
|
741 |
+
left: offset.left + "px", top: offset.top + "px"});
|
742 |
+
|
743 |
+
if (!inst.inline) {
|
744 |
+
showAnim = $.datepicker._get(inst, "showAnim");
|
745 |
+
duration = $.datepicker._get(inst, "duration");
|
746 |
+
inst.dpDiv.zIndex($(input).zIndex()+1);
|
747 |
+
$.datepicker._datepickerShowing = true;
|
748 |
+
|
749 |
+
if ( $.effects && $.effects.effect[ showAnim ] ) {
|
750 |
+
inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
|
751 |
+
} else {
|
752 |
+
inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
|
753 |
+
}
|
754 |
+
|
755 |
+
if ( $.datepicker._shouldFocusInput( inst ) ) {
|
756 |
+
inst.input.focus();
|
757 |
+
}
|
758 |
+
|
759 |
+
$.datepicker._curInst = inst;
|
760 |
+
}
|
761 |
+
},
|
762 |
+
|
763 |
+
/* Generate the date picker content. */
|
764 |
+
_updateDatepicker: function(inst) {
|
765 |
+
this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
|
766 |
+
instActive = inst; // for delegate hover events
|
767 |
+
inst.dpDiv.empty().append(this._generateHTML(inst));
|
768 |
+
this._attachHandlers(inst);
|
769 |
+
inst.dpDiv.find("." + this._dayOverClass + " a").mouseover();
|
770 |
+
|
771 |
+
var origyearshtml,
|
772 |
+
numMonths = this._getNumberOfMonths(inst),
|
773 |
+
cols = numMonths[1],
|
774 |
+
width = 17;
|
775 |
+
|
776 |
+
inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
|
777 |
+
if (cols > 1) {
|
778 |
+
inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
|
779 |
+
}
|
780 |
+
inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
|
781 |
+
"Class"]("ui-datepicker-multi");
|
782 |
+
inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
|
783 |
+
"Class"]("ui-datepicker-rtl");
|
784 |
+
|
785 |
+
if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
|
786 |
+
inst.input.focus();
|
787 |
+
}
|
788 |
+
|
789 |
+
// deffered render of the years select (to avoid flashes on Firefox)
|
790 |
+
if( inst.yearshtml ){
|
791 |
+
origyearshtml = inst.yearshtml;
|
792 |
+
setTimeout(function(){
|
793 |
+
//assure that inst.yearshtml didn't change.
|
794 |
+
if( origyearshtml === inst.yearshtml && inst.yearshtml ){
|
795 |
+
inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
|
796 |
+
}
|
797 |
+
origyearshtml = inst.yearshtml = null;
|
798 |
+
}, 0);
|
799 |
+
}
|
800 |
+
},
|
801 |
+
|
802 |
+
// #6694 - don't focus the input if it's already focused
|
803 |
+
// this breaks the change event in IE
|
804 |
+
// Support: IE and jQuery <1.9
|
805 |
+
_shouldFocusInput: function( inst ) {
|
806 |
+
return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
|
807 |
+
},
|
808 |
+
|
809 |
+
/* Check positioning to remain on screen. */
|
810 |
+
_checkOffset: function(inst, offset, isFixed) {
|
811 |
+
var dpWidth = inst.dpDiv.outerWidth(),
|
812 |
+
dpHeight = inst.dpDiv.outerHeight(),
|
813 |
+
inputWidth = inst.input ? inst.input.outerWidth() : 0,
|
814 |
+
inputHeight = inst.input ? inst.input.outerHeight() : 0,
|
815 |
+
viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
|
816 |
+
viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
|
817 |
+
|
818 |
+
offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
|
819 |
+
offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
|
820 |
+
offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
|
821 |
+
|
822 |
+
// now check if datepicker is showing outside window viewport - move to a better place if so.
|
823 |
+
offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
|
824 |
+
Math.abs(offset.left + dpWidth - viewWidth) : 0);
|
825 |
+
offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
|
826 |
+
Math.abs(dpHeight + inputHeight) : 0);
|
827 |
+
|
828 |
+
return offset;
|
829 |
+
},
|
830 |
+
|
831 |
+
/* Find an object's position on the screen. */
|
832 |
+
_findPos: function(obj) {
|
833 |
+
var position,
|
834 |
+
inst = this._getInst(obj),
|
835 |
+
isRTL = this._get(inst, "isRTL");
|
836 |
+
|
837 |
+
while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
|
838 |
+
obj = obj[isRTL ? "previousSibling" : "nextSibling"];
|
839 |
+
}
|
840 |
+
|
841 |
+
position = $(obj).offset();
|
842 |
+
return [position.left, position.top];
|
843 |
+
},
|
844 |
+
|
845 |
+
/* Hide the date picker from view.
|
846 |
+
* @param input element - the input field attached to the date picker
|
847 |
+
*/
|
848 |
+
_hideDatepicker: function(input) {
|
849 |
+
var showAnim, duration, postProcess, onClose,
|
850 |
+
inst = this._curInst;
|
851 |
+
|
852 |
+
if (!inst || (input && inst !== $.data(input, PROP_NAME))) {
|
853 |
+
return;
|
854 |
+
}
|
855 |
+
|
856 |
+
if (this._datepickerShowing) {
|
857 |
+
showAnim = this._get(inst, "showAnim");
|
858 |
+
duration = this._get(inst, "duration");
|
859 |
+
postProcess = function() {
|
860 |
+
$.datepicker._tidyDialog(inst);
|
861 |
+
};
|
862 |
+
|
863 |
+
// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
|
864 |
+
if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
|
865 |
+
inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
|
866 |
+
} else {
|
867 |
+
inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
|
868 |
+
(showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
|
869 |
+
}
|
870 |
+
|
871 |
+
if (!showAnim) {
|
872 |
+
postProcess();
|
873 |
+
}
|
874 |
+
this._datepickerShowing = false;
|
875 |
+
|
876 |
+
onClose = this._get(inst, "onClose");
|
877 |
+
if (onClose) {
|
878 |
+
onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
|
879 |
+
}
|
880 |
+
|
881 |
+
this._lastInput = null;
|
882 |
+
if (this._inDialog) {
|
883 |
+
this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
|
884 |
+
if ($.blockUI) {
|
885 |
+
$.unblockUI();
|
886 |
+
$("body").append(this.dpDiv);
|
887 |
+
}
|
888 |
+
}
|
889 |
+
this._inDialog = false;
|
890 |
+
}
|
891 |
+
},
|
892 |
+
|
893 |
+
/* Tidy up after a dialog display. */
|
894 |
+
_tidyDialog: function(inst) {
|
895 |
+
inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
|
896 |
+
},
|
897 |
+
|
898 |
+
/* Close date picker if clicked elsewhere. */
|
899 |
+
_checkExternalClick: function(event) {
|
900 |
+
if (!$.datepicker._curInst) {
|
901 |
+
return;
|
902 |
+
}
|
903 |
+
|
904 |
+
var $target = $(event.target),
|
905 |
+
inst = $.datepicker._getInst($target[0]);
|
906 |
+
|
907 |
+
if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
|
908 |
+
$target.parents("#" + $.datepicker._mainDivId).length === 0 &&
|
909 |
+
!$target.hasClass($.datepicker.markerClassName) &&
|
910 |
+
!$target.closest("." + $.datepicker._triggerClass).length &&
|
911 |
+
$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
|
912 |
+
( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
|
913 |
+
$.datepicker._hideDatepicker();
|
914 |
+
}
|
915 |
+
},
|
916 |
+
|
917 |
+
/* Adjust one of the date sub-fields. */
|
918 |
+
_adjustDate: function(id, offset, period) {
|
919 |
+
var target = $(id),
|
920 |
+
inst = this._getInst(target[0]);
|
921 |
+
|
922 |
+
if (this._isDisabledDatepicker(target[0])) {
|
923 |
+
return;
|
924 |
+
}
|
925 |
+
this._adjustInstDate(inst, offset +
|
926 |
+
(period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
|
927 |
+
period);
|
928 |
+
this._updateDatepicker(inst);
|
929 |
+
},
|
930 |
+
|
931 |
+
/* Action for current link. */
|
932 |
+
_gotoToday: function(id) {
|
933 |
+
var date,
|
934 |
+
target = $(id),
|
935 |
+
inst = this._getInst(target[0]);
|
936 |
+
|
937 |
+
if (this._get(inst, "gotoCurrent") && inst.currentDay) {
|
938 |
+
inst.selectedDay = inst.currentDay;
|
939 |
+
inst.drawMonth = inst.selectedMonth = inst.currentMonth;
|
940 |
+
inst.drawYear = inst.selectedYear = inst.currentYear;
|
941 |
+
} else {
|
942 |
+
date = new Date();
|
943 |
+
inst.selectedDay = date.getDate();
|
944 |
+
inst.drawMonth = inst.selectedMonth = date.getMonth();
|
945 |
+
inst.drawYear = inst.selectedYear = date.getFullYear();
|
946 |
+
}
|
947 |
+
this._notifyChange(inst);
|
948 |
+
this._adjustDate(target);
|
949 |
+
},
|
950 |
+
|
951 |
+
/* Action for selecting a new month/year. */
|
952 |
+
_selectMonthYear: function(id, select, period) {
|
953 |
+
var target = $(id),
|
954 |
+
inst = this._getInst(target[0]);
|
955 |
+
|
956 |
+
inst["selected" + (period === "M" ? "Month" : "Year")] =
|
957 |
+
inst["draw" + (period === "M" ? "Month" : "Year")] =
|
958 |
+
parseInt(select.options[select.selectedIndex].value,10);
|
959 |
+
|
960 |
+
this._notifyChange(inst);
|
961 |
+
this._adjustDate(target);
|
962 |
+
},
|
963 |
+
|
964 |
+
/* Action for selecting a day. */
|
965 |
+
_selectDay: function(id, month, year, td) {
|
966 |
+
var inst,
|
967 |
+
target = $(id);
|
968 |
+
|
969 |
+
if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
|
970 |
+
return;
|
971 |
+
}
|
972 |
+
|
973 |
+
inst = this._getInst(target[0]);
|
974 |
+
inst.selectedDay = inst.currentDay = $("a", td).html();
|
975 |
+
inst.selectedMonth = inst.currentMonth = month;
|
976 |
+
inst.selectedYear = inst.currentYear = year;
|
977 |
+
this._selectDate(id, this._formatDate(inst,
|
978 |
+
inst.currentDay, inst.currentMonth, inst.currentYear));
|
979 |
+
},
|
980 |
+
|
981 |
+
/* Erase the input field and hide the date picker. */
|
982 |
+
_clearDate: function(id) {
|
983 |
+
var target = $(id);
|
984 |
+
this._selectDate(target, "");
|
985 |
+
},
|
986 |
+
|
987 |
+
/* Update the input field with the selected date. */
|
988 |
+
_selectDate: function(id, dateStr) {
|
989 |
+
var onSelect,
|
990 |
+
target = $(id),
|
991 |
+
inst = this._getInst(target[0]);
|
992 |
+
|
993 |
+
dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
|
994 |
+
if (inst.input) {
|
995 |
+
inst.input.val(dateStr);
|
996 |
+
}
|
997 |
+
this._updateAlternate(inst);
|
998 |
+
|
999 |
+
onSelect = this._get(inst, "onSelect");
|
1000 |
+
if (onSelect) {
|
1001 |
+
onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
|
1002 |
+
} else if (inst.input) {
|
1003 |
+
inst.input.trigger("change"); // fire the change event
|
1004 |
+
}
|
1005 |
+
|
1006 |
+
if (inst.inline){
|
1007 |
+
this._updateDatepicker(inst);
|
1008 |
+
} else {
|
1009 |
+
this._hideDatepicker();
|
1010 |
+
this._lastInput = inst.input[0];
|
1011 |
+
if (typeof(inst.input[0]) !== "object") {
|
1012 |
+
inst.input.focus(); // restore focus
|
1013 |
+
}
|
1014 |
+
this._lastInput = null;
|
1015 |
+
}
|
1016 |
+
},
|
1017 |
+
|
1018 |
+
/* Update any alternate field to synchronise with the main field. */
|
1019 |
+
_updateAlternate: function(inst) {
|
1020 |
+
var altFormat, date, dateStr,
|
1021 |
+
altField = this._get(inst, "altField");
|
1022 |
+
|
1023 |
+
if (altField) { // update alternate field too
|
1024 |
+
altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
|
1025 |
+
date = this._getDate(inst);
|
1026 |
+
dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
|
1027 |
+
$(altField).each(function() { $(this).val(dateStr); });
|
1028 |
+
}
|
1029 |
+
},
|
1030 |
+
|
1031 |
+
/* Set as beforeShowDay function to prevent selection of weekends.
|
1032 |
+
* @param date Date - the date to customise
|
1033 |
+
* @return [boolean, string] - is this date selectable?, what is its CSS class?
|
1034 |
+
*/
|
1035 |
+
noWeekends: function(date) {
|
1036 |
+
var day = date.getDay();
|
1037 |
+
return [(day > 0 && day < 6), ""];
|
1038 |
+
},
|
1039 |
+
|
1040 |
+
/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
|
1041 |
+
* @param date Date - the date to get the week for
|
1042 |
+
* @return number - the number of the week within the year that contains this date
|
1043 |
+
*/
|
1044 |
+
iso8601Week: function(date) {
|
1045 |
+
var time,
|
1046 |
+
checkDate = new Date(date.getTime());
|
1047 |
+
|
1048 |
+
// Find Thursday of this week starting on Monday
|
1049 |
+
checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
|
1050 |
+
|
1051 |
+
time = checkDate.getTime();
|
1052 |
+
checkDate.setMonth(0); // Compare with Jan 1
|
1053 |
+
checkDate.setDate(1);
|
1054 |
+
return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
|
1055 |
+
},
|
1056 |
+
|
1057 |
+
/* Parse a string value into a date object.
|
1058 |
+
* See formatDate below for the possible formats.
|
1059 |
+
*
|
1060 |
+
* @param format string - the expected format of the date
|
1061 |
+
* @param value string - the date in the above format
|
1062 |
+
* @param settings Object - attributes include:
|
1063 |
+
* shortYearCutoff number - the cutoff year for determining the century (optional)
|
1064 |
+
* dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
|
1065 |
+
* dayNames string[7] - names of the days from Sunday (optional)
|
1066 |
+
* monthNamesShort string[12] - abbreviated names of the months (optional)
|
1067 |
+
* monthNames string[12] - names of the months (optional)
|
1068 |
+
* @return Date - the extracted date value or null if value is blank
|
1069 |
+
*/
|
1070 |
+
parseDate: function (format, value, settings) {
|
1071 |
+
if (format == null || value == null) {
|
1072 |
+
throw "Invalid arguments";
|
1073 |
+
}
|
1074 |
+
|
1075 |
+
value = (typeof value === "object" ? value.toString() : value + "");
|
1076 |
+
if (value === "") {
|
1077 |
+
return null;
|
1078 |
+
}
|
1079 |
+
|
1080 |
+
var iFormat, dim, extra,
|
1081 |
+
iValue = 0,
|
1082 |
+
shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
|
1083 |
+
shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
|
1084 |
+
new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
|
1085 |
+
dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
|
1086 |
+
dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
|
1087 |
+
monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
|
1088 |
+
monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
|
1089 |
+
year = -1,
|
1090 |
+
month = -1,
|
1091 |
+
day = -1,
|
1092 |
+
doy = -1,
|
1093 |
+
literal = false,
|
1094 |
+
date,
|
1095 |
+
// Check whether a format character is doubled
|
1096 |
+
lookAhead = function(match) {
|
1097 |
+
var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
|
1098 |
+
if (matches) {
|
1099 |
+
iFormat++;
|
1100 |
+
}
|
1101 |
+
return matches;
|
1102 |
+
},
|
1103 |
+
// Extract a number from the string value
|
1104 |
+
getNumber = function(match) {
|
1105 |
+
var isDoubled = lookAhead(match),
|
1106 |
+
size = (match === "@" ? 14 : (match === "!" ? 20 :
|
1107 |
+
(match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
|
1108 |
+
digits = new RegExp("^\\d{1," + size + "}"),
|
1109 |
+
num = value.substring(iValue).match(digits);
|
1110 |
+
if (!num) {
|
1111 |
+
throw "Missing number at position " + iValue;
|
1112 |
+
}
|
1113 |
+
iValue += num[0].length;
|
1114 |
+
return parseInt(num[0], 10);
|
1115 |
+
},
|
1116 |
+
// Extract a name from the string value and convert to an index
|
1117 |
+
getName = function(match, shortNames, longNames) {
|
1118 |
+
var index = -1,
|
1119 |
+
names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
|
1120 |
+
return [ [k, v] ];
|
1121 |
+
}).sort(function (a, b) {
|
1122 |
+
return -(a[1].length - b[1].length);
|
1123 |
+
});
|
1124 |
+
|
1125 |
+
$.each(names, function (i, pair) {
|
1126 |
+
var name = pair[1];
|
1127 |
+
if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
|
1128 |
+
index = pair[0];
|
1129 |
+
iValue += name.length;
|
1130 |
+
return false;
|
1131 |
+
}
|
1132 |
+
});
|
1133 |
+
if (index !== -1) {
|
1134 |
+
return index + 1;
|
1135 |
+
} else {
|
1136 |
+
throw "Unknown name at position " + iValue;
|
1137 |
+
}
|
1138 |
+
},
|
1139 |
+
// Confirm that a literal character matches the string value
|
1140 |
+
checkLiteral = function() {
|
1141 |
+
if (value.charAt(iValue) !== format.charAt(iFormat)) {
|
1142 |
+
throw "Unexpected literal at position " + iValue;
|
1143 |
+
}
|
1144 |
+
iValue++;
|
1145 |
+
};
|
1146 |
+
|
1147 |
+
for (iFormat = 0; iFormat < format.length; iFormat++) {
|
1148 |
+
if (literal) {
|
1149 |
+
if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
|
1150 |
+
literal = false;
|
1151 |
+
} else {
|
1152 |
+
checkLiteral();
|
1153 |
+
}
|
1154 |
+
} else {
|
1155 |
+
switch (format.charAt(iFormat)) {
|
1156 |
+
case "d":
|
1157 |
+
day = getNumber("d");
|
1158 |
+
break;
|
1159 |
+
case "D":
|
1160 |
+
getName("D", dayNamesShort, dayNames);
|
1161 |
+
break;
|
1162 |
+
case "o":
|
1163 |
+
doy = getNumber("o");
|
1164 |
+
break;
|
1165 |
+
case "m":
|
1166 |
+
month = getNumber("m");
|
1167 |
+
break;
|
1168 |
+
case "M":
|
1169 |
+
month = getName("M", monthNamesShort, monthNames);
|
1170 |
+
break;
|
1171 |
+
case "y":
|
1172 |
+
year = getNumber("y");
|
1173 |
+
break;
|
1174 |
+
case "@":
|
1175 |
+
date = new Date(getNumber("@"));
|
1176 |
+
year = date.getFullYear();
|
1177 |
+
month = date.getMonth() + 1;
|
1178 |
+
day = date.getDate();
|
1179 |
+
break;
|
1180 |
+
case "!":
|
1181 |
+
date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
|
1182 |
+
year = date.getFullYear();
|
1183 |
+
month = date.getMonth() + 1;
|
1184 |
+
day = date.getDate();
|
1185 |
+
break;
|
1186 |
+
case "'":
|
1187 |
+
if (lookAhead("'")){
|
1188 |
+
checkLiteral();
|
1189 |
+
} else {
|
1190 |
+
literal = true;
|
1191 |
+
}
|
1192 |
+
break;
|
1193 |
+
default:
|
1194 |
+
checkLiteral();
|
1195 |
+
}
|
1196 |
+
}
|
1197 |
+
}
|
1198 |
+
|
1199 |
+
if (iValue < value.length){
|
1200 |
+
extra = value.substr(iValue);
|
1201 |
+
if (!/^\s+/.test(extra)) {
|
1202 |
+
throw "Extra/unparsed characters found in date: " + extra;
|
1203 |
+
}
|
1204 |
+
}
|
1205 |
+
|
1206 |
+
if (year === -1) {
|
1207 |
+
year = new Date().getFullYear();
|
1208 |
+
} else if (year < 100) {
|
1209 |
+
year += new Date().getFullYear() - new Date().getFullYear() % 100 +
|
1210 |
+
(year <= shortYearCutoff ? 0 : -100);
|
1211 |
+
}
|
1212 |
+
|
1213 |
+
if (doy > -1) {
|
1214 |
+
month = 1;
|
1215 |
+
day = doy;
|
1216 |
+
do {
|
1217 |
+
dim = this._getDaysInMonth(year, month - 1);
|
1218 |
+
if (day <= dim) {
|
1219 |
+
break;
|
1220 |
+
}
|
1221 |
+
month++;
|
1222 |
+
day -= dim;
|
1223 |
+
} while (true);
|
1224 |
+
}
|
1225 |
+
|
1226 |
+
date = this._daylightSavingAdjust(new Date(year, month - 1, day));
|
1227 |
+
if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
|
1228 |
+
throw "Invalid date"; // E.g. 31/02/00
|
1229 |
+
}
|
1230 |
+
return date;
|
1231 |
+
},
|
1232 |
+
|
1233 |
+
/* Standard date formats. */
|
1234 |
+
ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
|
1235 |
+
COOKIE: "D, dd M yy",
|
1236 |
+
ISO_8601: "yy-mm-dd",
|
1237 |
+
RFC_822: "D, d M y",
|
1238 |
+
RFC_850: "DD, dd-M-y",
|
1239 |
+
RFC_1036: "D, d M y",
|
1240 |
+
RFC_1123: "D, d M yy",
|
1241 |
+
RFC_2822: "D, d M yy",
|
1242 |
+
RSS: "D, d M y", // RFC 822
|
1243 |
+
TICKS: "!",
|
1244 |
+
TIMESTAMP: "@",
|
1245 |
+
W3C: "yy-mm-dd", // ISO 8601
|
1246 |
+
|
1247 |
+
_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
|
1248 |
+
Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
|
1249 |
+
|
1250 |
+
/* Format a date object into a string value.
|
1251 |
+
* The format can be combinations of the following:
|
1252 |
+
* d - day of month (no leading zero)
|
1253 |
+
* dd - day of month (two digit)
|
1254 |
+
* o - day of year (no leading zeros)
|
1255 |
+
* oo - day of year (three digit)
|
1256 |
+
* D - day name short
|
1257 |
+
* DD - day name long
|
1258 |
+
* m - month of year (no leading zero)
|
1259 |
+
* mm - month of year (two digit)
|
1260 |
+
* M - month name short
|
1261 |
+
* MM - month name long
|
1262 |
+
* y - year (two digit)
|
1263 |
+
* yy - year (four digit)
|
1264 |
+
* @ - Unix timestamp (ms since 01/01/1970)
|
1265 |
+
* ! - Windows ticks (100ns since 01/01/0001)
|
1266 |
+
* "..." - literal text
|
1267 |
+
* '' - single quote
|
1268 |
+
*
|
1269 |
+
* @param format string - the desired format of the date
|
1270 |
+
* @param date Date - the date value to format
|
1271 |
+
* @param settings Object - attributes include:
|
1272 |
+
* dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
|
1273 |
+
* dayNames string[7] - names of the days from Sunday (optional)
|
1274 |
+
* monthNamesShort string[12] - abbreviated names of the months (optional)
|
1275 |
+
* monthNames string[12] - names of the months (optional)
|
1276 |
+
* @return string - the date in the above format
|
1277 |
+
*/
|
1278 |
+
formatDate: function (format, date, settings) {
|
1279 |
+
if (!date) {
|
1280 |
+
return "";
|
1281 |
+
}
|
1282 |
+
|
1283 |
+
var iFormat,
|
1284 |
+
dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
|
1285 |
+
dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
|
1286 |
+
monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
|
1287 |
+
monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
|
1288 |
+
// Check whether a format character is doubled
|
1289 |
+
lookAhead = function(match) {
|
1290 |
+
var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
|
1291 |
+
if (matches) {
|
1292 |
+
iFormat++;
|
1293 |
+
}
|
1294 |
+
return matches;
|
1295 |
+
},
|
1296 |
+
// Format a number, with leading zero if necessary
|
1297 |
+
formatNumber = function(match, value, len) {
|
1298 |
+
var num = "" + value;
|
1299 |
+
if (lookAhead(match)) {
|
1300 |
+
while (num.length < len) {
|
1301 |
+
num = "0" + num;
|
1302 |
+
}
|
1303 |
+
}
|
1304 |
+
return num;
|
1305 |
+
},
|
1306 |
+
// Format a name, short or long as requested
|
1307 |
+
formatName = function(match, value, shortNames, longNames) {
|
1308 |
+
return (lookAhead(match) ? longNames[value] : shortNames[value]);
|
1309 |
+
},
|
1310 |
+
output = "",
|
1311 |
+
literal = false;
|
1312 |
+
|
1313 |
+
if (date) {
|
1314 |
+
for (iFormat = 0; iFormat < format.length; iFormat++) {
|
1315 |
+
if (literal) {
|
1316 |
+
if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
|
1317 |
+
literal = false;
|
1318 |
+
} else {
|
1319 |
+
output += format.charAt(iFormat);
|
1320 |
+
}
|
1321 |
+
} else {
|
1322 |
+
switch (format.charAt(iFormat)) {
|
1323 |
+
case "d":
|
1324 |
+
output += formatNumber("d", date.getDate(), 2);
|
1325 |
+
break;
|
1326 |
+
case "D":
|
1327 |
+
output += formatName("D", date.getDay(), dayNamesShort, dayNames);
|
1328 |
+
break;
|
1329 |
+
case "o":
|
1330 |
+
output += formatNumber("o",
|
1331 |
+
Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
|
1332 |
+
break;
|
1333 |
+
case "m":
|
1334 |
+
output += formatNumber("m", date.getMonth() + 1, 2);
|
1335 |
+
break;
|
1336 |
+
case "M":
|
1337 |
+
output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
|
1338 |
+
break;
|
1339 |
+
case "y":
|
1340 |
+
output += (lookAhead("y") ? date.getFullYear() :
|
1341 |
+
(date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
|
1342 |
+
break;
|
1343 |
+
case "@":
|
1344 |
+
output += date.getTime();
|
1345 |
+
break;
|
1346 |
+
case "!":
|
1347 |
+
output += date.getTime() * 10000 + this._ticksTo1970;
|
1348 |
+
break;
|
1349 |
+
case "'":
|
1350 |
+
if (lookAhead("'")) {
|
1351 |
+
output += "'";
|
1352 |
+
} else {
|
1353 |
+
literal = true;
|
1354 |
+
}
|
1355 |
+
break;
|
1356 |
+
default:
|
1357 |
+
output += format.charAt(iFormat);
|
1358 |
+
}
|
1359 |
+
}
|
1360 |
+
}
|
1361 |
+
}
|
1362 |
+
return output;
|
1363 |
+
},
|
1364 |
+
|
1365 |
+
/* Extract all possible characters from the date format. */
|
1366 |
+
_possibleChars: function (format) {
|
1367 |
+
var iFormat,
|
1368 |
+
chars = "",
|
1369 |
+
literal = false,
|
1370 |
+
// Check whether a format character is doubled
|
1371 |
+
lookAhead = function(match) {
|
1372 |
+
var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
|
1373 |
+
if (matches) {
|
1374 |
+
iFormat++;
|
1375 |
+
}
|
1376 |
+
return matches;
|
1377 |
+
};
|
1378 |
+
|
1379 |
+
for (iFormat = 0; iFormat < format.length; iFormat++) {
|
1380 |
+
if (literal) {
|
1381 |
+
if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
|
1382 |
+
literal = false;
|
1383 |
+
} else {
|
1384 |
+
chars += format.charAt(iFormat);
|
1385 |
+
}
|
1386 |
+
} else {
|
1387 |
+
switch (format.charAt(iFormat)) {
|
1388 |
+
case "d": case "m": case "y": case "@":
|
1389 |
+
chars += "0123456789";
|
1390 |
+
break;
|
1391 |
+
case "D": case "M":
|
1392 |
+
return null; // Accept anything
|
1393 |
+
case "'":
|
1394 |
+
if (lookAhead("'")) {
|
1395 |
+
chars += "'";
|
1396 |
+
} else {
|
1397 |
+
literal = true;
|
1398 |
+
}
|
1399 |
+
break;
|
1400 |
+
default:
|
1401 |
+
chars += format.charAt(iFormat);
|
1402 |
+
}
|
1403 |
+
}
|
1404 |
+
}
|
1405 |
+
return chars;
|
1406 |
+
},
|
1407 |
+
|
1408 |
+
/* Get a setting value, defaulting if necessary. */
|
1409 |
+
_get: function(inst, name) {
|
1410 |
+
return inst.settings[name] !== undefined ?
|
1411 |
+
inst.settings[name] : this._defaults[name];
|
1412 |
+
},
|
1413 |
+
|
1414 |
+
/* Parse existing date and initialise date picker. */
|
1415 |
+
_setDateFromField: function(inst, noDefault) {
|
1416 |
+
if (inst.input.val() === inst.lastVal) {
|
1417 |
+
return;
|
1418 |
+
}
|
1419 |
+
|
1420 |
+
var dateFormat = this._get(inst, "dateFormat"),
|
1421 |
+
dates = inst.lastVal = inst.input ? inst.input.val() : null,
|
1422 |
+
defaultDate = this._getDefaultDate(inst),
|
1423 |
+
date = defaultDate,
|
1424 |
+
settings = this._getFormatConfig(inst);
|
1425 |
+
|
1426 |
+
try {
|
1427 |
+
date = this.parseDate(dateFormat, dates, settings) || defaultDate;
|
1428 |
+
} catch (event) {
|
1429 |
+
dates = (noDefault ? "" : dates);
|
1430 |
+
}
|
1431 |
+
inst.selectedDay = date.getDate();
|
1432 |
+
inst.drawMonth = inst.selectedMonth = date.getMonth();
|
1433 |
+
inst.drawYear = inst.selectedYear = date.getFullYear();
|
1434 |
+
inst.currentDay = (dates ? date.getDate() : 0);
|
1435 |
+
inst.currentMonth = (dates ? date.getMonth() : 0);
|
1436 |
+
inst.currentYear = (dates ? date.getFullYear() : 0);
|
1437 |
+
this._adjustInstDate(inst);
|
1438 |
+
},
|
1439 |
+
|
1440 |
+
/* Retrieve the default date shown on opening. */
|
1441 |
+
_getDefaultDate: function(inst) {
|
1442 |
+
return this._restrictMinMax(inst,
|
1443 |
+
this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
|
1444 |
+
},
|
1445 |
+
|
1446 |
+
/* A date may be specified as an exact value or a relative one. */
|
1447 |
+
_determineDate: function(inst, date, defaultDate) {
|
1448 |
+
var offsetNumeric = function(offset) {
|
1449 |
+
var date = new Date();
|
1450 |
+
date.setDate(date.getDate() + offset);
|
1451 |
+
return date;
|
1452 |
+
},
|
1453 |
+
offsetString = function(offset) {
|
1454 |
+
try {
|
1455 |
+
return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
|
1456 |
+
offset, $.datepicker._getFormatConfig(inst));
|
1457 |
+
}
|
1458 |
+
catch (e) {
|
1459 |
+
// Ignore
|
1460 |
+
}
|
1461 |
+
|
1462 |
+
var date = (offset.toLowerCase().match(/^c/) ?
|
1463 |
+
$.datepicker._getDate(inst) : null) || new Date(),
|
1464 |
+
year = date.getFullYear(),
|
1465 |
+
month = date.getMonth(),
|
1466 |
+
day = date.getDate(),
|
1467 |
+
pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
|
1468 |
+
matches = pattern.exec(offset);
|
1469 |
+
|
1470 |
+
while (matches) {
|
1471 |
+
switch (matches[2] || "d") {
|
1472 |
+
case "d" : case "D" :
|
1473 |
+
day += parseInt(matches[1],10); break;
|
1474 |
+
case "w" : case "W" :
|
1475 |
+
day += parseInt(matches[1],10) * 7; break;
|
1476 |
+
case "m" : case "M" :
|
1477 |
+
month += parseInt(matches[1],10);
|
1478 |
+
day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
|
1479 |
+
break;
|
1480 |
+
case "y": case "Y" :
|
1481 |
+
year += parseInt(matches[1],10);
|
1482 |
+
day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
|
1483 |
+
break;
|
1484 |
+
}
|
1485 |
+
matches = pattern.exec(offset);
|
1486 |
+
}
|
1487 |
+
return new Date(year, month, day);
|
1488 |
+
},
|
1489 |
+
newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
|
1490 |
+
(typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
|
1491 |
+
|
1492 |
+
newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
|
1493 |
+
if (newDate) {
|
1494 |
+
newDate.setHours(0);
|
1495 |
+
newDate.setMinutes(0);
|
1496 |
+
newDate.setSeconds(0);
|
1497 |
+
newDate.setMilliseconds(0);
|
1498 |
+
}
|
1499 |
+
return this._daylightSavingAdjust(newDate);
|
1500 |
+
},
|
1501 |
+
|
1502 |
+
/* Handle switch to/from daylight saving.
|
1503 |
+
* Hours may be non-zero on daylight saving cut-over:
|
1504 |
+
* > 12 when midnight changeover, but then cannot generate
|
1505 |
+
* midnight datetime, so jump to 1AM, otherwise reset.
|
1506 |
+
* @param date (Date) the date to check
|
1507 |
+
* @return (Date) the corrected date
|
1508 |
+
*/
|
1509 |
+
_daylightSavingAdjust: function(date) {
|
1510 |
+
if (!date) {
|
1511 |
+
return null;
|
1512 |
+
}
|
1513 |
+
date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
|
1514 |
+
return date;
|
1515 |
+
},
|
1516 |
+
|
1517 |
+
/* Set the date(s) directly. */
|
1518 |
+
_setDate: function(inst, date, noChange) {
|
1519 |
+
var clear = !date,
|
1520 |
+
origMonth = inst.selectedMonth,
|
1521 |
+
origYear = inst.selectedYear,
|
1522 |
+
newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
|
1523 |
+
|
1524 |
+
inst.selectedDay = inst.currentDay = newDate.getDate();
|
1525 |
+
inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
|
1526 |
+
inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
|
1527 |
+
if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
|
1528 |
+
this._notifyChange(inst);
|
1529 |
+
}
|
1530 |
+
this._adjustInstDate(inst);
|
1531 |
+
if (inst.input) {
|
1532 |
+
inst.input.val(clear ? "" : this._formatDate(inst));
|
1533 |
+
}
|
1534 |
+
},
|
1535 |
+
|
1536 |
+
/* Retrieve the date(s) directly. */
|
1537 |
+
_getDate: function(inst) {
|
1538 |
+
var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
|
1539 |
+
this._daylightSavingAdjust(new Date(
|
1540 |
+
inst.currentYear, inst.currentMonth, inst.currentDay)));
|
1541 |
+
return startDate;
|
1542 |
+
},
|
1543 |
+
|
1544 |
+
/* Attach the onxxx handlers. These are declared statically so
|
1545 |
+
* they work with static code transformers like Caja.
|
1546 |
+
*/
|
1547 |
+
_attachHandlers: function(inst) {
|
1548 |
+
var stepMonths = this._get(inst, "stepMonths"),
|
1549 |
+
id = "#" + inst.id.replace( /\\\\/g, "\\" );
|
1550 |
+
inst.dpDiv.find("[data-handler]").map(function () {
|
1551 |
+
var handler = {
|
1552 |
+
prev: function () {
|
1553 |
+
$.datepicker._adjustDate(id, -stepMonths, "M");
|
1554 |
+
},
|
1555 |
+
next: function () {
|
1556 |
+
$.datepicker._adjustDate(id, +stepMonths, "M");
|
1557 |
+
},
|
1558 |
+
hide: function () {
|
1559 |
+
$.datepicker._hideDatepicker();
|
1560 |
+
},
|
1561 |
+
today: function () {
|
1562 |
+
$.datepicker._gotoToday(id);
|
1563 |
+
},
|
1564 |
+
selectDay: function () {
|
1565 |
+
$.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
|
1566 |
+
return false;
|
1567 |
+
},
|
1568 |
+
selectMonth: function () {
|
1569 |
+
$.datepicker._selectMonthYear(id, this, "M");
|
1570 |
+
return false;
|
1571 |
+
},
|
1572 |
+
selectYear: function () {
|
1573 |
+
$.datepicker._selectMonthYear(id, this, "Y");
|
1574 |
+
return false;
|
1575 |
+
}
|
1576 |
+
};
|
1577 |
+
$(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
|
1578 |
+
});
|
1579 |
+
},
|
1580 |
+
|
1581 |
+
/* Generate the HTML for the current state of the date picker. */
|
1582 |
+
_generateHTML: function(inst) {
|
1583 |
+
var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
|
1584 |
+
controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
|
1585 |
+
monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
|
1586 |
+
selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
|
1587 |
+
cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
|
1588 |
+
printDate, dRow, tbody, daySettings, otherMonth, unselectable,
|
1589 |
+
tempDate = new Date(),
|
1590 |
+
today = this._daylightSavingAdjust(
|
1591 |
+
new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
|
1592 |
+
isRTL = this._get(inst, "isRTL"),
|
1593 |
+
showButtonPanel = this._get(inst, "showButtonPanel"),
|
1594 |
+
hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
|
1595 |
+
navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
|
1596 |
+
numMonths = this._getNumberOfMonths(inst),
|
1597 |
+
showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
|
1598 |
+
stepMonths = this._get(inst, "stepMonths"),
|
1599 |
+
isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
|
1600 |
+
currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
|
1601 |
+
new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
|
1602 |
+
minDate = this._getMinMaxDate(inst, "min"),
|
1603 |
+
maxDate = this._getMinMaxDate(inst, "max"),
|
1604 |
+
drawMonth = inst.drawMonth - showCurrentAtPos,
|
1605 |
+
drawYear = inst.drawYear;
|
1606 |
+
|
1607 |
+
if (drawMonth < 0) {
|
1608 |
+
drawMonth += 12;
|
1609 |
+
drawYear--;
|
1610 |
+
}
|
1611 |
+
if (maxDate) {
|
1612 |
+
maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
|
1613 |
+
maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
|
1614 |
+
maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
|
1615 |
+
while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
|
1616 |
+
drawMonth--;
|
1617 |
+
if (drawMonth < 0) {
|
1618 |
+
drawMonth = 11;
|
1619 |
+
drawYear--;
|
1620 |
+
}
|
1621 |
+
}
|
1622 |
+
}
|
1623 |
+
inst.drawMonth = drawMonth;
|
1624 |
+
inst.drawYear = drawYear;
|
1625 |
+
|
1626 |
+
prevText = this._get(inst, "prevText");
|
1627 |
+
prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
|
1628 |
+
this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
|
1629 |
+
this._getFormatConfig(inst)));
|
1630 |
+
|
1631 |
+
prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
|
1632 |
+
"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
|
1633 |
+
" title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
|
1634 |
+
(hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ prevText +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>"));
|
1635 |
+
|
1636 |
+
nextText = this._get(inst, "nextText");
|
1637 |
+
nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
|
1638 |
+
this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
|
1639 |
+
this._getFormatConfig(inst)));
|
1640 |
+
|
1641 |
+
next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
|
1642 |
+
"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
|
1643 |
+
" title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
|
1644 |
+
(hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>"));
|
1645 |
+
|
1646 |
+
currentText = this._get(inst, "currentText");
|
1647 |
+
gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
|
1648 |
+
currentText = (!navigationAsDateFormat ? currentText :
|
1649 |
+
this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
|
1650 |
+
|
1651 |
+
controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
|
1652 |
+
this._get(inst, "closeText") + "</button>" : "");
|
1653 |
+
|
1654 |
+
buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
|
1655 |
+
(this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
|
1656 |
+
">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
|
1657 |
+
|
1658 |
+
firstDay = parseInt(this._get(inst, "firstDay"),10);
|
1659 |
+
firstDay = (isNaN(firstDay) ? 0 : firstDay);
|
1660 |
+
|
1661 |
+
showWeek = this._get(inst, "showWeek");
|
1662 |
+
dayNames = this._get(inst, "dayNames");
|
1663 |
+
dayNamesMin = this._get(inst, "dayNamesMin");
|
1664 |
+
monthNames = this._get(inst, "monthNames");
|
1665 |
+
monthNamesShort = this._get(inst, "monthNamesShort");
|
1666 |
+
beforeShowDay = this._get(inst, "beforeShowDay");
|
1667 |
+
showOtherMonths = this._get(inst, "showOtherMonths");
|
1668 |
+
selectOtherMonths = this._get(inst, "selectOtherMonths");
|
1669 |
+
defaultDate = this._getDefaultDate(inst);
|
1670 |
+
html = "";
|
1671 |
+
dow;
|
1672 |
+
for (row = 0; row < numMonths[0]; row++) {
|
1673 |
+
group = "";
|
1674 |
+
this.maxRows = 4;
|
1675 |
+
for (col = 0; col < numMonths[1]; col++) {
|
1676 |
+
selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
|
1677 |
+
cornerClass = " ui-corner-all";
|
1678 |
+
calender = "";
|
1679 |
+
if (isMultiMonth) {
|
1680 |
+
calender += "<div class='ui-datepicker-group";
|
1681 |
+
if (numMonths[1] > 1) {
|
1682 |
+
switch (col) {
|
1683 |
+
case 0: calender += " ui-datepicker-group-first";
|
1684 |
+
cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
|
1685 |
+
case numMonths[1]-1: calender += " ui-datepicker-group-last";
|
1686 |
+
cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
|
1687 |
+
default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
|
1688 |
+
}
|
1689 |
+
}
|
1690 |
+
calender += "'>";
|
1691 |
+
}
|
1692 |
+
calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
|
1693 |
+
(/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
|
1694 |
+
(/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
|
1695 |
+
this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
|
1696 |
+
row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
|
1697 |
+
"</div><table class='ui-datepicker-calendar'><thead>" +
|
1698 |
+
"<tr>";
|
1699 |
+
thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
|
1700 |
+
for (dow = 0; dow < 7; dow++) { // days of the week
|
1701 |
+
day = (dow + firstDay) % 7;
|
1702 |
+
thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
|
1703 |
+
"<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
|
1704 |
+
}
|
1705 |
+
calender += thead + "</tr></thead><tbody>";
|
1706 |
+
daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
|
1707 |
+
if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
|
1708 |
+
inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
|
1709 |
+
}
|
1710 |
+
leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
|
1711 |
+
curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
|
1712 |
+
numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
|
1713 |
+
this.maxRows = numRows;
|
1714 |
+
printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
|
1715 |
+
for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
|
1716 |
+
calender += "<tr>";
|
1717 |
+
tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
|
1718 |
+
this._get(inst, "calculateWeek")(printDate) + "</td>");
|
1719 |
+
for (dow = 0; dow < 7; dow++) { // create date picker days
|
1720 |
+
daySettings = (beforeShowDay ?
|
1721 |
+
beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
|
1722 |
+
otherMonth = (printDate.getMonth() !== drawMonth);
|
1723 |
+
unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
|
1724 |
+
(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
|
1725 |
+
tbody += "<td class='" +
|
1726 |
+
((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
|
1727 |
+
(otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
|
1728 |
+
((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
|
1729 |
+
(defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
|
1730 |
+
// or defaultDate is current printedDate and defaultDate is selectedDate
|
1731 |
+
" " + this._dayOverClass : "") + // highlight selected day
|
1732 |
+
(unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days
|
1733 |
+
(otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
|
1734 |
+
(printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
|
1735 |
+
(printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
|
1736 |
+
((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "'") + "'" : "") + // cell title
|
1737 |
+
(unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
|
1738 |
+
(otherMonth && !showOtherMonths ? " " : // display for other months
|
1739 |
+
(unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
|
1740 |
+
(printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
|
1741 |
+
(printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
|
1742 |
+
(otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
|
1743 |
+
"' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
|
1744 |
+
printDate.setDate(printDate.getDate() + 1);
|
1745 |
+
printDate = this._daylightSavingAdjust(printDate);
|
1746 |
+
}
|
1747 |
+
calender += tbody + "</tr>";
|
1748 |
+
}
|
1749 |
+
drawMonth++;
|
1750 |
+
if (drawMonth > 11) {
|
1751 |
+
drawMonth = 0;
|
1752 |
+
drawYear++;
|
1753 |
+
}
|
1754 |
+
calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
|
1755 |
+
((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
|
1756 |
+
group += calender;
|
1757 |
+
}
|
1758 |
+
html += group;
|
1759 |
+
}
|
1760 |
+
html += buttonPanel;
|
1761 |
+
inst._keyEvent = false;
|
1762 |
+
return html;
|
1763 |
+
},
|
1764 |
+
|
1765 |
+
/* Generate the month and year header. */
|
1766 |
+
_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
|
1767 |
+
secondary, monthNames, monthNamesShort) {
|
1768 |
+
|
1769 |
+
var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
|
1770 |
+
changeMonth = this._get(inst, "changeMonth"),
|
1771 |
+
changeYear = this._get(inst, "changeYear"),
|
1772 |
+
showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
|
1773 |
+
html = "<div class='ui-datepicker-title'>",
|
1774 |
+
monthHtml = "";
|
1775 |
+
|
1776 |
+
// month selection
|
1777 |
+
if (secondary || !changeMonth) {
|
1778 |
+
monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
|
1779 |
+
} else {
|
1780 |
+
inMinYear = (minDate && minDate.getFullYear() === drawYear);
|
1781 |
+
inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
|
1782 |
+
monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
|
1783 |
+
for ( month = 0; month < 12; month++) {
|
1784 |
+
if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
|
1785 |
+
monthHtml += "<option value='" + month + "'" +
|
1786 |
+
(month === drawMonth ? " selected='selected'" : "") +
|
1787 |
+
">" + monthNamesShort[month] + "</option>";
|
1788 |
+
}
|
1789 |
+
}
|
1790 |
+
monthHtml += "</select>";
|
1791 |
+
}
|
1792 |
+
|
1793 |
+
if (!showMonthAfterYear) {
|
1794 |
+
html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : "");
|
1795 |
+
}
|
1796 |
+
|
1797 |
+
// year selection
|
1798 |
+
if ( !inst.yearshtml ) {
|
1799 |
+
inst.yearshtml = "";
|
1800 |
+
if (secondary || !changeYear) {
|
1801 |
+
html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
|
1802 |
+
} else {
|
1803 |
+
// determine range of years to display
|
1804 |
+
years = this._get(inst, "yearRange").split(":");
|
1805 |
+
thisYear = new Date().getFullYear();
|
1806 |
+
determineYear = function(value) {
|
1807 |
+
var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
|
1808 |
+
(value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
|
1809 |
+
parseInt(value, 10)));
|
1810 |
+
return (isNaN(year) ? thisYear : year);
|
1811 |
+
};
|
1812 |
+
year = determineYear(years[0]);
|
1813 |
+
endYear = Math.max(year, determineYear(years[1] || ""));
|
1814 |
+
year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
|
1815 |
+
endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
|
1816 |
+
inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
|
1817 |
+
for (; year <= endYear; year++) {
|
1818 |
+
inst.yearshtml += "<option value='" + year + "'" +
|
1819 |
+
(year === drawYear ? " selected='selected'" : "") +
|
1820 |
+
">" + year + "</option>";
|
1821 |
+
}
|
1822 |
+
inst.yearshtml += "</select>";
|
1823 |
+
|
1824 |
+
html += inst.yearshtml;
|
1825 |
+
inst.yearshtml = null;
|
1826 |
+
}
|
1827 |
+
}
|
1828 |
+
|
1829 |
+
html += this._get(inst, "yearSuffix");
|
1830 |
+
if (showMonthAfterYear) {
|
1831 |
+
html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml;
|
1832 |
+
}
|
1833 |
+
html += "</div>"; // Close datepicker_header
|
1834 |
+
return html;
|
1835 |
+
},
|
1836 |
+
|
1837 |
+
/* Adjust one of the date sub-fields. */
|
1838 |
+
_adjustInstDate: function(inst, offset, period) {
|
1839 |
+
var year = inst.drawYear + (period === "Y" ? offset : 0),
|
1840 |
+
month = inst.drawMonth + (period === "M" ? offset : 0),
|
1841 |
+
day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
|
1842 |
+
date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
|
1843 |
+
|
1844 |
+
inst.selectedDay = date.getDate();
|
1845 |
+
inst.drawMonth = inst.selectedMonth = date.getMonth();
|
1846 |
+
inst.drawYear = inst.selectedYear = date.getFullYear();
|
1847 |
+
if (period === "M" || period === "Y") {
|
1848 |
+
this._notifyChange(inst);
|
1849 |
+
}
|
1850 |
+
},
|
1851 |
+
|
1852 |
+
/* Ensure a date is within any min/max bounds. */
|
1853 |
+
_restrictMinMax: function(inst, date) {
|
1854 |
+
var minDate = this._getMinMaxDate(inst, "min"),
|
1855 |
+
maxDate = this._getMinMaxDate(inst, "max"),
|
1856 |
+
newDate = (minDate && date < minDate ? minDate : date);
|
1857 |
+
return (maxDate && newDate > maxDate ? maxDate : newDate);
|
1858 |
+
},
|
1859 |
+
|
1860 |
+
/* Notify change of month/year. */
|
1861 |
+
_notifyChange: function(inst) {
|
1862 |
+
var onChange = this._get(inst, "onChangeMonthYear");
|
1863 |
+
if (onChange) {
|
1864 |
+
onChange.apply((inst.input ? inst.input[0] : null),
|
1865 |
+
[inst.selectedYear, inst.selectedMonth + 1, inst]);
|
1866 |
+
}
|
1867 |
+
},
|
1868 |
+
|
1869 |
+
/* Determine the number of months to show. */
|
1870 |
+
_getNumberOfMonths: function(inst) {
|
1871 |
+
var numMonths = this._get(inst, "numberOfMonths");
|
1872 |
+
return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
|
1873 |
+
},
|
1874 |
+
|
1875 |
+
/* Determine the current maximum date - ensure no time components are set. */
|
1876 |
+
_getMinMaxDate: function(inst, minMax) {
|
1877 |
+
return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
|
1878 |
+
},
|
1879 |
+
|
1880 |
+
/* Find the number of days in a given month. */
|
1881 |
+
_getDaysInMonth: function(year, month) {
|
1882 |
+
return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
|
1883 |
+
},
|
1884 |
+
|
1885 |
+
/* Find the day of the week of the first of a month. */
|
1886 |
+
_getFirstDayOfMonth: function(year, month) {
|
1887 |
+
return new Date(year, month, 1).getDay();
|
1888 |
+
},
|
1889 |
+
|
1890 |
+
/* Determines if we should allow a "next/prev" month display change. */
|
1891 |
+
_canAdjustMonth: function(inst, offset, curYear, curMonth) {
|
1892 |
+
var numMonths = this._getNumberOfMonths(inst),
|
1893 |
+
date = this._daylightSavingAdjust(new Date(curYear,
|
1894 |
+
curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
|
1895 |
+
|
1896 |
+
if (offset < 0) {
|
1897 |
+
date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
|
1898 |
+
}
|
1899 |
+
return this._isInRange(inst, date);
|
1900 |
+
},
|
1901 |
+
|
1902 |
+
/* Is the given date in the accepted range? */
|
1903 |
+
_isInRange: function(inst, date) {
|
1904 |
+
var yearSplit, currentYear,
|
1905 |
+
minDate = this._getMinMaxDate(inst, "min"),
|
1906 |
+
maxDate = this._getMinMaxDate(inst, "max"),
|
1907 |
+
minYear = null,
|
1908 |
+
maxYear = null,
|
1909 |
+
years = this._get(inst, "yearRange");
|
1910 |
+
if (years){
|
1911 |
+
yearSplit = years.split(":");
|
1912 |
+
currentYear = new Date().getFullYear();
|
1913 |
+
minYear = parseInt(yearSplit[0], 10);
|
1914 |
+
maxYear = parseInt(yearSplit[1], 10);
|
1915 |
+
if ( yearSplit[0].match(/[+\-].*/) ) {
|
1916 |
+
minYear += currentYear;
|
1917 |
+
}
|
1918 |
+
if ( yearSplit[1].match(/[+\-].*/) ) {
|
1919 |
+
maxYear += currentYear;
|
1920 |
+
}
|
1921 |
+
}
|
1922 |
+
|
1923 |
+
return ((!minDate || date.getTime() >= minDate.getTime()) &&
|
1924 |
+
(!maxDate || date.getTime() <= maxDate.getTime()) &&
|
1925 |
+
(!minYear || date.getFullYear() >= minYear) &&
|
1926 |
+
(!maxYear || date.getFullYear() <= maxYear));
|
1927 |
+
},
|
1928 |
+
|
1929 |
+
/* Provide the configuration settings for formatting/parsing. */
|
1930 |
+
_getFormatConfig: function(inst) {
|
1931 |
+
var shortYearCutoff = this._get(inst, "shortYearCutoff");
|
1932 |
+
shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
|
1933 |
+
new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
|
1934 |
+
return {shortYearCutoff: shortYearCutoff,
|
1935 |
+
dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
|
1936 |
+
monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
|
1937 |
+
},
|
1938 |
+
|
1939 |
+
/* Format the given date for display. */
|
1940 |
+
_formatDate: function(inst, day, month, year) {
|
1941 |
+
if (!day) {
|
1942 |
+
inst.currentDay = inst.selectedDay;
|
1943 |
+
inst.currentMonth = inst.selectedMonth;
|
1944 |
+
inst.currentYear = inst.selectedYear;
|
1945 |
+
}
|
1946 |
+
var date = (day ? (typeof day === "object" ? day :
|
1947 |
+
this._daylightSavingAdjust(new Date(year, month, day))) :
|
1948 |
+
this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
|
1949 |
+
return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
|
1950 |
+
}
|
1951 |
+
});
|
1952 |
+
|
1953 |
+
/*
|
1954 |
+
* Bind hover events for datepicker elements.
|
1955 |
+
* Done via delegate so the binding only occurs once in the lifetime of the parent div.
|
1956 |
+
* Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
|
1957 |
+
*/
|
1958 |
+
function bindHover(dpDiv) {
|
1959 |
+
var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
|
1960 |
+
return dpDiv.delegate(selector, "mouseout", function() {
|
1961 |
+
$(this).removeClass("ui-state-hover");
|
1962 |
+
if (this.className.indexOf("ui-datepicker-prev") !== -1) {
|
1963 |
+
$(this).removeClass("ui-datepicker-prev-hover");
|
1964 |
+
}
|
1965 |
+
if (this.className.indexOf("ui-datepicker-next") !== -1) {
|
1966 |
+
$(this).removeClass("ui-datepicker-next-hover");
|
1967 |
+
}
|
1968 |
+
})
|
1969 |
+
.delegate(selector, "mouseover", function(){
|
1970 |
+
if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
|
1971 |
+
$(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
|
1972 |
+
$(this).addClass("ui-state-hover");
|
1973 |
+
if (this.className.indexOf("ui-datepicker-prev") !== -1) {
|
1974 |
+
$(this).addClass("ui-datepicker-prev-hover");
|
1975 |
+
}
|
1976 |
+
if (this.className.indexOf("ui-datepicker-next") !== -1) {
|
1977 |
+
$(this).addClass("ui-datepicker-next-hover");
|
1978 |
+
}
|
1979 |
+
}
|
1980 |
+
});
|
1981 |
+
}
|
1982 |
+
|
1983 |
+
/* jQuery extend now ignores nulls! */
|
1984 |
+
function extendRemove(target, props) {
|
1985 |
+
$.extend(target, props);
|
1986 |
+
for (var name in props) {
|
1987 |
+
if (props[name] == null) {
|
1988 |
+
target[name] = props[name];
|
1989 |
+
}
|
1990 |
+
}
|
1991 |
+
return target;
|
1992 |
+
}
|
1993 |
+
|
1994 |
+
/* Invoke the datepicker functionality.
|
1995 |
+
@param options string - a command, optionally followed by additional parameters or
|
1996 |
+
Object - settings for attaching new datepicker functionality
|
1997 |
+
@return jQuery object */
|
1998 |
+
$.fn.datepicker = function(options){
|
1999 |
+
|
2000 |
+
/* Verify an empty collection wasn't passed - Fixes #6976 */
|
2001 |
+
if ( !this.length ) {
|
2002 |
+
return this;
|
2003 |
+
}
|
2004 |
+
|
2005 |
+
/* Initialise the date picker. */
|
2006 |
+
if (!$.datepicker.initialized) {
|
2007 |
+
$(document).mousedown($.datepicker._checkExternalClick);
|
2008 |
+
$.datepicker.initialized = true;
|
2009 |
+
}
|
2010 |
+
|
2011 |
+
/* Append datepicker main container to body if not exist. */
|
2012 |
+
if ($("#"+$.datepicker._mainDivId).length === 0) {
|
2013 |
+
$("body").append($.datepicker.dpDiv);
|
2014 |
+
}
|
2015 |
+
|
2016 |
+
var otherArgs = Array.prototype.slice.call(arguments, 1);
|
2017 |
+
if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
|
2018 |
+
return $.datepicker["_" + options + "Datepicker"].
|
2019 |
+
apply($.datepicker, [this[0]].concat(otherArgs));
|
2020 |
+
}
|
2021 |
+
if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
|
2022 |
+
return $.datepicker["_" + options + "Datepicker"].
|
2023 |
+
apply($.datepicker, [this[0]].concat(otherArgs));
|
2024 |
+
}
|
2025 |
+
return this.each(function() {
|
2026 |
+
typeof options === "string" ?
|
2027 |
+
$.datepicker["_" + options + "Datepicker"].
|
2028 |
+
apply($.datepicker, [this].concat(otherArgs)) :
|
2029 |
+
$.datepicker._attachDatepicker(this, options);
|
2030 |
+
});
|
2031 |
+
};
|
2032 |
+
|
2033 |
+
$.datepicker = new Datepicker(); // singleton instance
|
2034 |
+
$.datepicker.initialized = false;
|
2035 |
+
$.datepicker.uuid = new Date().getTime();
|
2036 |
+
$.datepicker.version = "1.10.4";
|
2037 |
+
|
2038 |
+
})(jQuery);
|
lib/cmb_metaboxes/js/jquery.timePicker.min.js
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* A time picker for jQuery.
|
3 |
+
*
|
4 |
+
* Dual licensed under the MIT and GPL licenses.
|
5 |
+
* Copyright (c) 2009 Anders Fajerson
|
6 |
+
*
|
7 |
+
* @name timePicker
|
8 |
+
* @author Anders Fajerson (http://perifer.se)
|
9 |
+
* @see http://github.com/perifer/timePicker
|
10 |
+
* @example $("#mytime").timePicker();
|
11 |
+
* @example $("#mytime").timePicker({step:30, startTime:"15:00", endTime:"18:00"});
|
12 |
+
*/
|
13 |
+
(function(a){function g(a){a.setFullYear(2001),a.setMonth(0),a.setDate(0);return a}function f(a,b){if(a){var c=a.split(b.separator),d=parseFloat(c[0]),e=parseFloat(c[1]);b.show24Hours||(d===12&&a.indexOf("AM")!==-1?d=0:d!==12&&a.indexOf("PM")!==-1&&(d+=12));var f=new Date(0,0,0,d,e,0);return g(f)}return null}function e(a,b){return typeof a=="object"?g(a):f(a,b)}function d(a){return(a<10?"0":"")+a}function c(a,b){var c=a.getHours(),e=b.show24Hours?c:(c+11)%12+1,f=a.getMinutes();return d(e)+b.separator+d(f)+(b.show24Hours?"":c<12?" AM":" PM")}function b(b,c,d,e){b.value=a(c).text(),a(b).change(),a.browser.msie||b.focus(),d.hide()}a.fn.timePicker=function(b){var c=a.extend({},a.fn.timePicker.defaults,b);return this.each(function(){a.timePicker(this,c)})},a.timePicker=function(b,c){var d=a(b)[0];return d.timePicker||(d.timePicker=new jQuery._timePicker(d,c))},a.timePicker.version="0.3",a._timePicker=function(d,h){var i=!1,j=!1,k=e(h.startTime,h),l=e(h.endTime,h),m="selected",n="li."+m;a(d).attr("autocomplete","OFF");var o=[],p=new Date(k);while(p<=l)o[o.length]=c(p,h),p=new Date(p.setMinutes(p.getMinutes()+h.step));var q=a('<div class="time-picker'+(h.show24Hours?"":" time-picker-12hours")+'"></div>'),r=a("<ul></ul>");for(var s=0;s<o.length;s++)r.append("<li>"+o[s]+"</li>");q.append(r),q.appendTo("body").hide(),q.mouseover(function(){i=!0}).mouseout(function(){i=!1}),a("li",r).mouseover(function(){j||(a(n,q).removeClass(m),a(this).addClass(m))}).mousedown(function(){i=!0}).click(function(){b(d,this,q,h),i=!1});var t=function(){if(q.is(":visible"))return!1;a("li",q).removeClass(m);var b=a(d).offset();q.css({top:b.top+d.offsetHeight,left:b.left}),q.show();var e=d.value?f(d.value,h):k,i=k.getHours()*60+k.getMinutes(),j=e.getHours()*60+e.getMinutes()-i,n=Math.round(j/h.step),o=g(new Date(0,0,0,0,n*h.step+i,0));o=k<o&&o<=l?o:k;var p=a("li:contains("+c(o,h)+")",q);p.length&&(p.addClass(m),q[0].scrollTop=p[0].offsetTop);return!0};a(d).focus(t).click(t),a(d).blur(function(){i||q.hide()});var u=a.browser.opera||a.browser.mozilla?"keypress":"keydown";a(d)[u](function(c){var e;j=!0;var f=q[0].scrollTop;switch(c.keyCode){case 38:if(t())return!1;e=a(n,r);var g=e.prev().addClass(m)[0];g?(e.removeClass(m),g.offsetTop<f&&(q[0].scrollTop=f-g.offsetHeight)):(e.removeClass(m),g=a("li:last",r).addClass(m)[0],q[0].scrollTop=g.offsetTop-g.offsetHeight);return!1;case 40:if(t())return!1;e=a(n,r);var i=e.next().addClass(m)[0];i?(e.removeClass(m),i.offsetTop+i.offsetHeight>f+q[0].offsetHeight&&(q[0].scrollTop=f+i.offsetHeight)):(e.removeClass(m),i=a("li:first",r).addClass(m)[0],q[0].scrollTop=0);return!1;case 13:if(q.is(":visible")){var k=a(n,r)[0];b(d,k,q,h)}return!1;case 27:q.hide();return!1}return!0}),a(d).keyup(function(a){j=!1}),this.getTime=function(){return f(d.value,h)},this.setTime=function(b){d.value=c(e(b,h),h),a(d).change()}},a.fn.timePicker.defaults={step:30,startTime:new Date(0,0,0,0,0,0),endTime:new Date(0,0,0,23,30,0),separator:":",show24Hours:!0}})(jQuery)
|
lib/cmb_metaboxes/readme.md
ADDED
@@ -0,0 +1,296 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Custom Metaboxes and Fields for WordPress
|
2 |
+
|
3 |
+
**Contributors**:
|
4 |
+
|
5 |
+
* WebDevStudios ( [@webdevstudios](http://twitter.com/webdevstudios ) / [webdevstudios.com](http://webdevstudios.com) )
|
6 |
+
* Justin Sternberg ( [@jtsternberg](http://twitter.com/jtsternberg ) / [webdevstudios.com](http://webdevstudios.com) )
|
7 |
+
* Jared Atchison ( [@jaredatch](http://twitter.com/jaredatch ) / [jaredatchison.com](http://jaredatchison.com/) )
|
8 |
+
* Bill Erickson ( [@billerickson](http://twitter.com/billerickson ) / [billerickson.net](http://billerickson.net/) )
|
9 |
+
* Andrew Norcross ( [@norcross](http://twitter.com/norcross ) / [andrewnorcross.com](http://andrewnorcross.com/) )
|
10 |
+
|
11 |
+
**Version**: 1.2.0
|
12 |
+
**Requires at least**: 3.5
|
13 |
+
**Tested up to**: 3.9
|
14 |
+
**License**: GPLv2
|
15 |
+
|
16 |
+
## Description
|
17 |
+
|
18 |
+
Custom Metaboxes and Fields (CMB for short) will create metaboxes and forms with custom fields that will blow your mind.
|
19 |
+
|
20 |
+
##### Features:
|
21 |
+
|
22 |
+
* Create metaboxes to be used on post edit screens.
|
23 |
+
* Create forms to be used on options pages.
|
24 |
+
* Create forms to handle user meta and display them on user profile add/edit pages.
|
25 |
+
* Flexible API that allows you to use CMB forms almost anywhere, even on the front-end.
|
26 |
+
* Several field types are included and are [listed below](#field-types).
|
27 |
+
* Custom API hook that allows you to create your own field types.
|
28 |
+
* There are numerous hooks and filters, allowing you to modify many aspects of the library (without editing it directly).
|
29 |
+
* Repeatable fields for most field types are supported, as well as repeatable field groups.
|
30 |
+
|
31 |
+
##### Field Types:
|
32 |
+
1. [`title`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#title) An arbitrary title field *
|
33 |
+
1. [`text`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text)
|
34 |
+
1. [`text_small`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_small)
|
35 |
+
1. [`text_medium`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_medium)
|
36 |
+
1. [`text_email`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_email)
|
37 |
+
1. [`text_url`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_url)
|
38 |
+
1. [`text_money`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_money)
|
39 |
+
1. [`textarea`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#textarea)
|
40 |
+
1. [`textarea_small`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#textarea_small)
|
41 |
+
1. [`textarea_code`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#textarea_code)
|
42 |
+
1. [`text_date`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_date) Date Picker
|
43 |
+
1. [`text_time`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_time) Time picker
|
44 |
+
1. [`select_timezone`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#select_timezone) Time zone dropdown
|
45 |
+
1. [`text_date_timestamp`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_date_timestamp) Date Picker (UNIX timestamp)
|
46 |
+
1. [`text_datetime_timestamp`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_datetime_timestamp) Test Date/Time Picker Combo (UNIX timestamp)
|
47 |
+
1. [`text_datetime_timestamp_timezone`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_datetime_timestamp_timezone) Test Date/Time Picker/Time zone Combo (serialized DateTime object)
|
48 |
+
1. [`colorpicker`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#colorpicker) Color picker
|
49 |
+
1. [`radio`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#radio) *
|
50 |
+
1. [`radio_inline`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#radio_inline) *
|
51 |
+
1. [`taxonomy_radio`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#taxonomy_radio) *
|
52 |
+
1. [`taxonomy_radio_inline`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#taxonomy_radio_inline) *
|
53 |
+
1. [`select`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#select)
|
54 |
+
1. [`taxonomy_select`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#taxonomy_select) *
|
55 |
+
1. [`checkbox`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#checkbox) *
|
56 |
+
1. [`multicheck`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#multicheck)
|
57 |
+
1. [`taxonomy_multicheck`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#taxonomy_multicheck) *
|
58 |
+
1. [`taxonomy_multicheck_inline`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#taxonomy_multicheck_inline)
|
59 |
+
1. [`wysiwyg`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#wysiwyg) (TinyMCE) *
|
60 |
+
1. [`file`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#file) Image/File upload *†
|
61 |
+
1. [`file_list`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#file_list) Image/File list upload
|
62 |
+
1. [`oembed`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#oembed) Converts oembed urls (instagram, twitter, youtube, etc. [oEmbed in the Codex](https://codex.wordpress.org/Embeds))
|
63 |
+
1. [`group`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#group) Hybrid field that supports adding other fields as a repeatable group. *
|
64 |
+
1. [Create your own custom field type](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#Custom)
|
65 |
+
|
66 |
+
\* Not available as a repeatable field
|
67 |
+
† Use `file_list` for repeatable
|
68 |
+
|
69 |
+
[More on field types (GitHub wiki)](https://github.com/webdevstudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types)
|
70 |
+
|
71 |
+
##### 3rd Party Resources
|
72 |
+
* [CMB Attached Posts Field](https://github.com/coreymcollins/cmb-attached-posts) from [coreymcollins](https://github.com/coreymcollins): Custom field type for attaching posts to a page.
|
73 |
+
* [CMB Field Type: Google Maps](https://github.com/mustardBees/cmb_field_map) from [mustardBees](https://github.com/mustardBees): Custom field type for Google Maps.
|
74 |
+
> The `pw_map` field stores the latitude/longitude values which you can then use to display a map in your theme.
|
75 |
+
* [CMB Field Type: Select2](https://github.com/mustardBees/cmb-field-select2) from [mustardBees](https://github.com/mustardBees): Custom field types which use the [Select2](http://ivaynberg.github.io/select2/) script:
|
76 |
+
|
77 |
+
> 1. The `pw_select field` acts much like the default select field. However, it adds typeahead-style search allowing you to quickly make a selection from a large list
|
78 |
+
> 2. The `pw_multiselect` field allows you to select multiple values with typeahead-style search. The values can be dragged and dropped to reorder
|
79 |
+
* [Taxonomy_MetaData](https://github.com/jtsternberg/Taxonomy_MetaData#to-use-taxonomy_metadata-with-custom-metaboxes-and-fields): WordPress Helper Class for saving pseudo-metadata for taxonomy terms. Includes an extended class for using CMB to generate the actual form fields.
|
80 |
+
|
81 |
+
##### Contribution
|
82 |
+
All contributions welcome. If you would like to submit a pull request, please check out the [trunk branch](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/tree/trunk) and pull request against it.
|
83 |
+
|
84 |
+
##### Links
|
85 |
+
* [Github project page](https://github.com/webdevstudios/Custom-Metaboxes-and-Fields-for-WordPress)
|
86 |
+
* [Documentation (GitHub wiki)](https://github.com/webdevstudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki)
|
87 |
+
|
88 |
+
|
89 |
+
## Installation
|
90 |
+
|
91 |
+
1. Place the CMB directory inside of your theme or plugin.
|
92 |
+
2. Copy (and rename if desired) `example-functions.php` into a folder *above* the CMB directory OR copy the entirety of its contents to your theme's `functions.php` file.
|
93 |
+
2. Edit to only include the fields you need and rename the functions (CMB directory should be left unedited in order to easily update the library).
|
94 |
+
4. Profit.
|
95 |
+
|
96 |
+
## Changelog
|
97 |
+
|
98 |
+
### 1.2.0
|
99 |
+
|
100 |
+
**Enhancements**
|
101 |
+
|
102 |
+
* Add support for custom date/time formats. Props [@Scrent](https://github.com/Scrent). ([#506](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/506))
|
103 |
+
* Simplify `wysiwyg` escaping and allow it to be overridden via the `escape_cb` parameter. ([#491](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/491))
|
104 |
+
* Add a 'Select/Deselect all' button for the `multicheck` field type.
|
105 |
+
* Add title option for [repeatable groups](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#group). Title field takes an optional replacement hash, "{#}" that will be replaced by the row number.
|
106 |
+
* New field parameter, `show_on_cb`, allows you to conditionally display a field via a callback. ([#47](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/47))
|
107 |
+
* Unit testing (the beginning). Props [@brichards](https://github.com/brichards) and [@camdensegal](https://github.com/camdensegal).
|
108 |
+
|
109 |
+
**Bug Fixes**
|
110 |
+
|
111 |
+
* Fixed issue where remove file button wouldn't clear the url field. ([#514](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/514))
|
112 |
+
* `wysiwyg` fields now allow underscores. Fixes some wysiwyg display issues in WordPress 3.8. Props [@lswilson](https://github.com/lswilson). ([#491](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/491))
|
113 |
+
* Nonce field should only be added once per page. ([#521](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/521))
|
114 |
+
* Fix `in_array` issue when a post does not have any saved terms for a taxonomy multicheck. ([#527](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/527))
|
115 |
+
* Fixed error: 'Uninitialized string offset: 0 in cmb_Meta_Box_field.php...`. Props [@DevinWalker](https://github.com/DevinWalker). ([#539](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/539), [#549](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/549)))
|
116 |
+
* Fix missing `file` field description. ([#543](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/543), [#547](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/547))
|
117 |
+
|
118 |
+
|
119 |
+
|
120 |
+
### 1.1.3
|
121 |
+
**Bug Fixes**
|
122 |
+
|
123 |
+
* Update `cmb_get_field_value` function as it was passing the parameters to `cmb_get_field` in the wrong order.
|
124 |
+
* Fix repeating fields not working correctly if meta key or prefix contained an integer. ([#503](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/503))
|
125 |
+
|
126 |
+
### 1.1.2
|
127 |
+
|
128 |
+
**Bug Fixes**
|
129 |
+
|
130 |
+
* Fix issue with `cmb_Meta_Box_types.php` calling a missing method, `image_id_from_url`. ([#502](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/502))
|
131 |
+
|
132 |
+
|
133 |
+
### 1.1.1
|
134 |
+
|
135 |
+
**Bug Fixes**
|
136 |
+
|
137 |
+
* Radio button values were not showing saved value. ([#500](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/500))
|
138 |
+
|
139 |
+
### 1.1.0
|
140 |
+
|
141 |
+
**Enhancements**
|
142 |
+
|
143 |
+
* [Repeatable groups](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#group)
|
144 |
+
* Support for more fields to be repeatable, including oEmbed field, and date, time, and color picker fields, etc.
|
145 |
+
* Codebase has been revamped to be more modular and object-oriented.
|
146 |
+
* New filter, `"cmb_{$element}_attributes" ` for modifying an element's attributes.
|
147 |
+
* Every field now supports an `attributes` parameter that takes an array of attributes. [Read more](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#attributes).
|
148 |
+
* Removed `cmb_std_filter` in favor of `cmb_default_filter`. **THIS IS A BREAKING CHANGE**
|
149 |
+
* Better handling of labels in sidebar. They are now placed on top of the input rather than adjacent.
|
150 |
+
* Added i18n compatibility to text_money. props [@ArchCarrier](https://github.com/ArchCarrier), ([#485](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/485))
|
151 |
+
* New helper functions: `cmb_get_field` and `cmb_get_field_value` for getting access to CMB's field object and/or value.
|
152 |
+
* New JavaScript events, `cmb_add_row` and `cmb_remove_row` for hooking in and manipulating the new row's data.
|
153 |
+
* New filter, `cmb_localized_data`, for modifiying localized data passed to the CMB JS.
|
154 |
+
|
155 |
+
**Bug Fixes**
|
156 |
+
* Resolved occasional issue where only the first character of the label/value was diplayed. props [@mustardBees](https://github.com/mustardBees), ([#486](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/486))
|
157 |
+
|
158 |
+
|
159 |
+
### 1.0.2
|
160 |
+
|
161 |
+
**Enhancements**
|
162 |
+
|
163 |
+
* Change the way the `'cmb_validate_{$field['type']}'` filter works.
|
164 |
+
It is now passed a null value vs saved value. If null is returned, default sanitization will follow. **THIS IS A BREAKING CHANGE**. If you're already using this filter, take note.
|
165 |
+
* All field types that take an option array have been simplified to take `key => value` pairs (vs `array( 'name' => 'value', 'value' => 'key', )`). This effects the 'select', 'radio', 'radio_inline' field types. The 'multicheck' field type was already using the `key => value` format. Backwards compatibility has been maintained for those using the older style.
|
166 |
+
* Added default value option for `taxonomy_select` field type. props [@darlantc](https://github.com/darlantc), ([#473](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/473))
|
167 |
+
* Added `preview_size` parameter for `file_list` field type. props [@IgorCode](https://github.com/IgorCode), ([#471](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/471))
|
168 |
+
* Updated `file_list` images to be displayed horizontally instead of vertically. props [@IgorCode](https://github.com/IgorCode), ([#467](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/467))
|
169 |
+
* Use `get_the_terms` where possible since the data is cached.
|
170 |
+
|
171 |
+
**Bug Fixes**
|
172 |
+
|
173 |
+
* Fixed wysiwyg escaping slashes. props [@gregrickaby](https://github.com/gregrickaby), ([#465](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/465))
|
174 |
+
* Replaced `__DIR__`, as `dirname( __FILE__ )` is easier to maintain back-compatibility.
|
175 |
+
* Fixed missing table styling on new posts. props [@mustardBees](https://github.com/mustardBees), ([#438](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/438))
|
176 |
+
* Fix undeclared JS variable. [@veelen](https://github.com/veelen), ([#451](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/451))
|
177 |
+
* Fix `file_list` errors when removing all files and saving.
|
178 |
+
* Set correct `object_id` to be used later in `cmb_show_on` filter. [@lauravaq](https://github.com/lauravaq), ([#445](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/445))
|
179 |
+
* Fix sanitization recursion memeory issues.
|
180 |
+
|
181 |
+
### 1.0.1
|
182 |
+
|
183 |
+
**Enhancements**
|
184 |
+
|
185 |
+
* Now works with option pages and site settings. ([view example in wiki](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Using-CMB-to-create-an-Admin-Theme-Options-Page))
|
186 |
+
* two filters to override the setting and getting of options, `cmb_override_option_get_$option_key` and `cmb_override_option_save_$option_key` respectively. Handy for using plugins like [WP Large Options](https://github.com/voceconnect/wp-large-options/) ([also here](http://vip.wordpress.com/plugins/wp-large-options/)).
|
187 |
+
* Improved styling on taxonomy (\*tease\*) and options pages and for new 3.8 admin UI.
|
188 |
+
* New sanitization class to sanitize data when saved.
|
189 |
+
* New callback field parameter, `sanitization_cb`, for performing your own sanitization.
|
190 |
+
* new `cmb_Meta_Box_types::esc()` method that handles escaping data for display.
|
191 |
+
* New callback field parameter, `escape_cb`, for performing your own data escaping, as well as a new filter, `'cmb_types_esc_'. $field['type']`.
|
192 |
+
|
193 |
+
**Bug Fixes**
|
194 |
+
|
195 |
+
* Fixed wysiwyg editor button padding. props [@corvannoorloos](https://github.com/corvannoorloos), ([#391](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/391))
|
196 |
+
* A few php < 5.3 errors were addressed.
|
197 |
+
* Fields with quotation marks no longer break the input/textarea fields.
|
198 |
+
* metaboxes for Attachment pages now save correctly. Thanks [@nciske](https://github.com/nciske) for reporting. ([#412](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/412))
|
199 |
+
* Occasionally fields wouldn't save because of the admin show_on filter.
|
200 |
+
* Smaller images loaded to the file field type will no longer be blown up larger than their dimensions.
|
201 |
+
|
202 |
+
### 1.0.0
|
203 |
+
* Added `text_datetime_timestamp_timezone` type, a datetime combo field with an additional timezone drop down, props [@dessibelle](https://github.com/dessibelle)
|
204 |
+
* Added `select_timezone` type, a standalone time zone select dropdown. The time zone select can be used with standalone `text_datetime_timestamp` if desired. Props [@dessibelle](https://github.com/dessibelle)
|
205 |
+
* Added `text_url` type, a basic url field. Props [@dessibelle](https://github.com/dessibelle)
|
206 |
+
* Added `text_email` type, a basic email field. Props [@dessibelle](https://github.com/dessibelle)
|
207 |
+
* Added ability to display metabox fields in frontend. Default is true, but can be overriden using the `cmb_allow_frontend filter`. If set to true, an entire metabox form can be output with the `cmb_metabox_form( $meta_box, $object_id, $echo )` function. Props [@dessibelle](https://github.com/dessibelle), [@messenlehner](https://github.com/messenlehner) & [@jtsternberg](https://github.com/jtsternberg).
|
208 |
+
* Added hook `cmb_after_table` after all metabox output. Props [@wpsmith](https://github.com/wpsmith)
|
209 |
+
* `file_list` now works like a repeatable field. Add as many files as you want. Props [@coreymcollins](https://github.com/coreymcollins)
|
210 |
+
* `text`, `text_small`, `text_medium`, `text_url`, `text_email`, & `text_money` fields now all have the option to be repeatable. Props [@jtsternberg](https://github.com/jtsternberg)
|
211 |
+
* Custom metaboxes can now be added for user meta. Add them on the user add/edit screen, or in a custom user profile edit page on the front-end. Props [@tw2113](https://github.com/tw2113), [@jtsternberg](https://github.com/jtsternberg)
|
212 |
+
|
213 |
+
### 0.9.4
|
214 |
+
* Added field "before" and "after" options for each field. Solves issue with '$' not being the desired text_money monetary symbol, props [@GaryJones](https://github.com/GaryJones)
|
215 |
+
* Added filter for 'std' default fallback value, props [@messenlehner](https://github.com/messenlehner)
|
216 |
+
* Ensure oEmbed videos fit in their respective metaboxes, props [@jtsternberg](https://github.com/jtsternberg)
|
217 |
+
* Fixed issue where an upload field with 'show_names' disabled wouldn't have the correct button label, props [@jtsternberg](https://github.com/jtsternberg)
|
218 |
+
* Better file-extension check for images, props [@GhostToast](https://github.com/GhostToast)
|
219 |
+
* New filter, `cmb_valid_img_types`, for whitelisted image file-extensions, props [@jtsternberg](https://github.com/jtsternberg)
|
220 |
+
|
221 |
+
### 0.9.3
|
222 |
+
* Added field type and field id classes to each cmb table row, props [@jtsternberg](https://github.com/jtsternberg)
|
223 |
+
|
224 |
+
### 0.9.2
|
225 |
+
* Added post type comparison to prevent storing null values for taxonomy selectors, props [@norcross](https://github.com/norcross)
|
226 |
+
|
227 |
+
### 0.9.1
|
228 |
+
* Added `oEmbed` field type with ajax display, props [@jtsternberg](https://github.com/jtsternberg)
|
229 |
+
|
230 |
+
### 0.9
|
231 |
+
* __Note: This release requires WordPress 3.3+__
|
232 |
+
* Cleaned up scripts being queued, props [@jaredatch](https://github.com/jaredatch)
|
233 |
+
* Cleaned up and reorganized jQuery, props [@GaryJones](https://github.com/GaryJones)
|
234 |
+
* Use $pagenow instead of custom $current_page, props [@jaredatch](https://github.com/jaredatch)
|
235 |
+
* Fixed CSS, removed inline styles, now all in style.css, props [@jaredatch](https://github.com/jaredatch)
|
236 |
+
* Fixed multicheck issues (issue #48), props [@jaredatch](https://github.com/jaredatch)
|
237 |
+
* Fixed jQuery UI datepicker CSS conflicting with WordPress UI elements, props [@jaredatch](https://github.com/jaredatch)
|
238 |
+
* Fixed zeros not saving in fields, props [@GaryJones](https://github.com/GaryJones)
|
239 |
+
* Fixed improper labels on radio and multicheck fields, props [@jaredatch](https://github.com/jaredatch)
|
240 |
+
* Fixed fields not rendering properly when in sidebar, props [@jaredatch](https://github.com/jaredatch)
|
241 |
+
* Fixed bug where datepicker triggers extra space after footer in Firefox (issue #14), props [@jaredatch](https://github.com/jaredatch)
|
242 |
+
* Added jQuery UI datepicker packaged with 3.3 core, props [@jaredatch](https://github.com/jaredatch)
|
243 |
+
* Added date time combo picker, props [@jaredatch](https://github.com/jaredatch)
|
244 |
+
* Added color picker, props [@jaredatch](https://github.com/jaredatch)
|
245 |
+
* Added readme.md markdown file, props [@jaredatch](https://github.com/jaredatch)
|
246 |
+
|
247 |
+
### 0.8
|
248 |
+
* Added jQuery timepicker, props [@norcross](https://github.com/norcross)
|
249 |
+
* Added 'raw' textarea to convert special HTML entities back to characters, props [@norcross](https://github.com/norcross)
|
250 |
+
* Added missing examples on example-functions.php, props [@norcross](https://github.com/norcross)
|
251 |
+
|
252 |
+
### 0.7
|
253 |
+
* Added the new wp_editor() function for the WYSIWYG dialog box, props [@jcpry](https://github.com/jcpry)
|
254 |
+
* Created 'cmb_show_on' filter to define your own Show On Filters, props [@billerickson](https://github.com/billerickson)
|
255 |
+
* Added page template show_on filter, props [@billerickson](https://github.com/billerickson)
|
256 |
+
* Improvements to the 'file' field type, props [@randyhoyt](https://github.com/randyhoyt)
|
257 |
+
* Allow for default values on 'radio' and 'radio_inline' field types, props [@billerickson](https://github.com/billerickson)
|
258 |
+
|
259 |
+
### 0.6.1
|
260 |
+
* Enabled the ability to define your own custom field types (issue #28). props [@randyhoyt](https://github.com/randyhoyt)
|
261 |
+
|
262 |
+
### 0.6
|
263 |
+
* Added the ability to limit metaboxes to certain posts by id. props [@billerickson](https://github.com/billerickson)
|
264 |
+
|
265 |
+
### 0.5
|
266 |
+
* Fixed define to prevent notices. props [@destos](https://github.com/destos)
|
267 |
+
* Added text_date_timestap option. props [@andrewyno](https://github.com/andrewyno)
|
268 |
+
* Fixed WYSIWYG paragraph breaking/spacing bug. props [@wpsmith](https://github.com/wpsmith)
|
269 |
+
* Added taxonomy_radio and taxonomies_select options. props [@c3mdigital](https://github.com/c3mdigital)
|
270 |
+
* Fixed script causing the dashboard widgets to not be collapsible.
|
271 |
+
* Fixed various spacing and whitespace inconsistencies
|
272 |
+
|
273 |
+
### 0.4
|
274 |
+
* Think we have a release that is mostly working. We'll say the initial release :)
|
275 |
+
|
276 |
+
## Known Issues
|
277 |
+
|
278 |
+
* Problem inserting file url inside field for image with caption (issue #50) May be fixed, needs testing.
|
279 |
+
* `CMB_META_BOX_URL` does not define properly in WAMP/XAMP (Windows) (issue #31) May be fixed, needs testing.
|
280 |
+
* Metabox containing WYSIWYG editor cannot be moved (this is a TinyMCE issue)
|
281 |
+
|
282 |
+
## To-do
|
283 |
+
**Enhancements**
|
284 |
+
|
285 |
+
* Fix known issues (above)
|
286 |
+
* move timepicker and datepicker jQuery inline
|
287 |
+
* support for multiple configurable timepickers/datepickers
|
288 |
+
* add ability to save fields in a single custom field
|
289 |
+
* add ability to mark fields as required
|
290 |
+
* repeatable fields (halfway there)
|
291 |
+
* look at possiblity of tabs
|
292 |
+
* look at preserving taxonomy hierarchies
|
293 |
+
* Add input attributes filter
|
294 |
+
* Always load newest version of CMB
|
295 |
+
* Helper function to easily get oembed from stored oEmbed field
|
296 |
+
|
lib/cmb_metaboxes/style.css
ADDED
@@ -0,0 +1,621 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* CMB Styling
|
3 |
+
*/
|
4 |
+
|
5 |
+
table.cmb_metabox {
|
6 |
+
clear: both;
|
7 |
+
}
|
8 |
+
|
9 |
+
table.cmb_metabox > tr:first-of-type > td,
|
10 |
+
table.cmb_metabox > tr:first-of-type > th,
|
11 |
+
table.cmb_metabox tbody > tr:first-of-type > td,
|
12 |
+
table.cmb_metabox tbody > tr:first-of-type > th,
|
13 |
+
.post-php table.cmb_metabox .cmb-nested-table td,
|
14 |
+
.post-new-php table.cmb_metabox .cmb-nested-table td,
|
15 |
+
.post-php table.cmb_metabox .repeatable-group th,
|
16 |
+
.post-new-php table.cmb_metabox .repeatable-group th,
|
17 |
+
.post-php table.cmb_metabox .repeatable-group:first-of-type,
|
18 |
+
.post-new-php table.cmb_metabox .repeatable-group:first-of-type {
|
19 |
+
border: 0;
|
20 |
+
}
|
21 |
+
|
22 |
+
.post-php table.cmb_metabox td,
|
23 |
+
.post-new-php table.cmb_metabox td,
|
24 |
+
.post-php table.cmb_metabox th,
|
25 |
+
.post-new-php table.cmb_metabox th,
|
26 |
+
.post-php table.cmb_metabox .repeatable-group,
|
27 |
+
.post-new-php table.cmb_metabox .repeatable-group,
|
28 |
+
.post-php table.cmb_metabox .repeatable-group,
|
29 |
+
.post-new-php table.cmb_metabox .repeatable-group {
|
30 |
+
border-top: 1px solid #E9E9E9;
|
31 |
+
}
|
32 |
+
|
33 |
+
.repeatable-group th {
|
34 |
+
padding: 5px;
|
35 |
+
}
|
36 |
+
|
37 |
+
.repeatable-group .shift-rows {
|
38 |
+
text-decoration: none;
|
39 |
+
margin-right: 5px;
|
40 |
+
font-size: 1.2em;
|
41 |
+
}
|
42 |
+
|
43 |
+
.repeatable-group .cmb_upload_button {
|
44 |
+
float: right;
|
45 |
+
}
|
46 |
+
|
47 |
+
#poststuff .repeatable-group h2 {
|
48 |
+
margin: 0;
|
49 |
+
}
|
50 |
+
|
51 |
+
.cmb-group-title h4 {
|
52 |
+
font-size: 1.2em;
|
53 |
+
font-weight: 500;
|
54 |
+
border-bottom: 1px solid #ddd;
|
55 |
+
}
|
56 |
+
|
57 |
+
.post-php table.cmb_metabox th, .post-new-php table.cmb_metabox th {
|
58 |
+
text-align: right;
|
59 |
+
font-weight:bold;
|
60 |
+
}
|
61 |
+
|
62 |
+
.post-php table.cmb_metabox table th, .post-new-php table.cmb_metabox table th {
|
63 |
+
text-align: left;
|
64 |
+
}
|
65 |
+
|
66 |
+
table.cmb_metabox th label {
|
67 |
+
margin-top:5px;
|
68 |
+
display:block
|
69 |
+
}
|
70 |
+
|
71 |
+
p.cmb_metabox_description {
|
72 |
+
color: #AAA;
|
73 |
+
font-style: italic;
|
74 |
+
margin: 2px 0 !important
|
75 |
+
}
|
76 |
+
|
77 |
+
span.cmb_metabox_description {
|
78 |
+
color: #AAA;
|
79 |
+
font-style: italic
|
80 |
+
}
|
81 |
+
|
82 |
+
table.cmb_metabox input, table.cmb_metabox textarea {
|
83 |
+
font-size:14px;
|
84 |
+
padding: 5px;
|
85 |
+
}
|
86 |
+
|
87 |
+
table.cmb_metabox input[type=text], table.cmb_metabox textarea {
|
88 |
+
width: 97%;
|
89 |
+
}
|
90 |
+
|
91 |
+
table.cmb_metabox textarea.cmb_textarea_code {
|
92 |
+
font-family: Consolas,Monaco,monospace;
|
93 |
+
line-height: 16px;
|
94 |
+
}
|
95 |
+
|
96 |
+
table.cmb_metabox input.cmb_text_small {
|
97 |
+
width: 100px;
|
98 |
+
margin-right: 15px
|
99 |
+
}
|
100 |
+
|
101 |
+
table.cmb_metabox input.cmb_timepicker {
|
102 |
+
width: 100px;
|
103 |
+
margin-right: 15px
|
104 |
+
}
|
105 |
+
|
106 |
+
table.cmb_metabox input.cmb_text_money {
|
107 |
+
width: 90px;
|
108 |
+
margin-right: 15px
|
109 |
+
}
|
110 |
+
|
111 |
+
table.cmb_metabox input.cmb_text_medium {
|
112 |
+
width: 230px;
|
113 |
+
margin-right: 15px
|
114 |
+
}
|
115 |
+
|
116 |
+
table.cmb_metabox input.cmb_upload_file {
|
117 |
+
width: 65%;
|
118 |
+
}
|
119 |
+
|
120 |
+
table.cmb_metabox input.ed_button{
|
121 |
+
padding:2px 4px
|
122 |
+
}
|
123 |
+
|
124 |
+
table.cmb_metabox li {
|
125 |
+
font-size:14px;
|
126 |
+
margin: 1px 0 5px 0;
|
127 |
+
line-height: 16px;
|
128 |
+
}
|
129 |
+
|
130 |
+
table.cmb_metabox ul {
|
131 |
+
padding-top:5px;
|
132 |
+
margin: 0;
|
133 |
+
}
|
134 |
+
|
135 |
+
table.cmb_metabox select {
|
136 |
+
font-size:14px;
|
137 |
+
margin-top: 3px
|
138 |
+
}
|
139 |
+
|
140 |
+
table.cmb_metabox input:focus, table.cmb_metabox textarea:focus {
|
141 |
+
background: #fffff8
|
142 |
+
}
|
143 |
+
|
144 |
+
.cmb_metabox_title {
|
145 |
+
margin: 0 0 5px 0;
|
146 |
+
padding: 5px 0 0 0;
|
147 |
+
}
|
148 |
+
|
149 |
+
.edit-tags-php .cmb_metabox_title, .profile-php .cmb_metabox_title, .user-edit-php .cmb_metabox_title {
|
150 |
+
margin-left: -10px;
|
151 |
+
}
|
152 |
+
|
153 |
+
.cmb-inline ul {
|
154 |
+
padding: 4px 0 0 0
|
155 |
+
}
|
156 |
+
|
157 |
+
.cmb-inline li {display: inline-block;
|
158 |
+
padding-right: 18px
|
159 |
+
}
|
160 |
+
|
161 |
+
table.cmb_metabox input[type="radio"] {
|
162 |
+
margin: 0 5px 0 0;
|
163 |
+
padding: 0
|
164 |
+
}
|
165 |
+
|
166 |
+
table.cmb_metabox input[type="checkbox"] {
|
167 |
+
margin: 0 5px 0 0;
|
168 |
+
padding: 0
|
169 |
+
}
|
170 |
+
|
171 |
+
table.cmb_metabox .mceLayout {
|
172 |
+
border:1px solid #DFDFDF !important
|
173 |
+
}
|
174 |
+
|
175 |
+
table.cmb_metabox .mceIframeContainer {
|
176 |
+
background:#FFF
|
177 |
+
}
|
178 |
+
|
179 |
+
table.cmb_metabox .meta_mce {
|
180 |
+
width:97%
|
181 |
+
}
|
182 |
+
|
183 |
+
table.cmb_metabox .meta_mce textarea {
|
184 |
+
width:100%
|
185 |
+
}
|
186 |
+
|
187 |
+
table.cmb_metabox .cmb_media_status {
|
188 |
+
margin: 10px 0 0 0
|
189 |
+
}
|
190 |
+
|
191 |
+
table.cmb_metabox .cmb_media_status .img_status {
|
192 |
+
clear: none;
|
193 |
+
float: left;
|
194 |
+
display: inline-block;
|
195 |
+
margin-right: 10px;
|
196 |
+
width: auto;
|
197 |
+
}
|
198 |
+
|
199 |
+
table.cmb_metabox .cmb-type-file_list .cmb_media_status .img_status {
|
200 |
+
clear: none;
|
201 |
+
float: left;
|
202 |
+
margin-right: 10px;
|
203 |
+
width: auto;
|
204 |
+
}
|
205 |
+
|
206 |
+
table.cmb_metabox .cmb_media_status .img_status, table.cmb_metabox .cmb_media_status .embed_status {
|
207 |
+
position: relative;
|
208 |
+
}
|
209 |
+
|
210 |
+
table.cmb_metabox .cmb_media_status .img_status img, table.cmb_metabox .cmb_media_status .embed_status {
|
211 |
+
border:1px solid #DFDFDF;
|
212 |
+
background: #FAFAFA;
|
213 |
+
max-width:350px;
|
214 |
+
padding: 5px;
|
215 |
+
-moz-border-radius: 2px;
|
216 |
+
border-radius: 2px
|
217 |
+
}
|
218 |
+
|
219 |
+
table.cmb_metabox .cmb_media_status .embed_status {
|
220 |
+
float: left;
|
221 |
+
max-width:800px
|
222 |
+
}
|
223 |
+
|
224 |
+
table.cmb_metabox .cmb_media_status .img_status .cmb_remove_file_button, table.cmb_metabox .cmb_media_status .embed_status .cmb_remove_file_button {
|
225 |
+
text-indent: -9999px;
|
226 |
+
background: url(images/ico-delete.png);
|
227 |
+
width: 16px;
|
228 |
+
height: 16px;
|
229 |
+
position: absolute;
|
230 |
+
top: -5px;
|
231 |
+
left: -5px
|
232 |
+
}
|
233 |
+
|
234 |
+
table.cmb_metabox .attach_list li {
|
235 |
+
clear: both;
|
236 |
+
display: inline-block;
|
237 |
+
margin-bottom: 25px;
|
238 |
+
width: 100%;
|
239 |
+
}
|
240 |
+
|
241 |
+
table.cmb_metabox .attach_list li img {
|
242 |
+
float: left;
|
243 |
+
margin-right: 10px;
|
244 |
+
}
|
245 |
+
|
246 |
+
/**
|
247 |
+
* Sidebar placement adjustments
|
248 |
+
*/
|
249 |
+
.inner-sidebar table.cmb_metabox input[type=text],
|
250 |
+
#side-sortables table.cmb_metabox input[type=text],
|
251 |
+
table.cmb_metabox textarea {
|
252 |
+
width: 95%;
|
253 |
+
}
|
254 |
+
|
255 |
+
.inner-sidebar table.cmb_metabox .cmb_media_status .img_status img,
|
256 |
+
#side-sortables table.cmb_metabox .cmb_media_status .img_status img,
|
257 |
+
.inner-sidebar table.cmb_metabox .cmb_media_status .embed_status img,
|
258 |
+
#side-sortables table.cmb_metabox .cmb_media_status .embed_status img {
|
259 |
+
width: 90%;
|
260 |
+
}
|
261 |
+
|
262 |
+
.inner-sidebar table.cmb_metabox label,
|
263 |
+
#side-sortables table.cmb_metabox label {
|
264 |
+
display: block;
|
265 |
+
font-weight: bold;
|
266 |
+
padding: 0 0 5px;
|
267 |
+
}
|
268 |
+
|
269 |
+
.inner-sidebar table.cmb_metabox .cmb_list label,
|
270 |
+
#side-sortables table.cmb_metabox .cmb_list label {
|
271 |
+
display: inline;
|
272 |
+
font-weight: normal;
|
273 |
+
}
|
274 |
+
|
275 |
+
.inner-sidebar table.cmb_metabox .cmb_metabox_description,
|
276 |
+
#side-sortables table.cmb_metabox .cmb_metabox_description {
|
277 |
+
display: block;
|
278 |
+
padding: 7px 0 0;
|
279 |
+
}
|
280 |
+
|
281 |
+
.inner-sidebar table.cmb_metabox .cmb_metabox_title,
|
282 |
+
#side-sortables table.cmb_metabox .cmb_metabox_title {
|
283 |
+
font-size: 1.2em;
|
284 |
+
font-style: italic;
|
285 |
+
}
|
286 |
+
|
287 |
+
.postbox table.cmb_metabox .cmb-spinner {
|
288 |
+
float: left;
|
289 |
+
}
|
290 |
+
|
291 |
+
/**
|
292 |
+
* Color picker
|
293 |
+
*/
|
294 |
+
table.cmb_metabox .wp-color-result, table.cmb_metabox .wp-picker-input-wrap {
|
295 |
+
vertical-align: middle;
|
296 |
+
}
|
297 |
+
|
298 |
+
table.cmb_metabox .wp-color-result, table.cmb_metabox .wp-picker-container {
|
299 |
+
margin: 0 10px 0 0;
|
300 |
+
}
|
301 |
+
|
302 |
+
|
303 |
+
/**
|
304 |
+
* Timepicker
|
305 |
+
*/
|
306 |
+
div.time-picker {
|
307 |
+
position: absolute;
|
308 |
+
height: 191px;
|
309 |
+
width:6em;
|
310 |
+
/* needed for IE */overflow: auto;
|
311 |
+
background: #fff;
|
312 |
+
border: 1px solid #aaa;
|
313 |
+
z-index: 99;
|
314 |
+
margin: 0
|
315 |
+
}
|
316 |
+
|
317 |
+
div.time-picker-12hours {
|
318 |
+
width:8em; /* needed for IE */
|
319 |
+
}
|
320 |
+
|
321 |
+
div.time-picker ul {
|
322 |
+
list-style-type: none;
|
323 |
+
margin: 0;
|
324 |
+
padding: 0;
|
325 |
+
}
|
326 |
+
|
327 |
+
div.time-picker li {
|
328 |
+
cursor: pointer;
|
329 |
+
height: 10px;
|
330 |
+
font: 14px/1 Helvetica, Arial, sans-serif;
|
331 |
+
padding: 4px 3px;
|
332 |
+
}
|
333 |
+
|
334 |
+
div.time-picker li.selected {
|
335 |
+
background: #0063CE;
|
336 |
+
color: #fff;
|
337 |
+
}
|
338 |
+
|
339 |
+
/**
|
340 |
+
* jQuery UI CSS Framework 1.8.16
|
341 |
+
*
|
342 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
343 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
344 |
+
* http://jquery.org/license
|
345 |
+
*
|
346 |
+
* http://docs.jquery.com/UI/Theming/API
|
347 |
+
*/
|
348 |
+
.cmb_element .ui-helper-hidden { display: none; }
|
349 |
+
.cmb_element .ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
|
350 |
+
.cmb_element .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
|
351 |
+
.cmb_element .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
|
352 |
+
.cmb_element .ui-helper-clearfix { display: inline-block; }
|
353 |
+
* html .ui-helper-clearfix { height:1%; }
|
354 |
+
.cmb_element .ui-helper-clearfix { display:block; }
|
355 |
+
.cmb_element .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
|
356 |
+
.cmb_element .ui-state-disabled { cursor: default !important; }
|
357 |
+
.cmb_element .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
|
358 |
+
.cmb_element .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
|
359 |
+
.cmb_element .ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
|
360 |
+
.cmb_element .ui-widget .ui-widget { font-size: 1em; }
|
361 |
+
.cmb_element .ui-widget input, .cmb_element .ui-widget select, .cmb_element .ui-widget textarea, .cmb_element .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
|
362 |
+
.cmb_element .ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
|
363 |
+
.cmb_element .ui-widget-content a { color: #222222; }
|
364 |
+
.cmb_element .ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
|
365 |
+
.cmb_element .ui-widget-header a { color: #222222; }
|
366 |
+
.cmb_element .ui-state-default, .cmb_element .ui-widget-content .ui-state-default, .cmb_element .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
|
367 |
+
.cmb_element .ui-state-default a, .cmb_element .ui-state-default a:link, .cmb_element .ui-state-default a:visited { color: #555555; text-decoration: none; }
|
368 |
+
.cmb_element .ui-state-hover, .cmb_element .ui-widget-content .ui-state-hover, .cmb_element .ui-widget-header .ui-state-hover, .cmb_element .ui-state-focus, .cmb_element .ui-widget-content .ui-state-focus, .cmb_element .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
|
369 |
+
.cmb_element .ui-state-hover a, .cmb_element .ui-state-hover a:hover { color: #212121; text-decoration: none; }
|
370 |
+
.cmb_element .ui-state-active, .cmb_element .ui-widget-content .ui-state-active, .cmb_element .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
|
371 |
+
.cmb_element .ui-state-active a, .cmb_element .ui-state-active a:link, .cmb_element .ui-state-active a:visited { color: #212121; text-decoration: none; }
|
372 |
+
.cmb_element .ui-widget :active { outline: none; }
|
373 |
+
.cmb_element .ui-state-highlight, .cmb_element .ui-widget-content .ui-state-highlight, .cmb_element .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
|
374 |
+
.cmb_element .ui-state-highlight a, .cmb_element .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
|
375 |
+
.cmb_element .ui-state-error, .cmb_element .ui-widget-content .ui-state-error, .cmb_element .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
|
376 |
+
.cmb_element .ui-state-error a, .cmb_element .ui-widget-content .ui-state-error a, .cmb_element .ui-widget-header .ui-state-error a { color: #cd0a0a; }
|
377 |
+
.cmb_element .ui-state-error-text, .cmb_element .ui-widget-content .ui-state-error-text, .cmb_element .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
|
378 |
+
.cmb_element .ui-priority-primary, .cmb_element .ui-widget-content .ui-priority-primary, .cmb_element .ui-widget-header .ui-priority-primary { font-weight: bold; }
|
379 |
+
.cmb_element .ui-priority-secondary, .cmb_element .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
|
380 |
+
.cmb_element .ui-state-disabled, .cmb_element .ui-widget-content .ui-state-disabled, .cmb_element .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
|
381 |
+
.cmb_element .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
|
382 |
+
.cmb_element .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
|
383 |
+
.cmb_element .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
|
384 |
+
.cmb_element .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
|
385 |
+
.cmb_element .ui-state-hover .ui-icon, .cmb_element .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
|
386 |
+
.cmb_element .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
|
387 |
+
.cmb_element .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
|
388 |
+
.cmb_element .ui-state-error .ui-icon, .cmb_element .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
|
389 |
+
.cmb_element .ui-icon-carat-1-n { background-position: 0 0; }
|
390 |
+
.cmb_element .ui-icon-carat-1-ne { background-position: -16px 0; }
|
391 |
+
.cmb_element .ui-icon-carat-1-e { background-position: -32px 0; }
|
392 |
+
.cmb_element .ui-icon-carat-1-se { background-position: -48px 0; }
|
393 |
+
.cmb_element .ui-icon-carat-1-s { background-position: -64px 0; }
|
394 |
+
.cmb_element .ui-icon-carat-1-sw { background-position: -80px 0; }
|
395 |
+
.cmb_element .ui-icon-carat-1-w { background-position: -96px 0; }
|
396 |
+
.cmb_element .ui-icon-carat-1-nw { background-position: -112px 0; }
|
397 |
+
.cmb_element .ui-icon-carat-2-n-s { background-position: -128px 0; }
|
398 |
+
.cmb_element .ui-icon-carat-2-e-w { background-position: -144px 0; }
|
399 |
+
.cmb_element .ui-icon-triangle-1-n { background-position: 0 -16px; }
|
400 |
+
.cmb_element .ui-icon-triangle-1-ne { background-position: -16px -16px; }
|
401 |
+
.cmb_element .ui-icon-triangle-1-e { background-position: -32px -16px; }
|
402 |
+
.cmb_element .ui-icon-triangle-1-se { background-position: -48px -16px; }
|
403 |
+
.cmb_element .ui-icon-triangle-1-s { background-position: -64px -16px; }
|
404 |
+
.cmb_element .ui-icon-triangle-1-sw { background-position: -80px -16px; }
|
405 |
+
.cmb_element .ui-icon-triangle-1-w { background-position: -96px -16px; }
|
406 |
+
.cmb_element .ui-icon-triangle-1-nw { background-position: -112px -16px; }
|
407 |
+
.cmb_element .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
|
408 |
+
.cmb_element .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
|
409 |
+
.cmb_element .ui-icon-arrow-1-n { background-position: 0 -32px; }
|
410 |
+
.cmb_element .ui-icon-arrow-1-ne { background-position: -16px -32px; }
|
411 |
+
.cmb_element .ui-icon-arrow-1-e { background-position: -32px -32px; }
|
412 |
+
.cmb_element .ui-icon-arrow-1-se { background-position: -48px -32px; }
|
413 |
+
.cmb_element .ui-icon-arrow-1-s { background-position: -64px -32px; }
|
414 |
+
.cmb_element .ui-icon-arrow-1-sw { background-position: -80px -32px; }
|
415 |
+
.cmb_element .ui-icon-arrow-1-w { background-position: -96px -32px; }
|
416 |
+
.cmb_element .ui-icon-arrow-1-nw { background-position: -112px -32px; }
|
417 |
+
.cmb_element .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
|
418 |
+
.cmb_element .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
|
419 |
+
.cmb_element .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
|
420 |
+
.cmb_element .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
|
421 |
+
.cmb_element .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
|
422 |
+
.cmb_element .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
|
423 |
+
.cmb_element .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
|
424 |
+
.cmb_element .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
|
425 |
+
.cmb_element .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
|
426 |
+
.cmb_element .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
|
427 |
+
.cmb_element .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
|
428 |
+
.cmb_element .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
|
429 |
+
.cmb_element .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
|
430 |
+
.cmb_element .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
|
431 |
+
.cmb_element .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
|
432 |
+
.cmb_element .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
|
433 |
+
.cmb_element .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
|
434 |
+
.cmb_element .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
|
435 |
+
.cmb_element .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
|
436 |
+
.cmb_element .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
|
437 |
+
.cmb_element .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
|
438 |
+
.cmb_element .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
|
439 |
+
.cmb_element .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
|
440 |
+
.cmb_element .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
|
441 |
+
.cmb_element .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
|
442 |
+
.cmb_element .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
|
443 |
+
.cmb_element .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
|
444 |
+
.cmb_element .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
|
445 |
+
.cmb_element .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
|
446 |
+
.cmb_element .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
|
447 |
+
.cmb_element .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
|
448 |
+
.cmb_element .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
|
449 |
+
.cmb_element .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
|
450 |
+
.cmb_element .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
|
451 |
+
.cmb_element .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
|
452 |
+
.cmb_element .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
|
453 |
+
.cmb_element .ui-icon-arrow-4 { background-position: 0 -80px; }
|
454 |
+
.cmb_element .ui-icon-arrow-4-diag { background-position: -16px -80px; }
|
455 |
+
.cmb_element .ui-icon-extlink { background-position: -32px -80px; }
|
456 |
+
.cmb_element .ui-icon-newwin { background-position: -48px -80px; }
|
457 |
+
.cmb_element .ui-icon-refresh { background-position: -64px -80px; }
|
458 |
+
.cmb_element .ui-icon-shuffle { background-position: -80px -80px; }
|
459 |
+
.cmb_element .ui-icon-transfer-e-w { background-position: -96px -80px; }
|
460 |
+
.cmb_element .ui-icon-transferthick-e-w { background-position: -112px -80px; }
|
461 |
+
.cmb_element .ui-icon-folder-collapsed { background-position: 0 -96px; }
|
462 |
+
.cmb_element .ui-icon-folder-open { background-position: -16px -96px; }
|
463 |
+
.cmb_element .ui-icon-document { background-position: -32px -96px; }
|
464 |
+
.cmb_element .ui-icon-document-b { background-position: -48px -96px; }
|
465 |
+
.cmb_element .ui-icon-note { background-position: -64px -96px; }
|
466 |
+
.cmb_element .ui-icon-mail-closed { background-position: -80px -96px; }
|
467 |
+
.cmb_element .ui-icon-mail-open { background-position: -96px -96px; }
|
468 |
+
.cmb_element .ui-icon-suitcase { background-position: -112px -96px; }
|
469 |
+
.cmb_element .ui-icon-comment { background-position: -128px -96px; }
|
470 |
+
.cmb_element .ui-icon-person { background-position: -144px -96px; }
|
471 |
+
.cmb_element .ui-icon-print { background-position: -160px -96px; }
|
472 |
+
.cmb_element .ui-icon-trash { background-position: -176px -96px; }
|
473 |
+
.cmb_element .ui-icon-locked { background-position: -192px -96px; }
|
474 |
+
.cmb_element .ui-icon-unlocked { background-position: -208px -96px; }
|
475 |
+
.cmb_element .ui-icon-bookmark { background-position: -224px -96px; }
|
476 |
+
.cmb_element .ui-icon-tag { background-position: -240px -96px; }
|
477 |
+
.cmb_element .ui-icon-home { background-position: 0 -112px; }
|
478 |
+
.cmb_element .ui-icon-flag { background-position: -16px -112px; }
|
479 |
+
.cmb_element .ui-icon-calendar { background-position: -32px -112px; }
|
480 |
+
.cmb_element .ui-icon-cart { background-position: -48px -112px; }
|
481 |
+
.cmb_element .ui-icon-pencil { background-position: -64px -112px; }
|
482 |
+
.cmb_element .ui-icon-clock { background-position: -80px -112px; }
|
483 |
+
.cmb_element .ui-icon-disk { background-position: -96px -112px; }
|
484 |
+
.cmb_element .ui-icon-calculator { background-position: -112px -112px; }
|
485 |
+
.cmb_element .ui-icon-zoomin { background-position: -128px -112px; }
|
486 |
+
.cmb_element .ui-icon-zoomout { background-position: -144px -112px; }
|
487 |
+
.cmb_element .ui-icon-search { background-position: -160px -112px; }
|
488 |
+
.cmb_element .ui-icon-wrench { background-position: -176px -112px; }
|
489 |
+
.cmb_element .ui-icon-gear { background-position: -192px -112px; }
|
490 |
+
.cmb_element .ui-icon-heart { background-position: -208px -112px; }
|
491 |
+
.cmb_element .ui-icon-star { background-position: -224px -112px; }
|
492 |
+
.cmb_element .ui-icon-link { background-position: -240px -112px; }
|
493 |
+
.cmb_element .ui-icon-cancel { background-position: 0 -128px; }
|
494 |
+
.cmb_element .ui-icon-plus { background-position: -16px -128px; }
|
495 |
+
.cmb_element .ui-icon-plusthick { background-position: -32px -128px; }
|
496 |
+
.cmb_element .ui-icon-minus { background-position: -48px -128px; }
|
497 |
+
.cmb_element .ui-icon-minusthick { background-position: -64px -128px; }
|
498 |
+
.cmb_element .ui-icon-close { background-position: -80px -128px; }
|
499 |
+
.cmb_element .ui-icon-closethick { background-position: -96px -128px; }
|
500 |
+
.cmb_element .ui-icon-key { background-position: -112px -128px; }
|
501 |
+
.cmb_element .ui-icon-lightbulb { background-position: -128px -128px; }
|
502 |
+
.cmb_element .ui-icon-scissors { background-position: -144px -128px; }
|
503 |
+
.cmb_element .ui-icon-clipboard { background-position: -160px -128px; }
|
504 |
+
.cmb_element .ui-icon-copy { background-position: -176px -128px; }
|
505 |
+
.cmb_element .ui-icon-contact { background-position: -192px -128px; }
|
506 |
+
.cmb_element .ui-icon-image { background-position: -208px -128px; }
|
507 |
+
.cmb_element .ui-icon-video { background-position: -224px -128px; }
|
508 |
+
.cmb_element .ui-icon-script { background-position: -240px -128px; }
|
509 |
+
.cmb_element .ui-icon-alert { background-position: 0 -144px; }
|
510 |
+
.cmb_element .ui-icon-info { background-position: -16px -144px; }
|
511 |
+
.cmb_element .ui-icon-notice { background-position: -32px -144px; }
|
512 |
+
.cmb_element .ui-icon-help { background-position: -48px -144px; }
|
513 |
+
.cmb_element .ui-icon-check { background-position: -64px -144px; }
|
514 |
+
.cmb_element .ui-icon-bullet { background-position: -80px -144px; }
|
515 |
+
.cmb_element .ui-icon-radio-off { background-position: -96px -144px; }
|
516 |
+
.cmb_element .ui-icon-radio-on { background-position: -112px -144px; }
|
517 |
+
.cmb_element .ui-icon-pin-w { background-position: -128px -144px; }
|
518 |
+
.cmb_element .ui-icon-pin-s { background-position: -144px -144px; }
|
519 |
+
.cmb_element .ui-icon-play { background-position: 0 -160px; }
|
520 |
+
.cmb_element .ui-icon-pause { background-position: -16px -160px; }
|
521 |
+
.cmb_element .ui-icon-seek-next { background-position: -32px -160px; }
|
522 |
+
.cmb_element .ui-icon-seek-prev { background-position: -48px -160px; }
|
523 |
+
.cmb_element .ui-icon-seek-end { background-position: -64px -160px; }
|
524 |
+
.cmb_element .ui-icon-seek-start { background-position: -80px -160px; }
|
525 |
+
.cmb_element .ui-icon-seek-first { background-position: -80px -160px; }
|
526 |
+
.cmb_element .ui-icon-stop { background-position: -96px -160px; }
|
527 |
+
.cmb_element .ui-icon-eject { background-position: -112px -160px; }
|
528 |
+
.cmb_element .ui-icon-volume-off { background-position: -128px -160px; }
|
529 |
+
.cmb_element .ui-icon-volume-on { background-position: -144px -160px; }
|
530 |
+
.cmb_element .ui-icon-power { background-position: 0 -176px; }
|
531 |
+
.cmb_element .ui-icon-signal-diag { background-position: -16px -176px; }
|
532 |
+
.cmb_element .ui-icon-signal { background-position: -32px -176px; }
|
533 |
+
.cmb_element .ui-icon-battery-0 { background-position: -48px -176px; }
|
534 |
+
.cmb_element .ui-icon-battery-1 { background-position: -64px -176px; }
|
535 |
+
.cmb_element .ui-icon-battery-2 { background-position: -80px -176px; }
|
536 |
+
.cmb_element .ui-icon-battery-3 { background-position: -96px -176px; }
|
537 |
+
.cmb_element .ui-icon-circle-plus { background-position: 0 -192px; }
|
538 |
+
.cmb_element .ui-icon-circle-minus { background-position: -16px -192px; }
|
539 |
+
.cmb_element .ui-icon-circle-close { background-position: -32px -192px; }
|
540 |
+
.cmb_element .ui-icon-circle-triangle-e { background-position: -48px -192px; }
|
541 |
+
.cmb_element .ui-icon-circle-triangle-s { background-position: -64px -192px; }
|
542 |
+
.cmb_element .ui-icon-circle-triangle-w { background-position: -80px -192px; }
|
543 |
+
.cmb_element .ui-icon-circle-triangle-n { background-position: -96px -192px; }
|
544 |
+
.cmb_element .ui-icon-circle-arrow-e { background-position: -112px -192px; }
|
545 |
+
.cmb_element .ui-icon-circle-arrow-s { background-position: -128px -192px; }
|
546 |
+
.cmb_element .ui-icon-circle-arrow-w { background-position: -144px -192px; }
|
547 |
+
.cmb_element .ui-icon-circle-arrow-n { background-position: -160px -192px; }
|
548 |
+
.cmb_element .ui-icon-circle-zoomin { background-position: -176px -192px; }
|
549 |
+
.cmb_element .ui-icon-circle-zoomout { background-position: -192px -192px; }
|
550 |
+
.cmb_element .ui-icon-circle-check { background-position: -208px -192px; }
|
551 |
+
.cmb_element .ui-icon-circlesmall-plus { background-position: 0 -208px; }
|
552 |
+
.cmb_element .ui-icon-circlesmall-minus { background-position: -16px -208px; }
|
553 |
+
.cmb_element .ui-icon-circlesmall-close { background-position: -32px -208px; }
|
554 |
+
.cmb_element .ui-icon-squaresmall-plus { background-position: -48px -208px; }
|
555 |
+
.cmb_element .ui-icon-squaresmall-minus { background-position: -64px -208px; }
|
556 |
+
.cmb_element .ui-icon-squaresmall-close { background-position: -80px -208px; }
|
557 |
+
.cmb_element .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
|
558 |
+
.cmb_element .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
|
559 |
+
.cmb_element .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
|
560 |
+
.cmb_element .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
|
561 |
+
.cmb_element .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
|
562 |
+
.cmb_element .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
|
563 |
+
.cmb_element .ui-corner-all, .cmb_element .ui-corner-top, .cmb_element .ui-corner-left, .cmb_element .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; }
|
564 |
+
.cmb_element .ui-corner-all, .cmb_element .ui-corner-top, .cmb_element .ui-corner-right, .cmb_element .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; }
|
565 |
+
.cmb_element .ui-corner-all, .cmb_element .ui-corner-bottom, .cmb_element .ui-corner-left, .cmb_element .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
|
566 |
+
.cmb_element .ui-corner-all, .cmb_element .ui-corner-bottom, .cmb_element .ui-corner-right, .cmb_element .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
|
567 |
+
.cmb_element .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
|
568 |
+
.cmb_element .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
|
569 |
+
.cmb_element .ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
|
570 |
+
.cmb_element .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
|
571 |
+
.cmb_element .ui-datepicker .ui-datepicker-prev, .cmb_element .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
|
572 |
+
.cmb_element .ui-datepicker .ui-datepicker-prev-hover, .cmb_element .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
|
573 |
+
.cmb_element .ui-datepicker .ui-datepicker-prev { left:2px; }
|
574 |
+
.cmb_element .ui-datepicker .ui-datepicker-next { right:2px; }
|
575 |
+
.cmb_element .ui-datepicker .ui-datepicker-prev-hover { left:1px; }
|
576 |
+
.cmb_element .ui-datepicker .ui-datepicker-next-hover { right:1px; }
|
577 |
+
.cmb_element .ui-datepicker .ui-datepicker-prev span, .cmb_element .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
|
578 |
+
.cmb_element .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
|
579 |
+
.cmb_element .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
|
580 |
+
.cmb_element .ui-datepicker select.ui-datepicker-month-year {width: 100%;}
|
581 |
+
.cmb_element .ui-datepicker select.ui-datepicker-month,
|
582 |
+
.cmb_element .ui-datepicker select.ui-datepicker-year { width: 49%;}
|
583 |
+
.cmb_element .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
|
584 |
+
.cmb_element .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
|
585 |
+
.cmb_element .ui-datepicker td { border: 0; padding: 1px; }
|
586 |
+
.cmb_element .ui-datepicker td span, .cmb_element .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
|
587 |
+
.cmb_element .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
|
588 |
+
.cmb_element .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
|
589 |
+
.cmb_element .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
|
590 |
+
.cmb_element .ui-datepicker.ui-datepicker-multi { width:auto; }
|
591 |
+
.cmb_element .ui-datepicker-multi .ui-datepicker-group { float:left; }
|
592 |
+
.cmb_element .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
|
593 |
+
.cmb_element .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
|
594 |
+
.cmb_element .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
|
595 |
+
.cmb_element .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
|
596 |
+
.cmb_element .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
|
597 |
+
.cmb_element .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
|
598 |
+
.cmb_element .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
|
599 |
+
.cmb_element .ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
|
600 |
+
.cmb_element .ui-datepicker-rtl { direction: rtl; }
|
601 |
+
.cmb_element .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
|
602 |
+
.cmb_element .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
|
603 |
+
.cmb_element .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
|
604 |
+
.cmb_element .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
|
605 |
+
.cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
|
606 |
+
.cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
|
607 |
+
.cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
|
608 |
+
.cmb_element .ui-datepicker-rtl .ui-datepicker-group { float:right; }
|
609 |
+
.cmb_element .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
610 |
+
.cmb_element .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
611 |
+
.cmb_element .ui-datepicker-cover {
|
612 |
+
display: none; /*sorry for IE5*/
|
613 |
+
display/**/: block; /*sorry for IE5*/
|
614 |
+
position: absolute; /*must have*/
|
615 |
+
z-index: -1; /*must have*/
|
616 |
+
filter: mask(); /*must have*/
|
617 |
+
top: -4px; /*must have*/
|
618 |
+
left: -4px; /*must have*/
|
619 |
+
width: 200px; /*must have*/
|
620 |
+
height: 200px; /*must have*/
|
621 |
+
}
|
lib/cmb_metaboxes/style.min.css
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
table.cmb_metabox{clear:both}.post-new-php table.cmb_metabox .cmb-nested-table td,.post-new-php table.cmb_metabox .repeatable-group th,.post-new-php table.cmb_metabox .repeatable-group:first-of-type,.post-php table.cmb_metabox .cmb-nested-table td,.post-php table.cmb_metabox .repeatable-group th,.post-php table.cmb_metabox .repeatable-group:first-of-type,table.cmb_metabox tbody>tr:first-of-type>td,table.cmb_metabox tbody>tr:first-of-type>th,table.cmb_metabox>tr:first-of-type>td,table.cmb_metabox>tr:first-of-type>th{border:0}.post-new-php table.cmb_metabox .repeatable-group,.post-new-php table.cmb_metabox td,.post-new-php table.cmb_metabox th,.post-php table.cmb_metabox .repeatable-group,.post-php table.cmb_metabox td,.post-php table.cmb_metabox th{border-top:1px solid #E9E9E9}.repeatable-group th{padding:5px}.repeatable-group .shift-rows{text-decoration:none;margin-right:5px;font-size:1.2em}.repeatable-group .cmb_upload_button{float:right}#poststuff .repeatable-group h2{margin:0}.cmb-group-title h4{font-size:1.2em;font-weight:500;border-bottom:1px solid #ddd}.post-new-php table.cmb_metabox th,.post-php table.cmb_metabox th{text-align:right;font-weight:700}.post-new-php table.cmb_metabox table th,.post-php table.cmb_metabox table th{text-align:left}table.cmb_metabox th label{margin-top:5px;display:block}p.cmb_metabox_description{color:#AAA;font-style:italic;margin:2px 0!important}span.cmb_metabox_description{color:#AAA;font-style:italic}table.cmb_metabox input,table.cmb_metabox textarea{font-size:14px;padding:5px}table.cmb_metabox input[type=text],table.cmb_metabox textarea{width:97%}table.cmb_metabox textarea.cmb_textarea_code{font-family:Consolas,Monaco,monospace;line-height:16px}table.cmb_metabox input.cmb_text_small,table.cmb_metabox input.cmb_timepicker{width:100px;margin-right:15px}table.cmb_metabox input.cmb_text_money{width:90px;margin-right:15px}table.cmb_metabox input.cmb_text_medium{width:230px;margin-right:15px}table.cmb_metabox input.cmb_upload_file{width:65%}table.cmb_metabox input.ed_button{padding:2px 4px}table.cmb_metabox li{font-size:14px;margin:1px 0 5px;line-height:16px}table.cmb_metabox ul{padding-top:5px;margin:0}table.cmb_metabox select{font-size:14px;margin-top:3px}table.cmb_metabox input:focus,table.cmb_metabox textarea:focus{background:#fffff8}.cmb_metabox_title{margin:0 0 5px;padding:5px 0 0}.edit-tags-php .cmb_metabox_title,.profile-php .cmb_metabox_title,.user-edit-php .cmb_metabox_title{margin-left:-10px}.cmb-inline ul{padding:4px 0 0}.cmb-inline li{display:inline-block;padding-right:18px}table.cmb_metabox input[type=checkbox],table.cmb_metabox input[type=radio]{margin:0 5px 0 0;padding:0}table.cmb_metabox .mceLayout{border:1px solid #DFDFDF!important}table.cmb_metabox .mceIframeContainer{background:#FFF}table.cmb_metabox .meta_mce{width:97%}table.cmb_metabox .meta_mce textarea{width:100%}table.cmb_metabox .cmb_media_status{margin:10px 0 0}table.cmb_metabox .cmb_media_status .img_status{clear:none;float:left;display:inline-block;margin-right:10px;width:auto}table.cmb_metabox .cmb-type-file_list .cmb_media_status .img_status{clear:none;float:left;margin-right:10px;width:auto}table.cmb_metabox .cmb_media_status .embed_status,table.cmb_metabox .cmb_media_status .img_status{position:relative}table.cmb_metabox .cmb_media_status .embed_status,table.cmb_metabox .cmb_media_status .img_status img{border:1px solid #DFDFDF;background:#FAFAFA;max-width:350px;padding:5px;-moz-border-radius:2px;border-radius:2px}table.cmb_metabox .cmb_media_status .embed_status{float:left;max-width:800px}table.cmb_metabox .cmb_media_status .embed_status .cmb_remove_file_button,table.cmb_metabox .cmb_media_status .img_status .cmb_remove_file_button{text-indent:-9999px;background:url(images/ico-delete.png);width:16px;height:16px;position:absolute;top:-5px;left:-5px}table.cmb_metabox .attach_list li{clear:both;display:inline-block;margin-bottom:25px;width:100%}table.cmb_metabox .attach_list li img{float:left;margin-right:10px}#side-sortables table.cmb_metabox input[type=text],.inner-sidebar table.cmb_metabox input[type=text],table.cmb_metabox textarea{width:95%}#side-sortables table.cmb_metabox .cmb_media_status .embed_status img,#side-sortables table.cmb_metabox .cmb_media_status .img_status img,.inner-sidebar table.cmb_metabox .cmb_media_status .embed_status img,.inner-sidebar table.cmb_metabox .cmb_media_status .img_status img{width:90%}#side-sortables table.cmb_metabox label,.inner-sidebar table.cmb_metabox label{display:block;font-weight:700;padding:0 0 5px}#side-sortables table.cmb_metabox .cmb_list label,.inner-sidebar table.cmb_metabox .cmb_list label{display:inline;font-weight:400}#side-sortables table.cmb_metabox .cmb_metabox_description,.inner-sidebar table.cmb_metabox .cmb_metabox_description{display:block;padding:7px 0 0}#side-sortables table.cmb_metabox .cmb_metabox_title,.inner-sidebar table.cmb_metabox .cmb_metabox_title{font-size:1.2em;font-style:italic}.postbox table.cmb_metabox .cmb-spinner{float:left}table.cmb_metabox .wp-color-result,table.cmb_metabox .wp-picker-input-wrap{vertical-align:middle}table.cmb_metabox .wp-color-result,table.cmb_metabox .wp-picker-container{margin:0 10px 0 0}div.time-picker{position:absolute;height:191px;width:6em;overflow:auto;background:#fff;border:1px solid #aaa;z-index:99;margin:0}div.time-picker-12hours{width:8em}div.time-picker ul{list-style-type:none;margin:0;padding:0}div.time-picker li{cursor:pointer;height:10px;font:14px/1 Helvetica,Arial,sans-serif;padding:4px 3px}div.time-picker li.selected{background:#0063CE;color:#fff}.cmb_element .ui-helper-hidden{display:none}.cmb_element .ui-helper-hidden-accessible{position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.cmb_element .ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.cmb_element .ui-helper-clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden}* html .ui-helper-clearfix{height:1%}.cmb_element .ui-helper-clearfix{display:block}.cmb_element .ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.cmb_element .ui-state-disabled{cursor:default!important}.cmb_element .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.cmb_element .ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.cmb_element .ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.cmb_element .ui-widget .ui-widget{font-size:1em}.cmb_element .ui-widget button,.cmb_element .ui-widget input,.cmb_element .ui-widget select,.cmb_element .ui-widget textarea{font-family:Verdana,Arial,sans-serif;font-size:1em}.cmb_element .ui-widget-content{border:1px solid #aaa;background:#fff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x;color:#222}.cmb_element .ui-widget-content a{color:#222}.cmb_element .ui-widget-header{border:1px solid #aaa;background:#ccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x;color:#222;font-weight:700}.cmb_element .ui-widget-header a{color:#222}.cmb_element .ui-state-default,.cmb_element .ui-widget-content .ui-state-default,.cmb_element .ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;font-weight:400;color:#555}.cmb_element .ui-state-default a,.cmb_element .ui-state-default a:link,.cmb_element .ui-state-default a:visited{color:#555;text-decoration:none}.cmb_element .ui-state-focus,.cmb_element .ui-state-hover,.cmb_element .ui-widget-content .ui-state-focus,.cmb_element .ui-widget-content .ui-state-hover,.cmb_element .ui-widget-header .ui-state-focus,.cmb_element .ui-widget-header .ui-state-hover{border:1px solid #999;background:#dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x;font-weight:400;color:#212121}.cmb_element .ui-state-hover a,.cmb_element .ui-state-hover a:hover{color:#212121;text-decoration:none}.cmb_element .ui-state-active,.cmb_element .ui-widget-content .ui-state-active,.cmb_element .ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:400;color:#212121}.cmb_element .ui-state-active a,.cmb_element .ui-state-active a:link,.cmb_element .ui-state-active a:visited{color:#212121;text-decoration:none}.cmb_element .ui-widget :active{outline:0}.cmb_element .ui-state-highlight,.cmb_element .ui-widget-content .ui-state-highlight,.cmb_element .ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x;color:#363636}.cmb_element .ui-state-highlight a,.cmb_element .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.cmb_element .ui-state-error,.cmb_element .ui-widget-content .ui-state-error,.cmb_element .ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;color:#cd0a0a}.cmb_element .ui-state-error a,.cmb_element .ui-state-error-text,.cmb_element .ui-widget-content .ui-state-error a,.cmb_element .ui-widget-content .ui-state-error-text,.cmb_element .ui-widget-header .ui-state-error a,.cmb_element .ui-widget-header .ui-state-error-text{color:#cd0a0a}.cmb_element .ui-priority-primary,.cmb_element .ui-widget-content .ui-priority-primary,.cmb_element .ui-widget-header .ui-priority-primary{font-weight:700}.cmb_element .ui-priority-secondary,.cmb_element .ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:400}.cmb_element .ui-state-disabled,.cmb_element .ui-widget-content .ui-state-disabled,.cmb_element .ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.cmb_element .ui-icon{width:16px;height:16px;background-image:url(images/ui-icons_222222_256x240.png)}.cmb_element .ui-widget-content .ui-icon,.cmb_element .ui-widget-header .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.cmb_element .ui-state-default .ui-icon{background-image:url(images/ui-icons_888888_256x240.png)}.cmb_element .ui-state-active .ui-icon,.cmb_element .ui-state-focus .ui-icon,.cmb_element .ui-state-hover .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.cmb_element .ui-state-highlight .ui-icon{background-image:url(images/ui-icons_2e83ff_256x240.png)}.cmb_element .ui-state-error .ui-icon,.cmb_element .ui-state-error-text .ui-icon{background-image:url(images/ui-icons_cd0a0a_256x240.png)}.cmb_element .ui-icon-carat-1-n{background-position:0 0}.cmb_element .ui-icon-carat-1-ne{background-position:-16px 0}.cmb_element .ui-icon-carat-1-e{background-position:-32px 0}.cmb_element .ui-icon-carat-1-se{background-position:-48px 0}.cmb_element .ui-icon-carat-1-s{background-position:-64px 0}.cmb_element .ui-icon-carat-1-sw{background-position:-80px 0}.cmb_element .ui-icon-carat-1-w{background-position:-96px 0}.cmb_element .ui-icon-carat-1-nw{background-position:-112px 0}.cmb_element .ui-icon-carat-2-n-s{background-position:-128px 0}.cmb_element .ui-icon-carat-2-e-w{background-position:-144px 0}.cmb_element .ui-icon-triangle-1-n{background-position:0 -16px}.cmb_element .ui-icon-triangle-1-ne{background-position:-16px -16px}.cmb_element .ui-icon-triangle-1-e{background-position:-32px -16px}.cmb_element .ui-icon-triangle-1-se{background-position:-48px -16px}.cmb_element .ui-icon-triangle-1-s{background-position:-64px -16px}.cmb_element .ui-icon-triangle-1-sw{background-position:-80px -16px}.cmb_element .ui-icon-triangle-1-w{background-position:-96px -16px}.cmb_element .ui-icon-triangle-1-nw{background-position:-112px -16px}.cmb_element .ui-icon-triangle-2-n-s{background-position:-128px -16px}.cmb_element .ui-icon-triangle-2-e-w{background-position:-144px -16px}.cmb_element .ui-icon-arrow-1-n{background-position:0 -32px}.cmb_element .ui-icon-arrow-1-ne{background-position:-16px -32px}.cmb_element .ui-icon-arrow-1-e{background-position:-32px -32px}.cmb_element .ui-icon-arrow-1-se{background-position:-48px -32px}.cmb_element .ui-icon-arrow-1-s{background-position:-64px -32px}.cmb_element .ui-icon-arrow-1-sw{background-position:-80px -32px}.cmb_element .ui-icon-arrow-1-w{background-position:-96px -32px}.cmb_element .ui-icon-arrow-1-nw{background-position:-112px -32px}.cmb_element .ui-icon-arrow-2-n-s{background-position:-128px -32px}.cmb_element .ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.cmb_element .ui-icon-arrow-2-e-w{background-position:-160px -32px}.cmb_element .ui-icon-arrow-2-se-nw{background-position:-176px -32px}.cmb_element .ui-icon-arrowstop-1-n{background-position:-192px -32px}.cmb_element .ui-icon-arrowstop-1-e{background-position:-208px -32px}.cmb_element .ui-icon-arrowstop-1-s{background-position:-224px -32px}.cmb_element .ui-icon-arrowstop-1-w{background-position:-240px -32px}.cmb_element .ui-icon-arrowthick-1-n{background-position:0 -48px}.cmb_element .ui-icon-arrowthick-1-ne{background-position:-16px -48px}.cmb_element .ui-icon-arrowthick-1-e{background-position:-32px -48px}.cmb_element .ui-icon-arrowthick-1-se{background-position:-48px -48px}.cmb_element .ui-icon-arrowthick-1-s{background-position:-64px -48px}.cmb_element .ui-icon-arrowthick-1-sw{background-position:-80px -48px}.cmb_element .ui-icon-arrowthick-1-w{background-position:-96px -48px}.cmb_element .ui-icon-arrowthick-1-nw{background-position:-112px -48px}.cmb_element .ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.cmb_element .ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.cmb_element .ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.cmb_element .ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.cmb_element .ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.cmb_element .ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.cmb_element .ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.cmb_element .ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.cmb_element .ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.cmb_element .ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.cmb_element .ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.cmb_element .ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.cmb_element .ui-icon-arrowreturn-1-w{background-position:-64px -64px}.cmb_element .ui-icon-arrowreturn-1-n{background-position:-80px -64px}.cmb_element .ui-icon-arrowreturn-1-e{background-position:-96px -64px}.cmb_element .ui-icon-arrowreturn-1-s{background-position:-112px -64px}.cmb_element .ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.cmb_element .ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.cmb_element .ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.cmb_element .ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.cmb_element .ui-icon-arrow-4{background-position:0 -80px}.cmb_element .ui-icon-arrow-4-diag{background-position:-16px -80px}.cmb_element .ui-icon-extlink{background-position:-32px -80px}.cmb_element .ui-icon-newwin{background-position:-48px -80px}.cmb_element .ui-icon-refresh{background-position:-64px -80px}.cmb_element .ui-icon-shuffle{background-position:-80px -80px}.cmb_element .ui-icon-transfer-e-w{background-position:-96px -80px}.cmb_element .ui-icon-transferthick-e-w{background-position:-112px -80px}.cmb_element .ui-icon-folder-collapsed{background-position:0 -96px}.cmb_element .ui-icon-folder-open{background-position:-16px -96px}.cmb_element .ui-icon-document{background-position:-32px -96px}.cmb_element .ui-icon-document-b{background-position:-48px -96px}.cmb_element .ui-icon-note{background-position:-64px -96px}.cmb_element .ui-icon-mail-closed{background-position:-80px -96px}.cmb_element .ui-icon-mail-open{background-position:-96px -96px}.cmb_element .ui-icon-suitcase{background-position:-112px -96px}.cmb_element .ui-icon-comment{background-position:-128px -96px}.cmb_element .ui-icon-person{background-position:-144px -96px}.cmb_element .ui-icon-print{background-position:-160px -96px}.cmb_element .ui-icon-trash{background-position:-176px -96px}.cmb_element .ui-icon-locked{background-position:-192px -96px}.cmb_element .ui-icon-unlocked{background-position:-208px -96px}.cmb_element .ui-icon-bookmark{background-position:-224px -96px}.cmb_element .ui-icon-tag{background-position:-240px -96px}.cmb_element .ui-icon-home{background-position:0 -112px}.cmb_element .ui-icon-flag{background-position:-16px -112px}.cmb_element .ui-icon-calendar{background-position:-32px -112px}.cmb_element .ui-icon-cart{background-position:-48px -112px}.cmb_element .ui-icon-pencil{background-position:-64px -112px}.cmb_element .ui-icon-clock{background-position:-80px -112px}.cmb_element .ui-icon-disk{background-position:-96px -112px}.cmb_element .ui-icon-calculator{background-position:-112px -112px}.cmb_element .ui-icon-zoomin{background-position:-128px -112px}.cmb_element .ui-icon-zoomout{background-position:-144px -112px}.cmb_element .ui-icon-search{background-position:-160px -112px}.cmb_element .ui-icon-wrench{background-position:-176px -112px}.cmb_element .ui-icon-gear{background-position:-192px -112px}.cmb_element .ui-icon-heart{background-position:-208px -112px}.cmb_element .ui-icon-star{background-position:-224px -112px}.cmb_element .ui-icon-link{background-position:-240px -112px}.cmb_element .ui-icon-cancel{background-position:0 -128px}.cmb_element .ui-icon-plus{background-position:-16px -128px}.cmb_element .ui-icon-plusthick{background-position:-32px -128px}.cmb_element .ui-icon-minus{background-position:-48px -128px}.cmb_element .ui-icon-minusthick{background-position:-64px -128px}.cmb_element .ui-icon-close{background-position:-80px -128px}.cmb_element .ui-icon-closethick{background-position:-96px -128px}.cmb_element .ui-icon-key{background-position:-112px -128px}.cmb_element .ui-icon-lightbulb{background-position:-128px -128px}.cmb_element .ui-icon-scissors{background-position:-144px -128px}.cmb_element .ui-icon-clipboard{background-position:-160px -128px}.cmb_element .ui-icon-copy{background-position:-176px -128px}.cmb_element .ui-icon-contact{background-position:-192px -128px}.cmb_element .ui-icon-image{background-position:-208px -128px}.cmb_element .ui-icon-video{background-position:-224px -128px}.cmb_element .ui-icon-script{background-position:-240px -128px}.cmb_element .ui-icon-alert{background-position:0 -144px}.cmb_element .ui-icon-info{background-position:-16px -144px}.cmb_element .ui-icon-notice{background-position:-32px -144px}.cmb_element .ui-icon-help{background-position:-48px -144px}.cmb_element .ui-icon-check{background-position:-64px -144px}.cmb_element .ui-icon-bullet{background-position:-80px -144px}.cmb_element .ui-icon-radio-off{background-position:-96px -144px}.cmb_element .ui-icon-radio-on{background-position:-112px -144px}.cmb_element .ui-icon-pin-w{background-position:-128px -144px}.cmb_element .ui-icon-pin-s{background-position:-144px -144px}.cmb_element .ui-icon-play{background-position:0 -160px}.cmb_element .ui-icon-pause{background-position:-16px -160px}.cmb_element .ui-icon-seek-next{background-position:-32px -160px}.cmb_element .ui-icon-seek-prev{background-position:-48px -160px}.cmb_element .ui-icon-seek-end{background-position:-64px -160px}.cmb_element .ui-icon-seek-first,.cmb_element .ui-icon-seek-start{background-position:-80px -160px}.cmb_element .ui-icon-stop{background-position:-96px -160px}.cmb_element .ui-icon-eject{background-position:-112px -160px}.cmb_element .ui-icon-volume-off{background-position:-128px -160px}.cmb_element .ui-icon-volume-on{background-position:-144px -160px}.cmb_element .ui-icon-power{background-position:0 -176px}.cmb_element .ui-icon-signal-diag{background-position:-16px -176px}.cmb_element .ui-icon-signal{background-position:-32px -176px}.cmb_element .ui-icon-battery-0{background-position:-48px -176px}.cmb_element .ui-icon-battery-1{background-position:-64px -176px}.cmb_element .ui-icon-battery-2{background-position:-80px -176px}.cmb_element .ui-icon-battery-3{background-position:-96px -176px}.cmb_element .ui-icon-circle-plus{background-position:0 -192px}.cmb_element .ui-icon-circle-minus{background-position:-16px -192px}.cmb_element .ui-icon-circle-close{background-position:-32px -192px}.cmb_element .ui-icon-circle-triangle-e{background-position:-48px -192px}.cmb_element .ui-icon-circle-triangle-s{background-position:-64px -192px}.cmb_element .ui-icon-circle-triangle-w{background-position:-80px -192px}.cmb_element .ui-icon-circle-triangle-n{background-position:-96px -192px}.cmb_element .ui-icon-circle-arrow-e{background-position:-112px -192px}.cmb_element .ui-icon-circle-arrow-s{background-position:-128px -192px}.cmb_element .ui-icon-circle-arrow-w{background-position:-144px -192px}.cmb_element .ui-icon-circle-arrow-n{background-position:-160px -192px}.cmb_element .ui-icon-circle-zoomin{background-position:-176px -192px}.cmb_element .ui-icon-circle-zoomout{background-position:-192px -192px}.cmb_element .ui-icon-circle-check{background-position:-208px -192px}.cmb_element .ui-icon-circlesmall-plus{background-position:0 -208px}.cmb_element .ui-icon-circlesmall-minus{background-position:-16px -208px}.cmb_element .ui-icon-circlesmall-close{background-position:-32px -208px}.cmb_element .ui-icon-squaresmall-plus{background-position:-48px -208px}.cmb_element .ui-icon-squaresmall-minus{background-position:-64px -208px}.cmb_element .ui-icon-squaresmall-close{background-position:-80px -208px}.cmb_element .ui-icon-grip-dotted-vertical{background-position:0 -224px}.cmb_element .ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.cmb_element .ui-icon-grip-solid-vertical{background-position:-32px -224px}.cmb_element .ui-icon-grip-solid-horizontal{background-position:-48px -224px}.cmb_element .ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.cmb_element .ui-icon-grip-diagonal-se{background-position:-80px -224px}.cmb_element .ui-corner-all,.cmb_element .ui-corner-left,.cmb_element .ui-corner-tl,.cmb_element .ui-corner-top{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;-khtml-border-top-left-radius:4px;border-top-left-radius:4px}.cmb_element .ui-corner-all,.cmb_element .ui-corner-right,.cmb_element .ui-corner-top,.cmb_element .ui-corner-tr{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;-khtml-border-top-right-radius:4px;border-top-right-radius:4px}.cmb_element .ui-corner-all,.cmb_element .ui-corner-bl,.cmb_element .ui-corner-bottom,.cmb_element .ui-corner-left{-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;-khtml-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.cmb_element .ui-corner-all,.cmb_element .ui-corner-bottom,.cmb_element .ui-corner-br,.cmb_element .ui-corner-right{-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;-khtml-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.cmb_element .ui-widget-overlay{background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.cmb_element .ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);-moz-border-radius:8px;-khtml-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}.cmb_element .ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.cmb_element .ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.cmb_element .ui-datepicker .ui-datepicker-next,.cmb_element .ui-datepicker .ui-datepicker-prev{position:absolute;top:2px;width:1.8em;height:1.8em}.cmb_element .ui-datepicker .ui-datepicker-next-hover,.cmb_element .ui-datepicker .ui-datepicker-prev-hover{top:1px}.cmb_element .ui-datepicker .ui-datepicker-prev{left:2px}.cmb_element .ui-datepicker .ui-datepicker-next{right:2px}.cmb_element .ui-datepicker .ui-datepicker-prev-hover{left:1px}.cmb_element .ui-datepicker .ui-datepicker-next-hover{right:1px}.cmb_element .ui-datepicker .ui-datepicker-next span,.cmb_element .ui-datepicker .ui-datepicker-prev span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.cmb_element .ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.cmb_element .ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.cmb_element .ui-datepicker select.ui-datepicker-month-year{width:100%}.cmb_element .ui-datepicker select.ui-datepicker-month,.cmb_element .ui-datepicker select.ui-datepicker-year{width:49%}.cmb_element .ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.cmb_element .ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:700;border:0}.cmb_element .ui-datepicker td{border:0;padding:1px}.cmb_element .ui-datepicker td a,.cmb_element .ui-datepicker td span{display:block;padding:.2em;text-align:right;text-decoration:none}.cmb_element .ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.cmb_element .ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em;width:auto;overflow:visible}.cmb_element .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.cmb_element .ui-datepicker.ui-datepicker-multi{width:auto}.cmb_element .ui-datepicker-multi .ui-datepicker-group{float:left}.cmb_element .ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.cmb_element .ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.cmb_element .ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.cmb_element .ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.cmb_element .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.cmb_element .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.cmb_element .ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.cmb_element .ui-datepicker-row-break{clear:both;width:100%;font-size:0}.cmb_element .ui-datepicker-rtl{direction:rtl}.cmb_element .ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.cmb_element .ui-datepicker-rtl .ui-datepicker-group{float:right}.cmb_element .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.cmb_element .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.cmb_element .ui-datepicker-cover{display:none;display:block;position:absolute;z-index:-1;filter:mask();top:-4px;left:-4px;width:200px;height:200px}
|
readme.txt
CHANGED
@@ -3,8 +3,8 @@ Contributors: eherman24
|
|
3 |
Donate link: http://www.evan-herman.com/contact/?contact-reason=I%20want%20to%20make%20a%20donation%20for%20all%20your%20hard%20work
|
4 |
Tags: vertical, timeline, animated, css3, animations, evan, herman, evan herman, easy, time, line, font awesome, font, awesome, announcements, notifications, simple, events, calendar, scroll, triggered, scrolling, animated, fade, in, fade in
|
5 |
Requires at least: 3.9
|
6 |
-
Tested up to: 4.3
|
7 |
-
Stable tag: 1.1.7.
|
8 |
License: GPLv2 or later
|
9 |
|
10 |
Timeline express allows you to create a beautiful vertical animated and responsive timeline of posts , without writing a single line of code. Sweet!
|
@@ -339,6 +339,9 @@ add_filter( 'timeline_express_custom_template' , 'custom_timeline_express_templa
|
|
339 |
|
340 |
== Changelog ==
|
341 |
|
|
|
|
|
|
|
342 |
= 1.1.7.3 - July 15th, 2015 =
|
343 |
* Remove duplicate date picker fields on announcements
|
344 |
|
3 |
Donate link: http://www.evan-herman.com/contact/?contact-reason=I%20want%20to%20make%20a%20donation%20for%20all%20your%20hard%20work
|
4 |
Tags: vertical, timeline, animated, css3, animations, evan, herman, evan herman, easy, time, line, font awesome, font, awesome, announcements, notifications, simple, events, calendar, scroll, triggered, scrolling, animated, fade, in, fade in
|
5 |
Requires at least: 3.9
|
6 |
+
Tested up to: 4.3.1
|
7 |
+
Stable tag: 1.1.7.4
|
8 |
License: GPLv2 or later
|
9 |
|
10 |
Timeline express allows you to create a beautiful vertical animated and responsive timeline of posts , without writing a single line of code. Sweet!
|
339 |
|
340 |
== Changelog ==
|
341 |
|
342 |
+
= 1.1.7.4 - September 18th, 2015 =
|
343 |
+
* Fixed adding custom fields and using an image as an icon (https://gist.github.com/EvanHerman/6bbc8de82f34b4cb3c5c#comments)
|
344 |
+
|
345 |
= 1.1.7.3 - July 15th, 2015 =
|
346 |
* Remove duplicate date picker fields on announcements
|
347 |
|
timeline-express.php
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
Plugin Name: Timeline Express
|
5 |
Plugin URI: http://www.evan-herman.com
|
6 |
Description: Create a beautiful vertical, CSS3 animated and responsive timeline in minutes flat without writing code.
|
7 |
-
Version: 1.1.7.
|
8 |
Author: Evan Herman
|
9 |
Author URI: http://www.evan-herman.com
|
10 |
License: GPL2
|
@@ -28,7 +28,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
28 |
#_________________________________________________ CONSTANTS
|
29 |
|
30 |
/** Configuration **/
|
31 |
-
if(!defined('TIMELINE_EXPRESS_VERSION_CURRENT')) define('TIMELINE_EXPRESS_VERSION_CURRENT', '1.1.7.
|
32 |
if(!defined('TIMELINE_EXPRESS_PATH')) define('TIMELINE_EXPRESS_PATH', plugin_dir_path( __FILE__ ));
|
33 |
if(!defined('TIMELINE_EXPRESS_URL')) define('TIMELINE_EXPRESS_URL', plugins_url('timeline-express/'));
|
34 |
if(!defined('TIMELINE_EXPRESS_URL_WP')) define('TIMELINE_EXPRESS_URL_WP', get_bloginfo('url'));
|
4 |
Plugin Name: Timeline Express
|
5 |
Plugin URI: http://www.evan-herman.com
|
6 |
Description: Create a beautiful vertical, CSS3 animated and responsive timeline in minutes flat without writing code.
|
7 |
+
Version: 1.1.7.4
|
8 |
Author: Evan Herman
|
9 |
Author URI: http://www.evan-herman.com
|
10 |
License: GPL2
|
28 |
#_________________________________________________ CONSTANTS
|
29 |
|
30 |
/** Configuration **/
|
31 |
+
if(!defined('TIMELINE_EXPRESS_VERSION_CURRENT')) define('TIMELINE_EXPRESS_VERSION_CURRENT', '1.1.7.4');
|
32 |
if(!defined('TIMELINE_EXPRESS_PATH')) define('TIMELINE_EXPRESS_PATH', plugin_dir_path( __FILE__ ));
|
33 |
if(!defined('TIMELINE_EXPRESS_URL')) define('TIMELINE_EXPRESS_URL', plugins_url('timeline-express/'));
|
34 |
if(!defined('TIMELINE_EXPRESS_URL_WP')) define('TIMELINE_EXPRESS_URL_WP', get_bloginfo('url'));
|