Meta Box - Version 4.5

Version Description

  • Improvement: Separate esc_meta method
  • Improvement: Add ability to use URL to retrieve options for autocomplete field
  • Improvement: Add rwmb_get_field and rwmb_the_field functions to get and display field values in the frontend
  • Improvement: Add field type custom_html to display any HTML in the meta box
  • Improvement: Add field type key_value which allows users to add any number of key-value pairs
  • Improvement: Use single JS file to display Google Maps in the frontend. No more inline Javascript.
  • Improvement: Code refactor
Download this release

Release Info

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

Code changes from version 4.4.1 to 4.5

Files changed (84) hide show
  1. css/checkbox.css +4 -0
  2. css/color.css +7 -1
  3. css/jqueryui/jquery-ui-timepicker-addon.css +0 -6
  4. css/jqueryui/jquery-ui-timepicker-addon.min.css +5 -0
  5. css/map.css +4 -0
  6. css/taxonomy.css +5 -1
  7. inc/field-multiple-values.php +78 -0
  8. inc/field.php +147 -23
  9. inc/fields/autocomplete.php +40 -62
  10. inc/fields/checkbox-list.php +1 -69
  11. inc/fields/checkbox.php +37 -2
  12. inc/fields/custom-html.php +27 -0
  13. inc/fields/date.php +0 -1
  14. inc/fields/datetime.php +43 -30
  15. inc/fields/fieldset-text.php +62 -33
  16. inc/fields/file.php +90 -0
  17. inc/fields/heading.php +1 -1
  18. inc/fields/image-select.php +62 -0
  19. inc/fields/image.php +80 -0
  20. inc/fields/key-value.php +158 -0
  21. inc/fields/map.php +107 -10
  22. inc/fields/oembed.php +29 -0
  23. inc/fields/post.php +29 -38
  24. inc/fields/radio.php +19 -0
  25. inc/fields/select-advanced.php +1 -1
  26. inc/fields/select.php +78 -30
  27. inc/fields/taxonomy-advanced.php +32 -0
  28. inc/fields/taxonomy.php +105 -4
  29. inc/fields/text-list.php +51 -66
  30. inc/fields/textarea.php +12 -0
  31. inc/fields/time.php +19 -22
  32. inc/fields/user.php +17 -57
  33. inc/fields/wysiwyg.php +12 -0
  34. inc/helpers.php +130 -283
  35. inc/init.php +5 -0
  36. inc/meta-box.php +17 -5
  37. js/autocomplete.js +1 -1
  38. js/clone.js +5 -5
  39. js/datetime.js +13 -3
  40. js/jqueryui/jquery-ui-timepicker-addon-i18n.min.js +4 -0
  41. js/jqueryui/jquery-ui-timepicker-addon.js +0 -71
  42. js/jqueryui/jquery-ui-timepicker-addon.min.js +5 -0
  43. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-af.js +0 -20
  44. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-bg.js +0 -20
  45. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-ca.js +0 -20
  46. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-cs.js +0 -20
  47. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-de.js +0 -20
  48. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-el.js +0 -20
  49. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-es.js +0 -20
  50. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-et.js +0 -20
  51. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-eu.js +0 -20
  52. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-fi.js +0 -20
  53. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-fr.js +0 -20
  54. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-gl.js +0 -20
  55. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-he.js +0 -20
  56. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-hu.js +0 -20
  57. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-id.js +0 -20
  58. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-it.js +0 -20
  59. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-ja.js +0 -20
  60. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-ko.js +0 -20
  61. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-lt.js +0 -20
  62. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-nl.js +0 -20
  63. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-no.js +0 -20
  64. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-pl.js +0 -20
  65. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-pt-BR.js +0 -20
  66. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-pt.js +0 -20
  67. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-ro.js +0 -20
  68. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-ru.js +0 -20
  69. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-sk.js +0 -20
  70. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-sv.js +0 -20
  71. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-th.js +0 -17
  72. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-tr.js +0 -20
  73. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-uk.js +0 -20
  74. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-vi.js +0 -20
  75. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-zh-CN.js +0 -20
  76. js/jqueryui/timepicker-i18n/jquery-ui-timepicker-zh-TW.js +0 -20
  77. js/map-frontend.js +71 -0
  78. js/map.js +16 -0
  79. js/plupload-image.js +1 -1
  80. js/time.js +14 -4
  81. lang/fr_FR.mo +0 -0
  82. lang/fr_FR.po +456 -0
  83. meta-box.php +18 -20
  84. readme.txt +38 -4
css/checkbox.css ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ .rwmb-checkbox-wrapper .description {
2
+ display: inline;
3
+ font-style: normal;
4
+ }
css/color.css CHANGED
@@ -4,4 +4,10 @@
4
  background: rgb(238, 238, 238);
5
  border: 1px solid rgb(204, 204, 204);
6
  position: absolute;
7
- }
 
 
 
 
 
 
4
  background: rgb(238, 238, 238);
5
  border: 1px solid rgb(204, 204, 204);
6
  position: absolute;
7
+ }
8
+ .rwmb-color-wrapper .wp-picker-container {
9
+ position: relative;
10
+ }
11
+ .rwmb-color-wrapper .wp-picker-holder {
12
+ position: absolute;
13
+ }
css/jqueryui/jquery-ui-timepicker-addon.css DELETED
@@ -1,6 +0,0 @@
1
- .ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }
2
- .ui-timepicker-div dl { text-align: left; }
3
- .ui-timepicker-div dl dt { height: 25px; }
4
- .ui-timepicker-div dl dd { margin: -25px 10px 10px 65px; }
5
- .ui-timepicker-div td { font-size: 90%; }
6
- .ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; }
 
 
 
 
 
 
css/jqueryui/jquery-ui-timepicker-addon.min.css ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ /*! jQuery Timepicker Addon - v1.5.0 - 2014-09-01
2
+ * http://trentrichardson.com/examples/timepicker
3
+ * Copyright (c) 2014 Trent Richardson; Licensed MIT */
4
+
5
+ .ui-timepicker-div .ui-widget-header{margin-bottom:8px}.ui-timepicker-div dl{text-align:left}.ui-timepicker-div dl dt{float:left;clear:left;padding:0 0 0 5px}.ui-timepicker-div dl dd{margin:0 10px 10px 40%}.ui-timepicker-div td{font-size:90%}.ui-tpicker-grid-label{background:0 0;border:0;margin:0;padding:0}.ui-timepicker-rtl{direction:rtl}.ui-timepicker-rtl dl{text-align:right;padding:0 5px 0 0}.ui-timepicker-rtl dl dt{float:right;clear:right}.ui-timepicker-rtl dl dd{margin:0 40% 10px 10px}
css/map.css ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ .rwmb-map-canvas {
2
+ width: 100%;
3
+ height: 400px;
4
+ }
css/taxonomy.css CHANGED
@@ -2,9 +2,13 @@
2
  margin-left: 15px;
3
  margin-top: 5px;
4
  }
 
 
 
 
5
  .rw-taxonomy-tree.active {
6
  display: inline-block;
7
  }
8
  .rw-taxonomy-tree.disabled {
9
  display: none;
10
- }
2
  margin-left: 15px;
3
  margin-top: 5px;
4
  }
5
+ .rwmb-input > .rw-taxonomy-tree {
6
+ margin-left: 0;
7
+ margin-top: 0;
8
+ }
9
  .rw-taxonomy-tree.active {
10
  display: inline-block;
11
  }
12
  .rw-taxonomy-tree.disabled {
13
  display: none;
14
+ }
inc/field-multiple-values.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Prevent loading this file directly
3
+ defined( 'ABSPATH' ) || exit;
4
+
5
+ if ( ! class_exists( 'RWMB_Field_Multiple_Values' ) )
6
+ {
7
+ /**
8
+ * This class implements common methods used in fields which have multiple values
9
+ * like checkbox list, autocomplete, etc.
10
+ *
11
+ * The difference when handling actions for these fields are the way they get/set
12
+ * meta value. Briefly:
13
+ * - If field is cloneable, value is saved as a single entry in the database
14
+ * - Otherwise value is saved as multiple entries
15
+ */
16
+ class RWMB_Field_Multiple_Values extends RWMB_Field
17
+ {
18
+ /**
19
+ * Normalize parameters for field
20
+ *
21
+ * @param array $field
22
+ *
23
+ * @return array
24
+ */
25
+ static function normalize_field( $field )
26
+ {
27
+ $field['multiple'] = true;
28
+ $field['field_name'] = $field['id'];
29
+ if ( ! $field['clone'] )
30
+ $field['field_name'] .= '[]';
31
+
32
+ return $field;
33
+ }
34
+
35
+ /**
36
+ * Output the field value
37
+ * Display option name instead of option value
38
+ *
39
+ * @param array $field Field parameters
40
+ * @param array $args Additional arguments. Not used for these fields.
41
+ * @param int|null $post_id Post ID. null for current post. Optional.
42
+ *
43
+ * @return mixed Field value
44
+ */
45
+ static function the_value( $field, $args = array(), $post_id = null )
46
+ {
47
+ $value = self::get_value( $field, $args, $post_id );
48
+ if ( ! $value )
49
+ return '';
50
+
51
+ $output = '<ul>';
52
+ if ( $field['clone'] )
53
+ {
54
+ foreach ( $value as $subvalue )
55
+ {
56
+ $output .= '<li>';
57
+ $output .= '<ul>';
58
+ foreach ( $subvalue as $option )
59
+ {
60
+ $output .= '<li>' . $field['options'][$option] . '</li>';
61
+ }
62
+ $output .= '</ul>';
63
+ $output .= '</li>';
64
+ }
65
+ }
66
+ else
67
+ {
68
+ foreach ( $value as $option )
69
+ {
70
+ $output .= '<li>' . $field['options'][$option] . '</li>';
71
+ }
72
+ }
73
+ $output .= '</ul>';
74
+
75
+ return $output;
76
+ }
77
+ }
78
+ }
inc/field.php CHANGED
@@ -95,7 +95,7 @@ if ( ! class_exists( 'RWMB_Field ' ) )
95
  $input_html = apply_filters( "rwmb_{$id}_html", $input_html, $field, $sub_meta );
96
 
97
  // Remove clone button
98
- $input_html .= call_user_func( array( $field_class, 'remove_clone_button' ), $sub_meta, $sub_field );
99
 
100
  $input_html .= '</div>';
101
 
@@ -206,7 +206,7 @@ if ( ! class_exists( 'RWMB_Field ' ) )
206
  */
207
  static function end_html( $meta, $field )
208
  {
209
- $button = $field['clone'] ? call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'add_clone_button' ) ) : '';
210
  $desc = $field['desc'] ? "<p id='{$field['id']}_description' class='description'>{$field['desc']}</p>" : '';
211
 
212
  // Closes the container
@@ -218,21 +218,27 @@ if ( ! class_exists( 'RWMB_Field ' ) )
218
  /**
219
  * Add clone button
220
  *
 
 
221
  * @return string $html
222
  */
223
- static function add_clone_button()
224
  {
225
- return '<a href="#" class="rwmb-button button-primary add-clone">' . __( '+', 'meta-box' ) . '</a>';
 
226
  }
227
 
228
  /**
229
  * Remove clone button
230
  *
 
 
231
  * @return string $html
232
  */
233
- static function remove_clone_button()
234
  {
235
- return '<a href="#" class="rwmb-button button remove-clone">' . __( '&#8211;', 'meta-box' ) . '</a>';
 
236
  }
237
 
238
  /**
@@ -246,18 +252,48 @@ if ( ! class_exists( 'RWMB_Field ' ) )
246
  */
247
  static function meta( $post_id, $saved, $field )
248
  {
249
- $meta = get_post_meta( $post_id, $field['id'], ! $field['multiple'] );
 
 
 
 
 
 
 
 
250
 
251
  // Use $field['std'] only when the meta box hasn't been saved (i.e. the first time we run)
252
  $meta = ( ! $saved && '' === $meta || array() === $meta ) ? $field['std'] : $meta;
253
 
254
- // Escape attributes for non-wysiwyg fields
255
- if ( 'wysiwyg' !== $field['type'] )
256
- $meta = is_array( $meta ) ? array_map( 'esc_attr', $meta ) : esc_attr( $meta );
 
 
 
 
 
257
 
258
  return $meta;
259
  }
260
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
  /**
262
  * Set value of meta before saving into database
263
  *
@@ -285,6 +321,7 @@ if ( ! class_exists( 'RWMB_Field ' ) )
285
  {
286
  $name = $field['id'];
287
 
 
288
  if ( '' === $new || array() === $new )
289
  {
290
  delete_post_meta( $post_id, $name );
@@ -292,6 +329,20 @@ if ( ! class_exists( 'RWMB_Field ' ) )
292
  return;
293
  }
294
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295
  if ( $field['multiple'] )
296
  {
297
  foreach ( $new as $new_value )
@@ -304,20 +355,11 @@ if ( ! class_exists( 'RWMB_Field ' ) )
304
  if ( ! in_array( $old_value, $new ) )
305
  delete_post_meta( $post_id, $name, $old_value );
306
  }
 
307
  }
308
- else
309
- {
310
- if ( $field['clone'] )
311
- {
312
- $new = (array) $new;
313
- foreach ( $new as $k => $v )
314
- {
315
- if ( '' === $v )
316
- unset( $new[$k] );
317
- }
318
- }
319
- update_post_meta( $post_id, $name, $new );
320
- }
321
  }
322
 
323
  /**
@@ -331,5 +373,87 @@ if ( ! class_exists( 'RWMB_Field ' ) )
331
  {
332
  return $field;
333
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334
  }
335
  }
95
  $input_html = apply_filters( "rwmb_{$id}_html", $input_html, $field, $sub_meta );
96
 
97
  // Remove clone button
98
+ $input_html .= call_user_func( array( $field_class, 'remove_clone_button' ), $sub_field );
99
 
100
  $input_html .= '</div>';
101
 
206
  */
207
  static function end_html( $meta, $field )
208
  {
209
+ $button = $field['clone'] ? call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'add_clone_button' ), $field ) : '';
210
  $desc = $field['desc'] ? "<p id='{$field['id']}_description' class='description'>{$field['desc']}</p>" : '';
211
 
212
  // Closes the container
218
  /**
219
  * Add clone button
220
  *
221
+ * @param array $field Field parameter
222
+ *
223
  * @return string $html
224
  */
225
+ static function add_clone_button( $field )
226
  {
227
+ $text = apply_filters( 'rwmb_add_clone_button_text', __( '+', 'meta-box' ), $field );
228
+ return "<a href='#' class='rwmb-button button-primary add-clone'>$text</a>";
229
  }
230
 
231
  /**
232
  * Remove clone button
233
  *
234
+ * @param array $field Field parameter
235
+ *
236
  * @return string $html
237
  */
238
+ static function remove_clone_button( $field )
239
  {
240
+ $text = apply_filters( 'rwmb_remove_clone_button_text', __( '&#8211;', 'meta-box' ), $field );
241
+ return "<a href='#' class='rwmb-button button remove-clone'>$text</a>";
242
  }
243
 
244
  /**
252
  */
253
  static function meta( $post_id, $saved, $field )
254
  {
255
+ /**
256
+ * For special fields like 'divider', 'heading' which don't have ID, just return empty string
257
+ * to prevent notice error when displaying fields
258
+ */
259
+ if ( empty( $field['id'] ) )
260
+ return '';
261
+
262
+ $single = $field['clone'] || ! $field['multiple'];
263
+ $meta = get_post_meta( $post_id, $field['id'], $single );
264
 
265
  // Use $field['std'] only when the meta box hasn't been saved (i.e. the first time we run)
266
  $meta = ( ! $saved && '' === $meta || array() === $meta ) ? $field['std'] : $meta;
267
 
268
+ // Escape attributes
269
+ $meta = call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'esc_meta' ), $meta );
270
+
271
+ // Make sure meta value is an array for clonable and multiple fields
272
+ if ( $field['clone'] || $field['multiple'] )
273
+ {
274
+ $meta = (array) $meta;
275
+ }
276
 
277
  return $meta;
278
  }
279
 
280
+ /**
281
+ * Escape meta for field output
282
+ *
283
+ * @param mixed $meta
284
+ *
285
+ * @return mixed
286
+ */
287
+ static function esc_meta( $meta )
288
+ {
289
+ if ( is_array( $meta ) )
290
+ {
291
+ array_walk_recursive( $meta, 'esc_attr' );
292
+ return $meta;
293
+ }
294
+ return esc_attr( $meta );
295
+ }
296
+
297
  /**
298
  * Set value of meta before saving into database
299
  *
321
  {
322
  $name = $field['id'];
323
 
324
+ // Remove post meta if it's empty
325
  if ( '' === $new || array() === $new )
326
  {
327
  delete_post_meta( $post_id, $name );
329
  return;
330
  }
331
 
332
+ // If field is cloneable, value is saved as a single entry in the database
333
+ if ( $field['clone'] )
334
+ {
335
+ $new = (array) $new;
336
+ foreach ( $new as $k => $v )
337
+ {
338
+ if ( '' === $v )
339
+ unset( $new[$k] );
340
+ }
341
+ update_post_meta( $post_id, $name, $new );
342
+ return;
343
+ }
344
+
345
+ // If field is multiple, value is saved as multiple entries in the database (WordPress behaviour)
346
  if ( $field['multiple'] )
347
  {
348
  foreach ( $new as $new_value )
355
  if ( ! in_array( $old_value, $new ) )
356
  delete_post_meta( $post_id, $name, $old_value );
357
  }
358
+ return;
359
  }
360
+
361
+ // Default: just update post meta
362
+ update_post_meta( $post_id, $name, $new );
 
 
 
 
 
 
 
 
 
 
363
  }
364
 
365
  /**
373
  {
374
  return $field;
375
  }
376
+
377
+ /**
378
+ * Get the field value
379
+ * The difference between this function and 'meta' function is 'meta' function always returns the escaped value
380
+ * of the field saved in the database, while this function returns more meaningful value of the field, for ex.:
381
+ * for file/image: return array of file/image information instead of file/image IDs
382
+ *
383
+ * Each field can extend this function and add more data to the returned value.
384
+ * See specific field classes for details.
385
+ *
386
+ * @param array $field Field parameters
387
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
388
+ * @param int|null $post_id Post ID. null for current post. Optional.
389
+ *
390
+ * @return mixed Field value
391
+ */
392
+ static function get_value( $field, $args = array(), $post_id = null )
393
+ {
394
+ if ( ! $post_id )
395
+ $post_id = get_the_ID();
396
+
397
+ /**
398
+ * Get raw meta value in the database, no escape
399
+ * Very similar to self::meta() function
400
+ */
401
+
402
+ /**
403
+ * For special fields like 'divider', 'heading' which don't have ID, just return empty string
404
+ * to prevent notice error when display in fields
405
+ */
406
+ $value = '';
407
+ if ( ! empty( $field['id'] ) )
408
+ {
409
+ $single = $field['clone'] || ! $field['multiple'];
410
+ $value = get_post_meta( $post_id, $field['id'], $single );
411
+
412
+ // Make sure meta value is an array for clonable and multiple fields
413
+ if ( $field['clone'] || $field['multiple'] )
414
+ {
415
+ $value = (array) $value;
416
+ }
417
+ }
418
+
419
+ /**
420
+ * Return the meta value by default.
421
+ * For specific fields, the returned value might be different. See each field class for details
422
+ */
423
+ return $value;
424
+ }
425
+
426
+ /**
427
+ * Output the field value
428
+ * Depends on field value and field types, each field can extend this method to output its value in its own way
429
+ * See specific field classes for details.
430
+ *
431
+ * Note: we don't echo the field value directly. We return the output HTML of field, which will be used in
432
+ * rwmb_the_field function later.
433
+ *
434
+ * @use self::get_value()
435
+ * @see rwmb_the_field()
436
+ *
437
+ * @param array $field Field parameters
438
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
439
+ * @param int|null $post_id Post ID. null for current post. Optional.
440
+ *
441
+ * @return string HTML output of the field
442
+ */
443
+ static function the_value( $field, $args = array(), $post_id = null )
444
+ {
445
+ $value = call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'get_value' ), $field, $args, $post_id );
446
+ $output = $value;
447
+ if ( is_array( $value ) )
448
+ {
449
+ $output = '<ul>';
450
+ foreach ( $value as $subvalue )
451
+ {
452
+ $output .= '<li>' . $subvalue . '</li>';
453
+ }
454
+ $output .= '</ul>';
455
+ }
456
+ return $output;
457
+ }
458
  }
459
  }
inc/fields/autocomplete.php CHANGED
@@ -4,7 +4,7 @@ defined( 'ABSPATH' ) || exit;
4
 
5
  if ( ! class_exists( 'RWMB_Autocomplete_Field' ) )
6
  {
7
- class RWMB_Autocomplete_Field extends RWMB_Field
8
  {
9
  /**
10
  * Enqueue scripts and styles
@@ -31,13 +31,21 @@ if ( ! class_exists( 'RWMB_Autocomplete_Field' ) )
31
  if ( ! is_array( $meta ) )
32
  $meta = array( $meta );
33
 
34
- $options = array();
35
- foreach ( $field['options'] as $value => $label )
36
  {
37
- $options[] = array(
38
- 'value' => $value,
39
- 'label' => $label,
40
- );
 
 
 
 
 
 
 
 
 
41
  }
42
 
43
  // Input field that triggers autocomplete.
@@ -47,7 +55,7 @@ if ( ! class_exists( 'RWMB_Autocomplete_Field' ) )
47
  '<input type="text" class="rwmb-autocomplete" id="%s" data-name="%s" data-options="%s" size="%s">',
48
  $field['id'],
49
  $field['field_name'],
50
- esc_attr( json_encode( $options ) ),
51
  $field['size']
52
  );
53
 
@@ -62,10 +70,30 @@ if ( ! class_exists( 'RWMB_Autocomplete_Field' ) )
62
  <input type="hidden" class="rwmb-autocomplete-value" name="%s" value="%s">
63
  </div>
64
  ';
65
- foreach ( $field['options'] as $value => $label )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  {
67
- if ( in_array( $value, $meta ) )
68
  {
 
 
 
69
  $html .= sprintf(
70
  $tpl,
71
  $label,
@@ -75,57 +103,12 @@ if ( ! class_exists( 'RWMB_Autocomplete_Field' ) )
75
  );
76
  }
77
  }
 
78
  $html .= '</div>'; // .rwmb-autocomplete-results
79
 
80
  return $html;
81
  }
82
 
83
- /**
84
- * Get meta value
85
- * If field is cloneable, value is saved as a single entry in DB
86
- * Otherwise value is saved as multiple entries (for backward compatibility)
87
- *
88
- * @see "save" method for better understanding
89
- *
90
- * @param $post_id
91
- * @param $saved
92
- * @param $field
93
- *
94
- * @return array
95
- */
96
- static function meta( $post_id, $saved, $field )
97
- {
98
- $meta = get_post_meta( $post_id, $field['id'], $field['clone'] );
99
- $meta = ( ! $saved && '' === $meta || array() === $meta ) ? $field['std'] : $meta;
100
-
101
- return $meta;
102
- }
103
-
104
- /**
105
- * Save meta value
106
- * If field is cloneable, value is saved as a single entry in DB
107
- * Otherwise value is saved as multiple entries (for backward compatibility)
108
- *
109
- * @param $new
110
- * @param $old
111
- * @param $post_id
112
- * @param $field
113
- */
114
- static function save( $new, $old, $post_id, $field )
115
- {
116
- if ( ! $field['clone'] )
117
- {
118
- parent::save( $new, $old, $post_id, $field );
119
-
120
- return;
121
- }
122
-
123
- if ( empty( $new ) )
124
- delete_post_meta( $post_id, $field['id'] );
125
- else
126
- update_post_meta( $post_id, $field['id'], $new );
127
- }
128
-
129
  /**
130
  * Normalize parameters for field
131
  *
@@ -135,15 +118,10 @@ if ( ! class_exists( 'RWMB_Autocomplete_Field' ) )
135
  */
136
  static function normalize_field( $field )
137
  {
 
138
  $field = wp_parse_args( $field, array(
139
  'size' => 30,
140
  ) );
141
-
142
- $field['multiple'] = true;
143
- $field['field_name'] = $field['id'];
144
- if ( ! $field['clone'] )
145
- $field['field_name'] .= '[]';
146
-
147
  return $field;
148
  }
149
  }
4
 
5
  if ( ! class_exists( 'RWMB_Autocomplete_Field' ) )
6
  {
7
+ class RWMB_Autocomplete_Field extends RWMB_Field_Multiple_Values
8
  {
9
  /**
10
  * Enqueue scripts and styles
31
  if ( ! is_array( $meta ) )
32
  $meta = array( $meta );
33
 
34
+ if ( is_string( $field['options'] ) )
 
35
  {
36
+ $options = $field['options'];
37
+ }
38
+ else
39
+ {
40
+ $options = array();
41
+ foreach ( $field['options'] as $value => $label )
42
+ {
43
+ $options[] = array(
44
+ 'value' => $value,
45
+ 'label' => $label,
46
+ );
47
+ }
48
+ $options = json_encode( $options );
49
  }
50
 
51
  // Input field that triggers autocomplete.
55
  '<input type="text" class="rwmb-autocomplete" id="%s" data-name="%s" data-options="%s" size="%s">',
56
  $field['id'],
57
  $field['field_name'],
58
+ esc_attr( $options ),
59
  $field['size']
60
  );
61
 
70
  <input type="hidden" class="rwmb-autocomplete-value" name="%s" value="%s">
71
  </div>
72
  ';
73
+
74
+ if ( is_array( $field['options'] ) )
75
+ {
76
+ foreach ( $field['options'] as $value => $label )
77
+ {
78
+ if ( in_array( $value, $meta ) )
79
+ {
80
+ $html .= sprintf(
81
+ $tpl,
82
+ $label,
83
+ __( 'Delete', 'meta-box' ),
84
+ $field['field_name'],
85
+ $value
86
+ );
87
+ }
88
+ }
89
+ }
90
+ else
91
  {
92
+ foreach ( $meta as $value )
93
  {
94
+ if ( empty( $value ) )
95
+ continue;
96
+ $label = apply_filters( 'rwmb_autocomplete_result_label', $value, $field );
97
  $html .= sprintf(
98
  $tpl,
99
  $label,
103
  );
104
  }
105
  }
106
+
107
  $html .= '</div>'; // .rwmb-autocomplete-results
108
 
109
  return $html;
110
  }
111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  /**
113
  * Normalize parameters for field
114
  *
118
  */
119
  static function normalize_field( $field )
120
  {
121
+ $field = parent::normalize_field( $field );
122
  $field = wp_parse_args( $field, array(
123
  'size' => 30,
124
  ) );
 
 
 
 
 
 
125
  return $field;
126
  }
127
  }
inc/fields/checkbox-list.php CHANGED
@@ -4,7 +4,7 @@ defined( 'ABSPATH' ) || exit;
4
 
5
  if ( ! class_exists( 'RWMB_Checkbox_List_Field' ) )
6
  {
7
- class RWMB_Checkbox_List_Field extends RWMB_Field
8
  {
9
  /**
10
  * Get field HTML
@@ -33,73 +33,5 @@ if ( ! class_exists( 'RWMB_Checkbox_List_Field' ) )
33
 
34
  return implode( '<br>', $html );
35
  }
36
-
37
- /**
38
- * Get meta value
39
- * If field is cloneable, value is saved as a single entry in DB
40
- * Otherwise value is saved as multiple entries (for backward compatibility)
41
- *
42
- * @see "save" method for better understanding
43
- *
44
- * TODO: A good way to ALWAYS save values in single entry in DB, while maintaining backward compatibility
45
- *
46
- * @param $post_id
47
- * @param $saved
48
- * @param $field
49
- *
50
- * @return array
51
- */
52
- static function meta( $post_id, $saved, $field )
53
- {
54
- $meta = get_post_meta( $post_id, $field['id'], $field['clone'] );
55
- $meta = ( ! $saved && '' === $meta || array() === $meta ) ? $field['std'] : $meta;
56
- $meta = array_map( 'esc_attr', (array) $meta );
57
-
58
- return $meta;
59
- }
60
-
61
- /**
62
- * Save meta value
63
- * If field is cloneable, value is saved as a single entry in DB
64
- * Otherwise value is saved as multiple entries (for backward compatibility)
65
- *
66
- * TODO: A good way to ALWAYS save values in single entry in DB, while maintaining backward compatibility
67
- *
68
- * @param $new
69
- * @param $old
70
- * @param $post_id
71
- * @param $field
72
- */
73
- static function save( $new, $old, $post_id, $field )
74
- {
75
- if ( ! $field['clone'] )
76
- {
77
- parent::save( $new, $old, $post_id, $field );
78
-
79
- return;
80
- }
81
-
82
- if ( empty( $new ) )
83
- delete_post_meta( $post_id, $field['id'] );
84
- else
85
- update_post_meta( $post_id, $field['id'], $new );
86
- }
87
-
88
- /**
89
- * Normalize parameters for field
90
- *
91
- * @param array $field
92
- *
93
- * @return array
94
- */
95
- static function normalize_field( $field )
96
- {
97
- $field['multiple'] = true;
98
- $field['field_name'] = $field['id'];
99
- if ( ! $field['clone'] )
100
- $field['field_name'] .= '[]';
101
-
102
- return $field;
103
- }
104
  }
105
  }
4
 
5
  if ( ! class_exists( 'RWMB_Checkbox_List_Field' ) )
6
  {
7
+ class RWMB_Checkbox_List_Field extends RWMB_Field_Multiple_Values
8
  {
9
  /**
10
  * Get field HTML
33
 
34
  return implode( '<br>', $html );
35
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  }
37
  }
inc/fields/checkbox.php CHANGED
@@ -6,6 +6,16 @@ if ( ! class_exists( 'RWMB_Checkbox_Field' ) )
6
  {
7
  class RWMB_Checkbox_Field extends RWMB_Field
8
  {
 
 
 
 
 
 
 
 
 
 
9
  /**
10
  * Get field HTML
11
  *
@@ -16,11 +26,13 @@ if ( ! class_exists( 'RWMB_Checkbox_Field' ) )
16
  */
17
  static function html( $meta, $field )
18
  {
 
19
  return sprintf(
20
- '<input type="checkbox" class="rwmb-checkbox" name="%s" id="%s" value="1" %s>',
21
  $field['field_name'],
22
  $field['id'],
23
- checked( ! empty( $meta ), 1, false )
 
24
  );
25
  }
26
 
@@ -41,5 +53,28 @@ if ( ! class_exists( 'RWMB_Checkbox_Field' ) )
41
  {
42
  return empty( $new ) ? 0 : 1;
43
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  }
45
  }
6
  {
7
  class RWMB_Checkbox_Field extends RWMB_Field
8
  {
9
+ /**
10
+ * Enqueue scripts and styles
11
+ *
12
+ * @return void
13
+ */
14
+ static function admin_enqueue_scripts()
15
+ {
16
+ wp_enqueue_style( 'rwmb-checkbox', RWMB_CSS_URL . 'checkbox.css', array(), RWMB_VER );
17
+ }
18
+
19
  /**
20
  * Get field HTML
21
  *
26
  */
27
  static function html( $meta, $field )
28
  {
29
+ $desc = $field['desc'] ? "<span id='{$field['id']}_description' class='description'>{$field['desc']}</span>" : '';
30
  return sprintf(
31
+ '<label><input type="checkbox" class="rwmb-checkbox" name="%s" id="%s" value="1" %s> %s</label>',
32
  $field['field_name'],
33
  $field['id'],
34
+ checked( ! empty( $meta ), 1, false ),
35
+ $desc
36
  );
37
  }
38
 
53
  {
54
  return empty( $new ) ? 0 : 1;
55
  }
56
+
57
+ /**
58
+ * Output the field value
59
+ * Display 'Yes' or 'No' instead of '1' and '0'
60
+ *
61
+ * Note: we don't echo the field value directly. We return the output HTML of field, which will be used in
62
+ * rwmb_the_field function later.
63
+ *
64
+ * @use self::get_value()
65
+ * @see rwmb_the_field()
66
+ *
67
+ * @param array $field Field parameters
68
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
69
+ * @param int|null $post_id Post ID. null for current post. Optional.
70
+ *
71
+ * @return string HTML output of the field
72
+ */
73
+ static function the_value( $field, $args = array(), $post_id = null )
74
+ {
75
+ $value = self::get_value( $field, $args, $post_id );
76
+
77
+ return $value ? __( 'Yes', 'meta-box' ) : __( 'No', 'meta-box' );
78
+ }
79
  }
80
  }
inc/fields/custom-html.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Prevent loading this file directly
3
+ defined( 'ABSPATH' ) || exit;
4
+
5
+ if ( ! class_exists( 'RWMB_Custom_Html_Field' ) )
6
+ {
7
+ class RWMB_Custom_Html_Field extends RWMB_Field
8
+ {
9
+ /**
10
+ * Get field HTML
11
+ *
12
+ * @param mixed $meta
13
+ * @param array $field
14
+ *
15
+ * @return string
16
+ */
17
+ static function html( $meta, $field )
18
+ {
19
+ $html = ! empty( $field['std'] ) ? $field['std'] : '';
20
+ if ( ! empty( $field['callback'] ) && is_callable( $field['callback'] ) )
21
+ {
22
+ $html = call_user_func_array( $field['callback'], array( $meta, $field ) );
23
+ }
24
+ return $html;
25
+ }
26
+ }
27
+ }
inc/fields/date.php CHANGED
@@ -36,7 +36,6 @@ if ( ! class_exists( 'RWMB_Date_Field' ) )
36
  }
37
 
38
  wp_enqueue_script( 'rwmb-date', RWMB_JS_URL . 'date.js', $deps, RWMB_VER, true );
39
- wp_localize_script( 'rwmb-date', 'RWMB_Datepicker', array( 'lang' => $locale ) );
40
  }
41
 
42
  /**
36
  }
37
 
38
  wp_enqueue_script( 'rwmb-date', RWMB_JS_URL . 'date.js', $deps, RWMB_VER, true );
 
39
  }
40
 
41
  /**
inc/fields/datetime.php CHANGED
@@ -6,6 +6,28 @@ if ( ! class_exists( 'RWMB_Datetime_Field' ) )
6
  {
7
  class RWMB_Datetime_Field extends RWMB_Field
8
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  /**
10
  * Enqueue scripts and styles
11
  *
@@ -18,22 +40,31 @@ if ( ! class_exists( 'RWMB_Datetime_Field' ) )
18
  wp_register_style( 'jquery-ui-theme', "{$url}/jquery.ui.theme.css", array(), '1.8.17' );
19
  wp_register_style( 'jquery-ui-datepicker', "{$url}/jquery.ui.datepicker.css", array( 'jquery-ui-core', 'jquery-ui-theme' ), '1.8.17' );
20
  wp_register_style( 'jquery-ui-slider', "{$url}/jquery.ui.slider.css", array( 'jquery-ui-core', 'jquery-ui-theme' ), '1.8.17' );
21
- wp_enqueue_style( 'jquery-ui-timepicker', "{$url}/jquery-ui-timepicker-addon.css", array( 'jquery-ui-datepicker', 'jquery-ui-slider' ), '0.9.7' );
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
- wp_register_script( 'jquery-ui-timepicker', RWMB_JS_URL . 'jqueryui/jquery-ui-timepicker-addon.js', array( 'jquery-ui-datepicker', 'jquery-ui-slider' ), '0.9.7', true );
24
 
25
- // Load localized scripts
26
- $locale = str_replace( '_', '-', get_locale() );
27
  $date_paths = array( 'jqueryui/datepicker-i18n/jquery.ui.datepicker-' . $locale . '.js' );
28
- $time_paths = array( 'jqueryui/timepicker-i18n/jquery-ui-timepicker-' . $locale . '.js' );
29
  if ( strlen( $locale ) > 2 )
30
  {
31
  // Also check alternate i18n filenames
32
  // (e.g. jquery.ui.datepicker-de.js instead of jquery.ui.datepicker-de-DE.js)
33
  $date_paths[] = 'jqueryui/datepicker-i18n/jquery.ui.datepicker-' . substr( $locale, 0, 2 ) . '.js';
34
- $time_paths[] = 'jqueryui/timepicker-i18n/jquery-ui-timepicker-' . substr( $locale, 0, 2 ) . '.js';
35
  }
36
- $deps = array( 'jquery-ui-datepicker', 'jquery-ui-timepicker' );
37
  foreach ( $date_paths as $date_path )
38
  {
39
  if ( file_exists( RWMB_DIR . 'js/' . $date_path ) )
@@ -43,18 +74,12 @@ if ( ! class_exists( 'RWMB_Datetime_Field' ) )
43
  break;
44
  }
45
  }
46
- foreach ( $time_paths as $time_path )
47
- {
48
- if ( file_exists( RWMB_DIR . 'js/' . $time_path ) )
49
- {
50
- wp_register_script( 'jquery-ui-timepicker-i18n', RWMB_JS_URL . $time_path, array( 'jquery-ui-timepicker' ), '1.8.17', true );
51
- $deps[] = 'jquery-ui-timepicker-i18n';
52
- break;
53
- }
54
- }
55
 
56
  wp_enqueue_script( 'rwmb-datetime', RWMB_JS_URL . 'datetime.js', $deps, RWMB_VER, true );
57
- wp_localize_script( 'rwmb-datetime', 'RWMB_Datetimepicker', array( 'lang' => $locale ) );
 
 
 
58
  }
59
 
60
  /**
@@ -117,7 +142,7 @@ if ( ! class_exists( 'RWMB_Datetime_Field' ) )
117
  // Use 'js_options' instead
118
  $field['js_options'] = wp_parse_args( $field['js_options'], array(
119
  'dateFormat' => empty( $field['format'] ) ? 'yy-mm-dd' : $field['format'],
120
- 'timeFormat' => 'hh:mm',
121
  'showButtonPanel' => true,
122
  'separator' => ' ',
123
  ) );
@@ -125,18 +150,6 @@ if ( ! class_exists( 'RWMB_Datetime_Field' ) )
125
  return $field;
126
  }
127
 
128
- // Missing: 't' => '', T' => '', 'm' => '', 's' => ''
129
- static $time_format_translation = array(
130
- 'H' => 'H', 'HH' => 'H', 'h' => 'H', 'hh' => 'H',
131
- 'mm' => 'i', 'ss' => 's', 'l' => 'u', 'tt' => 'a', 'TT' => 'A',
132
- );
133
-
134
- // Missing: 'o' => '', '!' => '', 'oo' => '', '@' => '', "''" => "'"
135
- static $date_format_translation = array(
136
- 'd' => 'j', 'dd' => 'd', 'oo' => 'z', 'D' => 'D', 'DD' => 'l',
137
- 'm' => 'n', 'mm' => 'm', 'M' => 'M', 'MM' => 'F', 'y' => 'y', 'yy' => 'Y',
138
- );
139
-
140
  /**
141
  * Returns a date() compatible format string from the JavaScript format
142
  *
6
  {
7
  class RWMB_Datetime_Field extends RWMB_Field
8
  {
9
+ /**
10
+ * Translate date format from jQuery UI datepicker to PHP date()
11
+ * It's used to store timestamp value of the field
12
+ * Missing: 'o' => '', '!' => '', 'oo' => '', '@' => '', "''" => "'"
13
+ * @var array
14
+ */
15
+ static $date_format_translation = array(
16
+ 'd' => 'j', 'dd' => 'd', 'oo' => 'z', 'D' => 'D', 'DD' => 'l',
17
+ 'm' => 'n', 'mm' => 'm', 'M' => 'M', 'MM' => 'F', 'y' => 'y', 'yy' => 'Y',
18
+ );
19
+
20
+ /**
21
+ * Translate date format from jQuery UI datepicker to PHP date()
22
+ * It's used to store timestamp value of the field
23
+ * Missing: 't' => '', T' => '', 'm' => '', 's' => ''
24
+ * @var array
25
+ */
26
+ static $time_format_translation = array(
27
+ 'H' => 'H', 'HH' => 'H', 'h' => 'H', 'hh' => 'H',
28
+ 'mm' => 'i', 'ss' => 's', 'l' => 'u', 'tt' => 'a', 'TT' => 'A',
29
+ );
30
+
31
  /**
32
  * Enqueue scripts and styles
33
  *
40
  wp_register_style( 'jquery-ui-theme', "{$url}/jquery.ui.theme.css", array(), '1.8.17' );
41
  wp_register_style( 'jquery-ui-datepicker', "{$url}/jquery.ui.datepicker.css", array( 'jquery-ui-core', 'jquery-ui-theme' ), '1.8.17' );
42
  wp_register_style( 'jquery-ui-slider', "{$url}/jquery.ui.slider.css", array( 'jquery-ui-core', 'jquery-ui-theme' ), '1.8.17' );
43
+ wp_enqueue_style( 'jquery-ui-timepicker', "{$url}/jquery-ui-timepicker-addon.min.css", array( 'jquery-ui-datepicker', 'jquery-ui-slider' ), '1.5.0' );
44
+
45
+ $url = RWMB_JS_URL . 'jqueryui';
46
+ wp_register_script( 'jquery-ui-timepicker', "{$url}/jquery-ui-timepicker-addon.min.js", array( 'jquery-ui-datepicker', 'jquery-ui-slider' ), '1.5.0', true );
47
+
48
+ /**
49
+ * Localization
50
+ * Use 1 minified JS file for timepicker which contains all languages for simpilicity (in version < 4.4.2 we use separated JS files).
51
+ * The language is set in Javascript
52
+ *
53
+ * Note: we use full locale (de-DE) and fallback to short locale (de)
54
+ */
55
+ $locale = str_replace( '_', '-', get_locale() );
56
+ $locale_short = substr( $locale, 0, 2 );
57
 
58
+ wp_register_script( 'jquery-ui-timepicker-i18n', "{$url}/jquery-ui-timepicker-addon-i18n.min.js", array( 'jquery-ui-timepicker' ), '1.5.0', true );
59
 
 
 
60
  $date_paths = array( 'jqueryui/datepicker-i18n/jquery.ui.datepicker-' . $locale . '.js' );
 
61
  if ( strlen( $locale ) > 2 )
62
  {
63
  // Also check alternate i18n filenames
64
  // (e.g. jquery.ui.datepicker-de.js instead of jquery.ui.datepicker-de-DE.js)
65
  $date_paths[] = 'jqueryui/datepicker-i18n/jquery.ui.datepicker-' . substr( $locale, 0, 2 ) . '.js';
 
66
  }
67
+ $deps = array( 'jquery-ui-timepicker-i18n' );
68
  foreach ( $date_paths as $date_path )
69
  {
70
  if ( file_exists( RWMB_DIR . 'js/' . $date_path ) )
74
  break;
75
  }
76
  }
 
 
 
 
 
 
 
 
 
77
 
78
  wp_enqueue_script( 'rwmb-datetime', RWMB_JS_URL . 'datetime.js', $deps, RWMB_VER, true );
79
+ wp_localize_script( 'rwmb-datetime', 'RWMB_Datetimepicker', array(
80
+ 'locale' => $locale,
81
+ 'localeShort' => $locale_short,
82
+ ) );
83
  }
84
 
85
  /**
142
  // Use 'js_options' instead
143
  $field['js_options'] = wp_parse_args( $field['js_options'], array(
144
  'dateFormat' => empty( $field['format'] ) ? 'yy-mm-dd' : $field['format'],
145
+ 'timeFormat' => 'HH:mm',
146
  'showButtonPanel' => true,
147
  'separator' => ' ',
148
  ) );
150
  return $field;
151
  }
152
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  /**
154
  * Returns a date() compatible format string from the JavaScript format
155
  *
inc/fields/fieldset-text.php CHANGED
@@ -16,63 +16,92 @@ if ( ! class_exists( 'RWMB_Fieldset_Text_Field' ) )
16
  */
17
  static function html( $meta, $field )
18
  {
19
- if ( 1 == count( $meta ) && '' == trim( $meta[0] ) )
20
- $meta = '';
21
 
22
- $html = array();
23
- $before = '<fieldset><legend>' . $field['desc'] . '</legend>';
24
- $after = '</fieldset>';
25
-
26
- $tpl = '<label>%s <input type="text" class="rwmb-fieldset-text" name="%s[%s][%d]" placeholder="%s" value="%s" /></label>';
27
-
28
- for ( $n = 0; $n < $field['rows']; $n ++ )
29
  {
30
- foreach ( $field['options'] as $k => $v )
31
  {
32
- $fid = $field['id'];
33
- if ( is_array( $meta ) && ! empty( $meta ) )
34
- $html[] = sprintf( $tpl, $k, $fid, $v, $n, $k, $meta[$v][$n] );
35
- else
36
- $html[] = sprintf( $tpl, $k, $fid, $v, $n, $k, '' );
37
  }
38
  $html[] = '<br>';
39
  }
40
 
41
- $out = $before . implode( ' ', $html ) . $after;
42
 
43
  return $out;
44
  }
45
 
46
  /**
47
- * Get meta value
 
48
  *
49
- * @param $post_id
50
- * @param $saved
51
- * @param $field
52
  *
53
- * @return array
54
  */
55
- static function meta( $post_id, $saved, $field )
56
  {
57
- $meta = get_post_meta( $post_id, $field['id'] );
58
 
59
- if ( is_array( $meta ) && ! empty( $meta ) )
60
- $meta = $meta[0];
61
 
62
- return $meta;
63
  }
64
 
65
  /**
66
- * Save meta value
67
  *
68
- * @param $new
69
- * @param $old
70
- * @param $post_id
71
- * @param $field
72
  */
73
- static function save( $new, $old, $post_id, $field )
74
  {
75
- update_post_meta( $post_id, $field['id'], $new, $old );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  }
77
  }
78
  }
16
  */
17
  static function html( $meta, $field )
18
  {
19
+ $html = array();
20
+ $tpl = '<label>%s <input type="text" class="rwmb-fieldset-text" name="%s[%d][%s]" value="%s"></label>';
21
 
22
+ for ( $row = 0; $row < $field['rows']; $row ++ )
 
 
 
 
 
 
23
  {
24
+ foreach ( $field['options'] as $key => $label )
25
  {
26
+ $value = isset( $meta[$row][$key] ) ? $meta[$row][$key] : '';
27
+ $html[] = sprintf( $tpl, $label, $field['id'], $row, $key, $value );
 
 
 
28
  }
29
  $html[] = '<br>';
30
  }
31
 
32
+ $out = '<fieldset><legend>' . $field['desc'] . '</legend>' . implode( ' ', $html ) . '</fieldset>';
33
 
34
  return $out;
35
  }
36
 
37
  /**
38
+ * Show end HTML markup for fields
39
+ * Do not show field description. Field description is shown before list of fields
40
  *
41
+ * @param mixed $meta
42
+ * @param array $field
 
43
  *
44
+ * @return string
45
  */
46
+ static function end_html( $meta, $field )
47
  {
48
+ $button = $field['clone'] ? call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'add_clone_button' ), $field ) : '';
49
 
50
+ // Closes the container
51
+ $html = "$button</div>";
52
 
53
+ return $html;
54
  }
55
 
56
  /**
57
+ * Normalize parameters for field
58
  *
59
+ * @param array $field
60
+ *
61
+ * @return array
 
62
  */
63
+ static function normalize_field( $field )
64
  {
65
+ $field['multiple'] = false;
66
+ return $field;
67
+ }
68
+
69
+ /**
70
+ * Output the field value
71
+ * Display options in format Label: value in unordered list
72
+ *
73
+ * @param array $field Field parameters
74
+ * @param array $args Additional arguments. Not used for these fields.
75
+ * @param int|null $post_id Post ID. null for current post. Optional.
76
+ *
77
+ * @return mixed Field value
78
+ */
79
+ static function the_value( $field, $args = array(), $post_id = null )
80
+ {
81
+ $value = self::get_value( $field, $args, $post_id );
82
+ if ( ! $value )
83
+ return '';
84
+
85
+ $output = '<table>';
86
+ $output .= '<thead><tr>';
87
+ foreach ( $field['options'] as $label )
88
+ {
89
+ $output .= "<th>$label</th>";
90
+ }
91
+ $output .= '</tr></thead><tbody>';
92
+
93
+ foreach ( $value as $subvalue )
94
+ {
95
+ $output .= '<tr>';
96
+ foreach ( $subvalue as $value )
97
+ {
98
+ $output .= "<td>$value</td>";
99
+ }
100
+ $output .= '</tr>';
101
+ }
102
+ $output .= '</tbody></table>';
103
+
104
+ return $output;
105
  }
106
  }
107
  }
inc/fields/file.php CHANGED
@@ -304,5 +304,95 @@ if ( ! class_exists( 'RWMB_File_Field' ) )
304
 
305
  return empty( $meta ) ? array() : (array) $meta;
306
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
307
  }
308
  }
304
 
305
  return empty( $meta ) ? array() : (array) $meta;
306
  }
307
+
308
+ /**
309
+ * Get the field value
310
+ * The difference between this function and 'meta' function is 'meta' function always returns the escaped value
311
+ * of the field saved in the database, while this function returns more meaningful value of the field
312
+ *
313
+ * @param array $field Field parameters
314
+ * @param array $args Not used for this field
315
+ * @param int|null $post_id Post ID. null for current post. Optional.
316
+ *
317
+ * @return mixed Full info of uploaded files
318
+ */
319
+ static function get_value( $field, $args = array(), $post_id = null )
320
+ {
321
+ if ( ! $post_id )
322
+ $post_id = get_the_ID();
323
+
324
+ /**
325
+ * Get raw meta value in the database, no escape
326
+ * Very similar to self::meta() function
327
+ */
328
+ $file_ids = get_post_meta( $post_id, $field['id'], false );
329
+
330
+ // For each file, get full file info
331
+ $value = array();
332
+ foreach ( $file_ids as $file_id )
333
+ {
334
+ if ( $file_info = call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'file_info' ), $file_id, $args ) )
335
+ {
336
+ $value[$file_id] = $file_info;
337
+ }
338
+ }
339
+
340
+ return $value;
341
+ }
342
+
343
+ /**
344
+ * Output the field value
345
+ * Display unordered list of files
346
+ *
347
+ * @param array $field Field parameters
348
+ * @param array $args Additional arguments. Not used for these fields.
349
+ * @param int|null $post_id Post ID. null for current post. Optional.
350
+ *
351
+ * @return mixed Field value
352
+ */
353
+ static function the_value( $field, $args = array(), $post_id = null )
354
+ {
355
+ $value = self::get_value( $field, $args, $post_id );
356
+ if ( ! $value )
357
+ return '';
358
+
359
+ $output = '<ul>';
360
+ foreach ( $value as $file_id => $file_info )
361
+ {
362
+ $output .= sprintf(
363
+ '<li><a href="%s" target="_blank">%s</a></li>',
364
+ wp_get_attachment_url( $file_id ),
365
+ get_the_title( $file_id )
366
+ );
367
+ }
368
+ $output .= '</ul>';
369
+
370
+ return $output;
371
+ }
372
+
373
+ /**
374
+ * Get uploaded file information
375
+ *
376
+ * @param int $file_id Attachment file ID (post ID). Required.
377
+ * @param array $args Array of arguments (for size).
378
+ *
379
+ * @return array|bool False if file not found. Array of (id, name, path, url) on success
380
+ */
381
+ static function file_info( $file_id, $args = array() )
382
+ {
383
+ $path = get_attached_file( $file_id );
384
+ if ( ! $path )
385
+ {
386
+ return false;
387
+ }
388
+
389
+ return array(
390
+ 'ID' => $file_id,
391
+ 'name' => basename( $path ),
392
+ 'path' => $path,
393
+ 'url' => wp_get_attachment_url( $file_id ),
394
+ 'title' => get_the_title( $file_id ),
395
+ );
396
+ }
397
  }
398
  }
inc/fields/heading.php CHANGED
@@ -39,7 +39,7 @@ if ( ! class_exists( 'RWMB_Heading_Field' ) )
39
  */
40
  static function end_html( $meta, $field )
41
  {
42
- $id = $field['id'] ? " id='{$field['id']}-description" : '';
43
 
44
  return $field['desc'] ? "<p{$id} class='description'>{$field['desc']}</p>" : '';
45
  }
39
  */
40
  static function end_html( $meta, $field )
41
  {
42
+ $id = $field['id'] ? " id='{$field['id']}-description'" : '';
43
 
44
  return $field['desc'] ? "<p{$id} class='description'>{$field['desc']}</p>" : '';
45
  }
inc/fields/image-select.php CHANGED
@@ -59,5 +59,67 @@ if ( ! class_exists( 'RWMB_Image_Select_Field' ) )
59
 
60
  return $field;
61
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  }
63
  }
59
 
60
  return $field;
61
  }
62
+
63
+ /**
64
+ * Output the field value
65
+ * Display unordered list of images with option for size and link to full size
66
+ *
67
+ * @param array $field Field parameters
68
+ * @param array $args Additional arguments. Not used for these fields.
69
+ * @param int|null $post_id Post ID. null for current post. Optional.
70
+ *
71
+ * @return mixed Field value
72
+ */
73
+ static function the_value( $field, $args = array(), $post_id = null )
74
+ {
75
+ $value = self::get_value( $field, $args, $post_id );
76
+ if ( ! $value )
77
+ return '';
78
+
79
+ $function = array( RW_Meta_Box::get_class_name( $field ), 'get_option_label' );
80
+
81
+ if ( $field['clone'] )
82
+ {
83
+ $output = '<ul>';
84
+ if ( $field['multiple'] )
85
+ {
86
+ foreach ( $value as $subvalue )
87
+ {
88
+ $output .= '<li><ul>';
89
+ foreach ( $subvalue as &$option )
90
+ {
91
+ $output .= sprintf( '<li><img src="%s"></li>', esc_url( $field['options'][$value] ) );
92
+ }
93
+ $output .= '</ul></li>';
94
+ }
95
+ }
96
+ else
97
+ {
98
+ foreach ( $value as &$subvalue )
99
+ {
100
+ $output .= sprintf( '<li><img src="%s"></li>', esc_url( $field['options'][$subvalue] ) );
101
+ }
102
+ }
103
+ $output .= '</ul>';
104
+ }
105
+ else
106
+ {
107
+ if ( $field['multiple'] )
108
+ {
109
+ $output = '<ul>';
110
+ foreach ( $value as &$subvalue )
111
+ {
112
+ $output .= sprintf( '<li><img src="%s"></li>', esc_url( $field['options'][$subvalue] ) );
113
+ }
114
+ $output .= '</ul>';
115
+ }
116
+ else
117
+ {
118
+ $output = sprintf( '<img src="%s">', esc_url( $field['options'][$value] ) );
119
+ }
120
+ }
121
+
122
+ return $output;
123
+ }
124
  }
125
  }
inc/fields/image.php CHANGED
@@ -158,5 +158,85 @@ if ( ! class_exists( 'RWMB_Image_Field' ) )
158
  );
159
  }
160
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  }
162
  }
158
  );
159
  }
160
 
161
+ /**
162
+ * Output the field value
163
+ * Display unordered list of images with option for size and link to full size
164
+ *
165
+ * @param array $field Field parameters
166
+ * @param array $args Additional arguments. Not used for these fields.
167
+ * @param int|null $post_id Post ID. null for current post. Optional.
168
+ *
169
+ * @return mixed Field value
170
+ */
171
+ static function the_value( $field, $args = array(), $post_id = null )
172
+ {
173
+ $value = self::get_value( $field, $args, $post_id );
174
+ if ( ! $value )
175
+ return '';
176
+
177
+ $output = '<ul>';
178
+ foreach ( $value as $file_id => $file_info )
179
+ {
180
+ $img = sprintf(
181
+ '<img src="%s" alt="%s" title="%s">',
182
+ esc_url( $file_info['url'] ),
183
+ esc_attr( $file_info['alt'] ),
184
+ esc_attr( $file_info['title'] )
185
+ );
186
+
187
+ // Link thumbnail to full size image?
188
+ if ( isset( $args['link'] ) && $args['link'] )
189
+ {
190
+ $img = sprintf(
191
+ '<a href="%s" title="%s">%s</a>',
192
+ esc_url( $file_info['full_url'] ),
193
+ esc_attr( $file_info['title'] ),
194
+ $img
195
+ );
196
+ }
197
+
198
+ $output .= "<li>$img</li>";
199
+ }
200
+ $output .= '</ul>';
201
+
202
+ return $output;
203
+ }
204
+
205
+ /**
206
+ * Get uploaded file information
207
+ *
208
+ * @param int $file_id Attachment image ID (post ID). Required.
209
+ * @param array $args Array of arguments (for size).
210
+ *
211
+ * @return array|bool False if file not found. Array of image info on success
212
+ */
213
+ static function file_info( $file_id, $args = array() )
214
+ {
215
+ $args = wp_parse_args( $args, array(
216
+ 'size' => 'thumbnail',
217
+ ) );
218
+
219
+ $img_src = wp_get_attachment_image_src( $file_id, $args['size'] );
220
+ if ( ! $img_src )
221
+ {
222
+ return false;
223
+ }
224
+
225
+ $attachment = get_post( $file_id );
226
+ $path = get_attached_file( $file_id );
227
+ return array(
228
+ 'ID' => $file_id,
229
+ 'name' => basename( $path ),
230
+ 'path' => $path,
231
+ 'url' => $img_src[0],
232
+ 'width' => $img_src[1],
233
+ 'height' => $img_src[2],
234
+ 'full_url' => wp_get_attachment_url( $file_id ),
235
+ 'title' => $attachment->post_title,
236
+ 'caption' => $attachment->post_excerpt,
237
+ 'description' => $attachment->post_content,
238
+ 'alt' => get_post_meta( $file_id, '_wp_attachment_image_alt', true ),
239
+ );
240
+ }
241
  }
242
  }
inc/fields/key-value.php ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Prevent loading this file directly
3
+ defined( 'ABSPATH' ) || exit;
4
+
5
+ if ( ! class_exists( 'RWMB_Key_Value_Field' ) )
6
+ {
7
+ class RWMB_Key_Value_Field extends RWMB_Field
8
+ {
9
+ /**
10
+ * Get field HTML
11
+ *
12
+ * @param mixed $meta
13
+ * @param array $field
14
+ *
15
+ * @return string
16
+ */
17
+ static function html( $meta, $field )
18
+ {
19
+ $tpl = '<input type="text" class="rwmb-key-val" name="%s[]" value="%s" placeholder="' . esc_attr__( 'Key', 'meta-box' ) . '">';
20
+ $tpl .= '<input type="text" class="rwmb-key-val" name="%s[]" value="%s" placeholder="' . esc_attr__( 'Value', 'meta-box' ) . '">';
21
+
22
+ $key = isset( $meta[0] ) ? $meta[0] : '';
23
+ $val = isset( $meta[1] ) ? $meta[1] : '';
24
+
25
+ $html = sprintf( $tpl, $field['field_name'], $key, $field['field_name'], $val );
26
+
27
+ return $html;
28
+ }
29
+
30
+ /**
31
+ * Show begin HTML markup for fields
32
+ *
33
+ * @param mixed $meta
34
+ * @param array $field
35
+ *
36
+ * @return string
37
+ */
38
+ static function begin_html( $meta, $field )
39
+ {
40
+ $desc = $field['desc'] ? "<p id='{$field['id']}_description' class='description'>{$field['desc']}</p>" : '';
41
+
42
+ if ( empty( $field['name'] ) )
43
+ return '<div class="rwmb-input">' . $desc;
44
+
45
+ return sprintf(
46
+ '<div class="rwmb-label">
47
+ <label for="%s">%s</label>
48
+ </div>
49
+ <div class="rwmb-input">
50
+ %s',
51
+ $field['id'],
52
+ $field['name'],
53
+ $desc
54
+ );
55
+ }
56
+
57
+ /**
58
+ * Show end HTML markup for fields
59
+ * Do not show field description. Field description is shown before list of fields
60
+ *
61
+ * @param mixed $meta
62
+ * @param array $field
63
+ *
64
+ * @return string
65
+ */
66
+ static function end_html( $meta, $field )
67
+ {
68
+ $button = $field['clone'] ? call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'add_clone_button' ), $field ) : '';
69
+
70
+ // Closes the container
71
+ $html = "$button</div>";
72
+
73
+ return $html;
74
+ }
75
+
76
+ /**
77
+ * Escape meta for field output
78
+ *
79
+ * @param mixed $meta
80
+ *
81
+ * @return mixed
82
+ */
83
+ static function esc_meta( $meta )
84
+ {
85
+ foreach ( (array) $meta as $k => $pairs )
86
+ {
87
+ $meta[$k] = array_map( 'esc_attr', (array) $pairs );
88
+ }
89
+ return $meta;
90
+ }
91
+
92
+ /**
93
+ * Sanitize email
94
+ *
95
+ * @param mixed $new
96
+ * @param mixed $old
97
+ * @param int $post_id
98
+ * @param array $field
99
+ *
100
+ * @return string
101
+ */
102
+ static function value( $new, $old, $post_id, $field )
103
+ {
104
+ foreach ( $new as &$arr )
105
+ {
106
+ if ( empty( $arr[0] ) && empty( $arr[1] ) )
107
+ $arr = false;
108
+ }
109
+
110
+ $new = array_filter( $new );
111
+
112
+ return $new;
113
+ }
114
+
115
+ /**
116
+ * Normalize parameters for field
117
+ *
118
+ * @param array $field
119
+ *
120
+ * @return array
121
+ */
122
+ static function normalize_field( $field )
123
+ {
124
+ $field['clone'] = true;
125
+ $field['multiple'] = false;
126
+
127
+ return $field;
128
+ }
129
+
130
+ /**
131
+ * Output the field value
132
+ * Display unordered list of key - value pairs
133
+ *
134
+ * @use self::get_value()
135
+ * @see rwmb_the_field()
136
+ *
137
+ * @param array $field Field parameters
138
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
139
+ * @param int|null $post_id Post ID. null for current post. Optional.
140
+ *
141
+ * @return string HTML output of the field
142
+ */
143
+ static function the_value( $field, $args = array(), $post_id = null )
144
+ {
145
+ $value = self::get_value( $field, $args, $post_id );
146
+ if ( ! is_array( $value ) )
147
+ return '';
148
+
149
+ $output = '<ul>';
150
+ foreach ( $value as $subvalue )
151
+ {
152
+ $output .= sprintf( '<li><label>%s</label>: %s</li>', $subvalue[0], $subvalue[1] );
153
+ }
154
+ $output .= '</ul>';
155
+ return $output;
156
+ }
157
+ }
158
+ }
inc/fields/map.php CHANGED
@@ -13,8 +13,9 @@ if ( ! class_exists( 'RWMB_Map_Field' ) )
13
  */
14
  static function admin_enqueue_scripts()
15
  {
16
- wp_enqueue_script( 'googlemap', 'https://maps.google.com/maps/api/js?sensor=false', array(), '', true );
17
- wp_enqueue_script( 'rwmb-map', RWMB_JS_URL . 'map.js', array( 'jquery', 'jquery-ui-autocomplete', 'googlemap' ), RWMB_VER, true );
 
18
  }
19
 
20
  /**
@@ -27,20 +28,17 @@ if ( ! class_exists( 'RWMB_Map_Field' ) )
27
  */
28
  static function html( $meta, $field )
29
  {
30
- $address = isset( $field['address_field'] ) ? $field['address_field'] : false;
31
-
32
  $html = '<div class="rwmb-map-field">';
33
 
34
  $html .= sprintf(
35
- '<div class="rwmb-map-canvas" style="%s"%s></div>
36
  <input type="hidden" name="%s" class="rwmb-map-coordinate" value="%s">',
37
- isset( $field['style'] ) ? $field['style'] : '',
38
- isset( $field['std'] ) ? " data-default-loc=\"{$field['std']}\"" : '',
39
- $field['field_name'],
40
- $meta
41
  );
42
 
43
- if ( $address )
44
  {
45
  $html .= sprintf(
46
  '<button class="button rwmb-map-goto-address-button" value="%s">%s</button>',
@@ -53,5 +51,104 @@ if ( ! class_exists( 'RWMB_Map_Field' ) )
53
 
54
  return $html;
55
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  }
57
  }
13
  */
14
  static function admin_enqueue_scripts()
15
  {
16
+ wp_register_script( 'google-maps', 'https://maps.google.com/maps/api/js?sensor=false', array(), '', true );
17
+ wp_enqueue_style( 'rwmb-map', RWMB_CSS_URL . 'map.css' );
18
+ wp_enqueue_script( 'rwmb-map', RWMB_JS_URL . 'map.js', array( 'jquery-ui-autocomplete', 'google-maps' ), RWMB_VER, true );
19
  }
20
 
21
  /**
28
  */
29
  static function html( $meta, $field )
30
  {
 
 
31
  $html = '<div class="rwmb-map-field">';
32
 
33
  $html .= sprintf(
34
+ '<div class="rwmb-map-canvas" data-default-loc="%s"></div>
35
  <input type="hidden" name="%s" class="rwmb-map-coordinate" value="%s">',
36
+ esc_attr( $field['std'] ),
37
+ esc_attr( $field['field_name'] ),
38
+ esc_attr( $meta )
 
39
  );
40
 
41
+ if ( $address = $field['address_field'] )
42
  {
43
  $html .= sprintf(
44
  '<button class="button rwmb-map-goto-address-button" value="%s">%s</button>',
51
 
52
  return $html;
53
  }
54
+
55
+ /**
56
+ * Normalize parameters for field
57
+ *
58
+ * @param array $field
59
+ *
60
+ * @return array
61
+ */
62
+ static function normalize_field( $field )
63
+ {
64
+ $field = wp_parse_args( $field, array(
65
+ 'std' => '',
66
+ 'address_field' => '',
67
+ ) );
68
+
69
+ return $field;
70
+ }
71
+
72
+ /**
73
+ * Get the field value
74
+ * The difference between this function and 'meta' function is 'meta' function always returns the escaped value
75
+ * of the field saved in the database, while this function returns more meaningful value of the field
76
+ *
77
+ * @param array $field Field parameters
78
+ * @param array $args Not used for this field
79
+ * @param int|null $post_id Post ID. null for current post. Optional.
80
+ *
81
+ * @return mixed Array(latitude, longitude, zoom)
82
+ */
83
+ static function get_value( $field, $args = array(), $post_id = null )
84
+ {
85
+ $value = parent::get_value( $field, $args, $post_id );
86
+ list( $latitude, $longitude, $zoom ) = explode( ',', $value . ',,' );
87
+ return compact( 'latitude', 'longitude', 'zoom' );
88
+ }
89
+
90
+ /**
91
+ * Output the field value
92
+ * Display Google maps
93
+ *
94
+ * @param array $field Field parameters
95
+ * @param array $args Additional arguments. Not used for these fields.
96
+ * @param int|null $post_id Post ID. null for current post. Optional.
97
+ *
98
+ * @return mixed Field value
99
+ */
100
+ static function the_value( $field, $args = array(), $post_id = null )
101
+ {
102
+ $value = self::get_value( $field, $args, $post_id );
103
+ if ( ! $value['latitude'] || ! $value['longitude'] )
104
+ {
105
+ return '';
106
+ }
107
+ if ( ! $value['zoom'] )
108
+ {
109
+ $value['zoom'] = 14;
110
+ }
111
+
112
+ /**
113
+ * Enqueue scripts
114
+ * Note: We still can enqueue script which outputs in the footer
115
+ */
116
+ wp_register_script( 'google-maps', 'https://maps.google.com/maps/api/js?sensor=false', array(), '', true );
117
+ wp_enqueue_script( 'rwmb-map-frontend', RWMB_JS_URL . 'map-frontend.js', array( 'google-maps' ), '', true );
118
+
119
+ // Map parameters
120
+ $args = wp_parse_args( $args, array(
121
+ 'latitude' => $value['latitude'],
122
+ 'longitude' => $value['longitude'],
123
+ 'width' => '100%',
124
+ 'height' => '480px',
125
+ 'marker' => true, // Display marker?
126
+ 'marker_title' => '', // Marker title, when hover
127
+ 'info_window' => '', // Content of info window (when click on marker). HTML allowed
128
+ 'js_options' => array(),
129
+ ) );
130
+
131
+ /**
132
+ * Google Maps options
133
+ * Option name is the same as specified in Google Maps documentation
134
+ * This array will be convert to Javascript Object and pass as map options
135
+ * @link https://developers.google.com/maps/documentation/javascript/reference
136
+ */
137
+ $args['js_options'] = wp_parse_args( $args['js_options'], array(
138
+ // Default to 'zoom' level set in admin, but can be overwritten
139
+ 'zoom' => $value['zoom'],
140
+
141
+ // Map type, see https://developers.google.com/maps/documentation/javascript/reference#MapTypeId
142
+ 'mapTypeId' => 'ROADMAP',
143
+ ) );
144
+
145
+ $output = sprintf(
146
+ '<div class="rwmb-map-canvas" data-map_options="%s" style="width:%s;height:%s"></div>',
147
+ esc_attr( json_encode( $args ) ),
148
+ esc_attr( $args['width'] ),
149
+ esc_attr( $args['height'] )
150
+ );
151
+ return $output;
152
+ }
153
  }
154
  }
inc/fields/oembed.php CHANGED
@@ -78,5 +78,34 @@ if ( ! class_exists( 'RWMB_OEmbed_Field' ) )
78
  $meta ? self::get_embed( $meta ) : ''
79
  );
80
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  }
82
  }
78
  $meta ? self::get_embed( $meta ) : ''
79
  );
80
  }
81
+
82
+ /**
83
+ * Output the field value
84
+ * Display embed media
85
+ *
86
+ * @param array $field Field parameters
87
+ * @param array $args Additional arguments. Not used for these fields.
88
+ * @param int|null $post_id Post ID. null for current post. Optional.
89
+ *
90
+ * @return mixed Field value
91
+ */
92
+ static function the_value( $field, $args = array(), $post_id = null )
93
+ {
94
+ $value = self::get_value( $field, $args, $post_id );
95
+ if ( $field['clone'] )
96
+ {
97
+ $output = '<ul>';
98
+ foreach ( $value as $subvalue )
99
+ {
100
+ $output .= '<li>' . self::get_embed( $subvalue ) . '</li>';
101
+ }
102
+ $output .= '</ul>';
103
+ }
104
+ else
105
+ {
106
+ $output = self::get_embed( $value );
107
+ }
108
+ return $output;
109
+ }
110
  }
111
  }
inc/fields/post.php CHANGED
@@ -2,23 +2,13 @@
2
  // Prevent loading this file directly
3
  defined( 'ABSPATH' ) || exit;
4
 
5
- // Make sure "select" field is loaded
6
  require_once RWMB_FIELDS_DIR . 'select-advanced.php';
7
 
8
  if ( ! class_exists( 'RWMB_Post_Field' ) )
9
  {
10
- class RWMB_Post_Field extends RWMB_Field
11
  {
12
- /**
13
- * Enqueue scripts and styles
14
- *
15
- * @return void
16
- */
17
- static function admin_enqueue_scripts()
18
- {
19
- RWMB_Select_Advanced_Field::admin_enqueue_scripts();
20
- }
21
-
22
  /**
23
  * Get field HTML
24
  *
@@ -49,13 +39,6 @@ if ( ! class_exists( 'RWMB_Post_Field' ) )
49
  */
50
  static function normalize_field( $field )
51
  {
52
- $default_post_type = __( 'Post', 'meta-box' );
53
- if ( is_string( $field['post_type'] ) )
54
- {
55
- $post_type_object = get_post_type_object( $field['post_type'] );
56
- $default_post_type = $post_type_object->labels->singular_name;
57
- }
58
-
59
  $field = wp_parse_args( $field, array(
60
  'post_type' => 'post',
61
  'field_type' => 'select_advanced',
@@ -63,7 +46,10 @@ if ( ! class_exists( 'RWMB_Post_Field' ) )
63
  'query_args' => array(),
64
  ) );
65
 
66
- $field['std'] = empty( $field['std'] ) ? sprintf( __( 'Select a %s', 'meta-box' ), $default_post_type ) : $field['std'];
 
 
 
67
 
68
  if ( $field['parent'] )
69
  {
@@ -110,24 +96,7 @@ if ( ! class_exists( 'RWMB_Post_Field' ) )
110
  return $post->post_parent;
111
  }
112
 
113
- return RWMB_Select_Field::meta( $post_id, $saved, $field );
114
- }
115
-
116
- /**
117
- * Save meta value
118
- * If field is cloneable, value is saved as a single entry in DB
119
- * Otherwise value is saved as multiple entries (for backward compatibility)
120
- *
121
- * TODO: A good way to ALWAYS save values in single entry in DB, while maintaining backward compatibility
122
- *
123
- * @param $new
124
- * @param $old
125
- * @param $post_id
126
- * @param $field
127
- */
128
- static function save( $new, $old, $post_id, $field )
129
- {
130
- return RWMB_Select_Field::save( $new, $old, $post_id, $field );
131
  }
132
 
133
  /**
@@ -152,5 +121,27 @@ if ( ! class_exists( 'RWMB_Post_Field' ) )
152
 
153
  return $options;
154
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  }
156
  }
2
  // Prevent loading this file directly
3
  defined( 'ABSPATH' ) || exit;
4
 
5
+ // Make sure "select-advanced" field is loaded
6
  require_once RWMB_FIELDS_DIR . 'select-advanced.php';
7
 
8
  if ( ! class_exists( 'RWMB_Post_Field' ) )
9
  {
10
+ class RWMB_Post_Field extends RWMB_Select_Advanced_Field
11
  {
 
 
 
 
 
 
 
 
 
 
12
  /**
13
  * Get field HTML
14
  *
39
  */
40
  static function normalize_field( $field )
41
  {
 
 
 
 
 
 
 
42
  $field = wp_parse_args( $field, array(
43
  'post_type' => 'post',
44
  'field_type' => 'select_advanced',
46
  'query_args' => array(),
47
  ) );
48
 
49
+ $post_type_object = get_post_type_object( $field['post_type'] );
50
+ $post_type_label = $post_type_object->labels->singular_name;
51
+
52
+ $field['std'] = empty( $field['std'] ) ? sprintf( __( 'Select a %s', 'meta-box' ), $post_type_label ) : $field['std'];
53
 
54
  if ( $field['parent'] )
55
  {
96
  return $post->post_parent;
97
  }
98
 
99
+ return parent::meta( $post_id, $saved, $field );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  }
101
 
102
  /**
121
 
122
  return $options;
123
  }
124
+
125
+ /**
126
+ * Get post link to display in the frontend
127
+ *
128
+ * @param int $value Option value, e.g. post ID
129
+ * @param int $index Array index
130
+ * @param array $field Field parameter
131
+ *
132
+ * @return string
133
+ */
134
+ static function get_option_label( &$value, $index, $field )
135
+ {
136
+ $value = sprintf(
137
+ '<a href="%s" title="%s">%s</a>',
138
+ esc_url( get_permalink( $value ) ),
139
+ the_title_attribute( array(
140
+ 'post' => $value,
141
+ 'echo' => false,
142
+ ) ),
143
+ get_the_title( $value )
144
+ );
145
+ }
146
  }
147
  }
inc/fields/radio.php CHANGED
@@ -32,5 +32,24 @@ if ( ! class_exists( 'RWMB_Radio_Field' ) )
32
 
33
  return implode( ' ', $html );
34
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  }
36
  }
32
 
33
  return implode( ' ', $html );
34
  }
35
+
36
+ /**
37
+ * Output the field value
38
+ * Display option name instead of option value
39
+ *
40
+ * @use self::meta()
41
+ *
42
+ * @param array $field Field parameters
43
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
44
+ * @param int|null $post_id Post ID. null for current post. Optional.
45
+ *
46
+ * @return mixed Field value
47
+ */
48
+ static function the_value( $field, $args = array(), $post_id = null )
49
+ {
50
+ $value = parent::get_value( $field, $args, $post_id );
51
+
52
+ return empty( $value ) ? '' : $field['options'][$value];
53
+ }
54
  }
55
  }
inc/fields/select-advanced.php CHANGED
@@ -38,7 +38,7 @@ if ( ! class_exists( 'RWMB_Select_Advanced_Field' ) )
38
  $field['field_name'],
39
  $field['id'],
40
  $field['size'],
41
- $field['multiple'] ? ' multiple="multiple"' : '',
42
  esc_attr( json_encode( $field['js_options'] ) )
43
  );
44
 
38
  $field['field_name'],
39
  $field['id'],
40
  $field['size'],
41
+ $field['multiple'] ? ' multiple' : '',
42
  esc_attr( json_encode( $field['js_options'] ) )
43
  );
44
 
inc/fields/select.php CHANGED
@@ -31,7 +31,7 @@ if ( ! class_exists( 'RWMB_Select_Field' ) )
31
  $field['field_name'],
32
  $field['id'],
33
  $field['size'],
34
- $field['multiple'] ? ' multiple="multiple"' : ''
35
  );
36
 
37
  $html .= self::options_html( $field, $meta );
@@ -41,43 +41,17 @@ if ( ! class_exists( 'RWMB_Select_Field' ) )
41
  return $html;
42
  }
43
 
44
- /**
45
- * Get meta value
46
- * If field is cloneable, value is saved as a single entry in DB
47
- * Otherwise value is saved as multiple entries (for backward compatibility)
48
- *
49
- * @see "save" method for better understanding
50
- *
51
- * TODO: A good way to ALWAYS save values in single entry in DB, while maintaining backward compatibility
52
- *
53
- * @param $post_id
54
- * @param $saved
55
- * @param $field
56
- *
57
- * @return array
58
- */
59
- static function meta( $post_id, $saved, $field )
60
- {
61
- $single = $field['clone'] || ! $field['multiple'];
62
- $meta = get_post_meta( $post_id, $field['id'], $single );
63
- $meta = ( ! $saved && '' === $meta || array() === $meta ) ? $field['std'] : $meta;
64
-
65
- $meta = array_map( 'esc_attr', (array) $meta );
66
-
67
- return $meta;
68
- }
69
-
70
  /**
71
  * Save meta value
72
  * If field is cloneable, value is saved as a single entry in DB
73
  * Otherwise value is saved as multiple entries (for backward compatibility)
74
  *
75
- * TODO: A good way to ALWAYS save values in single entry in DB, while maintaining backward compatibility
76
- *
77
  * @param $new
78
  * @param $old
79
  * @param $post_id
80
  * @param $field
 
 
81
  */
82
  static function save( $new, $old, $post_id, $field )
83
  {
@@ -127,7 +101,12 @@ if ( ! class_exists( 'RWMB_Select_Field' ) )
127
  {
128
  $html = '';
129
  if ( $field['placeholder'] )
130
- $html = 'select' == $field['type'] ? "<option value=''>{$field['placeholder']}</option>" : '<option></option>';
 
 
 
 
 
131
 
132
  $option = '<option value="%s"%s>%s</option>';
133
 
@@ -143,5 +122,74 @@ if ( ! class_exists( 'RWMB_Select_Field' ) )
143
 
144
  return $html;
145
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  }
147
  }
31
  $field['field_name'],
32
  $field['id'],
33
  $field['size'],
34
+ $field['multiple'] ? ' multiple' : ''
35
  );
36
 
37
  $html .= self::options_html( $field, $meta );
41
  return $html;
42
  }
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  /**
45
  * Save meta value
46
  * If field is cloneable, value is saved as a single entry in DB
47
  * Otherwise value is saved as multiple entries (for backward compatibility)
48
  *
 
 
49
  * @param $new
50
  * @param $old
51
  * @param $post_id
52
  * @param $field
53
+ *
54
+ * @return void
55
  */
56
  static function save( $new, $old, $post_id, $field )
57
  {
101
  {
102
  $html = '';
103
  if ( $field['placeholder'] )
104
+ {
105
+ $show_placeholder = ( 'select' == $field['type'] ) // Normal select field
106
+ || ( isset( $field['field_type'] ) && 'select' == $field['field_type'] ) // For 'post' field
107
+ || ( isset( $field['display_type'] ) && 'select' == $field['display_type'] ); // For 'taxonomy' field
108
+ $html = $show_placeholder ? "<option value=''>{$field['placeholder']}</option>" : '<option></option>';
109
+ }
110
 
111
  $option = '<option value="%s"%s>%s</option>';
112
 
122
 
123
  return $html;
124
  }
125
+
126
+ /**
127
+ * Output the field value
128
+ * Display unordered list of option labels, not option values
129
+ *
130
+ * @param array $field Field parameters
131
+ * @param array $args Additional arguments. Not used for these fields.
132
+ * @param int|null $post_id Post ID. null for current post. Optional.
133
+ *
134
+ * @return string Link(s) to post
135
+ */
136
+ static function the_value( $field, $args = array(), $post_id = null )
137
+ {
138
+ $value = self::get_value( $field, $args, $post_id );
139
+ if ( ! $value )
140
+ return '';
141
+
142
+ $function = array( RW_Meta_Box::get_class_name( $field ), 'get_option_label' );
143
+
144
+ if ( $field['clone'] )
145
+ {
146
+ $output = '<ul>';
147
+ if ( $field['multiple'] )
148
+ {
149
+ foreach ( $value as $subvalue )
150
+ {
151
+ $output .= '<li>';
152
+ array_walk_recursive( $subvalue, $function, $field );
153
+ $output .= '<ul><li>' . implode( '</li><li>', $subvalue ) . '</li></ul>';
154
+ $output .= '</li>';
155
+ }
156
+ }
157
+ else
158
+ {
159
+ array_walk_recursive( $value, $function, $field );
160
+ $output = '<li>' . implode( '</li><li>', $value ) . '</li>';
161
+ }
162
+ $output .= '</ul>';
163
+ }
164
+ else
165
+ {
166
+ if ( $field['multiple'] )
167
+ {
168
+ array_walk_recursive( $value, $function, $field );
169
+ $output = '<ul><li>' . implode( '</li><li>', $value ) . '</li></ul>';
170
+ }
171
+ else
172
+ {
173
+ call_user_func_array( $function, array( &$value, 0, $field ) );
174
+ $output = $value;
175
+ }
176
+ }
177
+
178
+ return $output;
179
+ }
180
+
181
+ /**
182
+ * Get option label to display in the frontend
183
+ *
184
+ * @param int $value Option value
185
+ * @param int $index Array index
186
+ * @param array $field Field parameter
187
+ *
188
+ * @return string
189
+ */
190
+ static function get_option_label( &$value, $index, $field )
191
+ {
192
+ $value = $field['options'][$value];
193
+ }
194
  }
195
  }
inc/fields/taxonomy-advanced.php CHANGED
@@ -58,5 +58,37 @@ if ( ! class_exists( 'RWMB_Taxonomy_Advanced_Field' ) )
58
 
59
  return $meta;
60
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  }
62
  }
58
 
59
  return $meta;
60
  }
61
+
62
+ /**
63
+ * Get the field value
64
+ * Return list of post term objects
65
+ *
66
+ * @param array $field Field parameters
67
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
68
+ * @param int|null $post_id Post ID. null for current post. Optional.
69
+ *
70
+ * @return array List of post term objects
71
+ */
72
+ static function get_value( $field, $args = array(), $post_id = null )
73
+ {
74
+ if ( ! $post_id )
75
+ $post_id = get_the_ID();
76
+
77
+ $value = self::meta( $post_id, '', $field );
78
+
79
+ // Allow to pass more arguments to "get_terms"
80
+ $args = wp_parse_args( array(
81
+ 'include' => $value,
82
+ 'hide_empty' => false,
83
+ ), $args );
84
+ $value = get_terms( $field['options']['taxonomy'], $args );
85
+
86
+ // Get single value if necessary
87
+ if ( ! $field['clone'] && ! $field['multiple'] )
88
+ {
89
+ $value = reset( $value );
90
+ }
91
+ return $value;
92
+ }
93
  }
94
  }
inc/fields/taxonomy.php CHANGED
@@ -17,7 +17,7 @@ if ( ! class_exists( 'RWMB_Taxonomy_Field' ) )
17
  {
18
  RWMB_Select_Advanced_Field::admin_enqueue_scripts();
19
  wp_enqueue_style( 'rwmb-taxonomy', RWMB_CSS_URL . 'taxonomy.css', array(), RWMB_VER );
20
- wp_enqueue_script( 'rwmb-taxonomy', RWMB_JS_URL . 'taxonomy.js', array( 'jquery', 'rwmb-select-advanced', 'wp-ajax-response' ), RWMB_VER, true );
21
  }
22
 
23
  /**
@@ -88,7 +88,8 @@ if ( ! class_exists( 'RWMB_Taxonomy_Field' ) )
88
  $options = $field['options'];
89
  $terms = get_terms( $options['taxonomy'], $options['args'] );
90
 
91
- $field['options'] = self::get_options( $terms );
 
92
 
93
  $html = '';
94
 
@@ -130,7 +131,7 @@ if ( ! class_exists( 'RWMB_Taxonomy_Field' ) )
130
  static function walk_checkbox_tree( $meta, $field, $elements, $parent = 0, $active = false )
131
  {
132
  if ( ! isset( $elements[$parent] ) )
133
- return;
134
  $terms = $elements[$parent];
135
  $field['options'] = self::get_options( $terms );
136
  $hidden = $active ? '' : 'hidden';
@@ -167,7 +168,7 @@ if ( ! class_exists( 'RWMB_Taxonomy_Field' ) )
167
  static function walk_select_tree( $meta, $field, $elements, $parent = 0, $active = false )
168
  {
169
  if ( ! isset( $elements[$parent] ) )
170
- return;
171
  $terms = $elements[$parent];
172
  $field['options'] = self::get_options( $terms );
173
 
@@ -259,5 +260,105 @@ if ( ! class_exists( 'RWMB_Taxonomy_Field' ) )
259
 
260
  return $meta;
261
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  }
263
  }
17
  {
18
  RWMB_Select_Advanced_Field::admin_enqueue_scripts();
19
  wp_enqueue_style( 'rwmb-taxonomy', RWMB_CSS_URL . 'taxonomy.css', array(), RWMB_VER );
20
+ wp_enqueue_script( 'rwmb-taxonomy', RWMB_JS_URL . 'taxonomy.js', array( 'rwmb-select-advanced' ), RWMB_VER, true );
21
  }
22
 
23
  /**
88
  $options = $field['options'];
89
  $terms = get_terms( $options['taxonomy'], $options['args'] );
90
 
91
+ $field['options'] = self::get_options( $terms );
92
+ $field['display_type'] = $options['type'];
93
 
94
  $html = '';
95
 
131
  static function walk_checkbox_tree( $meta, $field, $elements, $parent = 0, $active = false )
132
  {
133
  if ( ! isset( $elements[$parent] ) )
134
+ return '';
135
  $terms = $elements[$parent];
136
  $field['options'] = self::get_options( $terms );
137
  $hidden = $active ? '' : 'hidden';
168
  static function walk_select_tree( $meta, $field, $elements, $parent = 0, $active = false )
169
  {
170
  if ( ! isset( $elements[$parent] ) )
171
+ return '';
172
  $terms = $elements[$parent];
173
  $field['options'] = self::get_options( $terms );
174
 
260
 
261
  return $meta;
262
  }
263
+
264
+ /**
265
+ * Get the field value
266
+ * Return list of post term objects
267
+ *
268
+ * @param array $field Field parameters
269
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
270
+ * @param int|null $post_id Post ID. null for current post. Optional.
271
+ *
272
+ * @return array List of post term objects
273
+ */
274
+ static function get_value( $field, $args = array(), $post_id = null )
275
+ {
276
+ if ( ! $post_id )
277
+ $post_id = get_the_ID();
278
+
279
+ $value = wp_get_post_terms( $post_id, $field['options']['taxonomy'] );
280
+
281
+ // Get single value if necessary
282
+ if ( ! $field['clone'] && ! $field['multiple'] )
283
+ {
284
+ $value = reset( $value );
285
+ }
286
+ return $value;
287
+ }
288
+
289
+ /**
290
+ * Output the field value
291
+ * Display unordered list of option labels, not option values
292
+ *
293
+ * @param array $field Field parameters
294
+ * @param array $args Additional arguments. Not used for these fields.
295
+ * @param int|null $post_id Post ID. null for current post. Optional.
296
+ *
297
+ * @return string Link(s) to post
298
+ */
299
+ static function the_value( $field, $args = array(), $post_id = null )
300
+ {
301
+ $class = RW_Meta_Box::get_class_name( $field );
302
+ $value = call_user_func( array( $class, 'get_value' ), $field, $args, $post_id );
303
+ if ( ! $value || is_wp_error( $value ) )
304
+ return '';
305
+
306
+ $function = array( $class, 'get_option_label' );
307
+
308
+ if ( $field['clone'] )
309
+ {
310
+ $output = '<ul>';
311
+ if ( $field['multiple'] )
312
+ {
313
+ foreach ( $value as $subvalue )
314
+ {
315
+ $output .= '<li>';
316
+ array_walk_recursive( $subvalue, $function, $field );
317
+ $output .= '<ul><li>' . implode( '</li><li>', $subvalue ) . '</li></ul>';
318
+ $output .= '</li>';
319
+ }
320
+ }
321
+ else
322
+ {
323
+ array_walk_recursive( $value, $function, $field );
324
+ $output = '<li>' . implode( '</li><li>', $value ) . '</li>';
325
+ }
326
+ $output .= '</ul>';
327
+ }
328
+ else
329
+ {
330
+ if ( $field['multiple'] )
331
+ {
332
+ array_walk_recursive( $value, $function, $field );
333
+ $output = '<ul><li>' . implode( '</li><li>', $value ) . '</li></ul>';
334
+ }
335
+ else
336
+ {
337
+ call_user_func_array( $function, array( &$value, 0, $field ) );
338
+ $output = $value;
339
+ }
340
+ }
341
+
342
+ return $output;
343
+ }
344
+
345
+ /**
346
+ * Get post link to display in the frontend
347
+ *
348
+ * @param object $value Option value, e.g. term object
349
+ * @param int $index Array index
350
+ * @param array $field Field parameter
351
+ *
352
+ * @return string
353
+ */
354
+ static function get_option_label( &$value, $index, $field )
355
+ {
356
+ $value = sprintf(
357
+ '<a href="%s" title="%s">%s</a>',
358
+ esc_url( get_term_link( $value ) ),
359
+ esc_attr( $value->name ),
360
+ $value->name
361
+ );
362
+ }
363
  }
364
  }
inc/fields/text-list.php CHANGED
@@ -4,7 +4,7 @@ defined( 'ABSPATH' ) || exit;
4
 
5
  if ( ! class_exists( 'RWMB_Text_List_Field' ) )
6
  {
7
- class RWMB_Text_List_Field extends RWMB_Field
8
  {
9
  /**
10
  * Get field HTML
@@ -16,94 +16,79 @@ if ( ! class_exists( 'RWMB_Text_List_Field' ) )
16
  */
17
  static function html( $meta, $field )
18
  {
19
- $html = '';
20
- $input = '<label><input type="text" class="rwmb-text-list" name="%s" id="%s" value="%s" placeholder="%s" /> %s</label>';
21
 
22
  $i = 0;
23
- foreach ( $field['options'] as $value => $label )
24
  {
25
- $html .= sprintf(
26
  $input,
27
  $field['field_name'],
28
- $field['id'],
29
- $meta[$i],
30
- $value,
31
  $label
32
  );
33
  $i ++;
34
  }
35
 
36
- return $html;
37
  }
38
 
39
  /**
40
- * Get meta value
41
- * If field is cloneable, value is saved as a single entry in DB
42
- * Otherwise value is saved as multiple entries (for backward compatibility)
43
  *
44
- * @see "save" method for better understanding
 
 
45
  *
46
- * TODO: A good way to ALWAYS save values in single entry in DB, while maintaining backward compatibility
47
- *
48
- * @param $post_id
49
- * @param $saved
50
- * @param $field
51
- *
52
- * @return array
53
  */
54
- static function meta( $post_id, $saved, $field )
55
  {
56
- $single = $field['clone'] || ! $field['multiple'];
57
- $meta = get_post_meta( $post_id, $field['id'], $single );
58
- $meta = ( ! $saved && '' === $meta || array() === $meta ) ? $field['std'] : $meta;
59
-
60
- $meta = array_map( 'esc_attr', (array) $meta );
61
 
62
- return $meta;
63
- }
64
-
65
- /**
66
- * Save meta value
67
- * If field is cloneable, value is saved as a single entry in DB
68
- * Otherwise value is saved as multiple entries (for backward compatibility)
69
- *
70
- * TODO: A good way to ALWAYS save values in single entry in DB, while maintaining backward compatibility
71
- *
72
- * @param $new
73
- * @param $old
74
- * @param $post_id
75
- * @param $field
76
- */
77
- static function save( $new, $old, $post_id, $field )
78
- {
79
- if ( ! $field['clone'] )
80
  {
81
- parent::save( $new, $old, $post_id, $field );
 
 
 
82
 
83
- return;
 
 
 
 
 
 
 
 
 
 
 
 
84
  }
85
-
86
- if ( empty( $new ) )
87
- delete_post_meta( $post_id, $field['id'] );
88
  else
89
- update_post_meta( $post_id, $field['id'], $new );
90
- }
91
-
92
- /**
93
- * Normalize parameters for field
94
- *
95
- * @param array $field
96
- *
97
- * @return array
98
- */
99
- static function normalize_field( $field )
100
- {
101
- $field['multiple'] = true;
102
- $field['field_name'] = $field['id'];
103
- if ( ! $field['clone'] )
104
- $field['field_name'] .= '[]';
105
 
106
- return $field;
107
  }
108
  }
109
  }
4
 
5
  if ( ! class_exists( 'RWMB_Text_List_Field' ) )
6
  {
7
+ class RWMB_Text_List_Field extends RWMB_Field_Multiple_Values
8
  {
9
  /**
10
  * Get field HTML
16
  */
17
  static function html( $meta, $field )
18
  {
19
+ $html = array();
20
+ $input = '<label><input type="text" class="rwmb-text-list" name="%s" value="%s" placeholder="%s"> %s</label>';
21
 
22
  $i = 0;
23
+ foreach ( $field['options'] as $placeholder => $label )
24
  {
25
+ $html[] = sprintf(
26
  $input,
27
  $field['field_name'],
28
+ isset( $meta[$i] ) ? esc_attr( $meta[$i] ) : '',
29
+ $placeholder,
 
30
  $label
31
  );
32
  $i ++;
33
  }
34
 
35
+ return implode( ' ', $html );
36
  }
37
 
38
  /**
39
+ * Output the field value
40
+ * Display option name instead of option value
 
41
  *
42
+ * @param array $field Field parameters
43
+ * @param array $args Additional arguments. Not used for these fields.
44
+ * @param int|null $post_id Post ID. null for current post. Optional.
45
  *
46
+ * @return mixed Field value
 
 
 
 
 
 
47
  */
48
+ static function the_value( $field, $args = array(), $post_id = null )
49
  {
50
+ $value = self::get_value( $field, $args, $post_id );
51
+ if ( ! $value )
52
+ return '';
 
 
53
 
54
+ $output = '<ul>';
55
+ if ( $field['clone'] )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  {
57
+ foreach ( $value as $subvalue )
58
+ {
59
+ $output .= '<li>';
60
+ $output .= '<ul>';
61
 
62
+ $i = 0;
63
+ foreach ( $field['options'] as $placeholder => $label )
64
+ {
65
+ $output .= sprintf(
66
+ '<li><label>%s</label>: %s</li>',
67
+ $label,
68
+ isset( $subvalue[$i] ) ? $subvalue[$i] : ''
69
+ );
70
+ $i ++;
71
+ }
72
+ $output .= '</ul>';
73
+ $output .= '</li>';
74
+ }
75
  }
 
 
 
76
  else
77
+ {
78
+ $i = 0;
79
+ foreach ( $field['options'] as $placeholder => $label )
80
+ {
81
+ $output .= sprintf(
82
+ '<li><label>%s</label>: %s</li>',
83
+ $label,
84
+ isset( $value[$i] ) ? $value[$i] : ''
85
+ );
86
+ $i ++;
87
+ }
88
+ }
89
+ $output .= '</ul>';
 
 
 
90
 
91
+ return $output;
92
  }
93
  }
94
  }
inc/fields/textarea.php CHANGED
@@ -27,6 +27,18 @@ if ( ! class_exists( 'RWMB_Textarea_Field' ) )
27
  );
28
  }
29
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  /**
31
  * Normalize parameters for field
32
  *
27
  );
28
  }
29
 
30
+ /**
31
+ * Escape meta for field output
32
+ *
33
+ * @param mixed $meta
34
+ *
35
+ * @return mixed
36
+ */
37
+ static function esc_meta( $meta )
38
+ {
39
+ return is_array( $meta ) ? array_map( 'esc_textarea', $meta ) : esc_textarea( $meta );
40
+ }
41
+
42
  /**
43
  * Normalize parameters for field
44
  *
inc/fields/time.php CHANGED
@@ -18,30 +18,27 @@ if ( ! class_exists( 'RWMB_Time_Field' ) )
18
  wp_register_style( 'jquery-ui-theme', "{$url}/jquery.ui.theme.css", array(), '1.8.17' );
19
  wp_register_style( 'jquery-ui-datepicker', "{$url}/jquery.ui.datepicker.css", array( 'jquery-ui-core', 'jquery-ui-theme' ), '1.8.17' );
20
  wp_register_style( 'jquery-ui-slider', "{$url}/jquery.ui.slider.css", array( 'jquery-ui-core', 'jquery-ui-theme' ), '1.8.17' );
21
- wp_enqueue_style( 'jquery-ui-timepicker', "{$url}/jquery-ui-timepicker-addon.css", array( 'jquery-ui-datepicker', 'jquery-ui-slider' ), '0.9.7' );
22
 
23
  $url = RWMB_JS_URL . 'jqueryui';
24
- wp_register_script( 'jquery-ui-timepicker', "{$url}/jquery-ui-timepicker-addon.js", array( 'jquery-ui-datepicker', 'jquery-ui-slider' ), '0.9.7', true );
25
- $deps = array( 'jquery-ui-timepicker' );
26
 
27
- $locale = str_replace( '_', '-', get_locale() );
28
- $timepicker_locale_js_url = '';
29
- if ( file_exists( RWMB_DIR . "js/jqueryui/timepicker-i18n/jquery-ui-timepicker-{$locale}.js" ) )
30
- {
31
- $timepicker_locale_js_url = "{$url}/timepicker-i18n/jquery-ui-timepicker-{$locale}.js";
32
- }
33
- elseif ( strlen( $locale ) > 2 && file_exists( RWMB_DIR . 'js/jqueryui/timepicker-i18n/jquery-ui-timepicker-' . substr( $locale, 0, 2 ) . '.js' ) )
34
- {
35
- $timepicker_locale_js_url = "{$url}/timepicker-i18n/jquery-ui-timepicker-" . substr( $locale, 0, 2 ) . '.js';
36
- }
37
- if ( $timepicker_locale_js_url )
38
- {
39
- wp_register_script( 'jquery-ui-timepicker-i18n', $timepicker_locale_js_url, array( 'jquery-ui-timepicker' ), '0.9.7', true );
40
- $deps = array( 'jquery-ui-timepicker-i18n' );
41
- }
42
 
43
- wp_enqueue_script( 'rwmb-time', RWMB_JS_URL . 'time.js', $deps, RWMB_VER, true );
44
- wp_localize_script( 'rwmb-time', 'RWMB_Timepicker', array( 'lang' => $locale ) );
 
 
 
45
  }
46
 
47
  /**
@@ -55,7 +52,7 @@ if ( ! class_exists( 'RWMB_Time_Field' ) )
55
  static function html( $meta, $field )
56
  {
57
  return sprintf(
58
- '<input type="text" class="rwmb-time" name="%s" value="%s" id="%s" size="%s" data-options="%s" />',
59
  $field['field_name'],
60
  $meta,
61
  isset( $field['clone'] ) && $field['clone'] ? '' : $field['id'],
@@ -82,7 +79,7 @@ if ( ! class_exists( 'RWMB_Time_Field' ) )
82
  // Use 'js_options' instead
83
  $field['js_options'] = wp_parse_args( $field['js_options'], array(
84
  'showButtonPanel' => true,
85
- 'timeFormat' => empty( $field['format'] ) ? 'hh:mm:ss' : $field['format'],
86
  ) );
87
 
88
  return $field;
18
  wp_register_style( 'jquery-ui-theme', "{$url}/jquery.ui.theme.css", array(), '1.8.17' );
19
  wp_register_style( 'jquery-ui-datepicker', "{$url}/jquery.ui.datepicker.css", array( 'jquery-ui-core', 'jquery-ui-theme' ), '1.8.17' );
20
  wp_register_style( 'jquery-ui-slider', "{$url}/jquery.ui.slider.css", array( 'jquery-ui-core', 'jquery-ui-theme' ), '1.8.17' );
21
+ wp_enqueue_style( 'jquery-ui-timepicker', "{$url}/jquery-ui-timepicker-addon.min.css", array( 'jquery-ui-datepicker', 'jquery-ui-slider' ), '1.5.0' );
22
 
23
  $url = RWMB_JS_URL . 'jqueryui';
24
+ wp_register_script( 'jquery-ui-timepicker', "{$url}/jquery-ui-timepicker-addon.min.js", array( 'jquery-ui-datepicker', 'jquery-ui-slider' ), '1.5.0', true );
 
25
 
26
+ /**
27
+ * Localization
28
+ * Use 1 minified JS file which contains all languages for simpilicity (in version < 4.4.2 we use separated JS files).
29
+ * The language is set in Javascript
30
+ *
31
+ * Note: we use full locale (de-DE) and fallback to short locale (de)
32
+ */
33
+ $locale = str_replace( '_', '-', get_locale() );
34
+ $locale_short = substr( $locale, 0, 2 );
35
+ wp_register_script( 'jquery-ui-timepicker-i18n', "{$url}/jquery-ui-timepicker-addon-i18n.min.js", array( 'jquery-ui-timepicker' ), '1.5.0', true );
 
 
 
 
 
36
 
37
+ wp_enqueue_script( 'rwmb-time', RWMB_JS_URL . 'time.js', array( 'jquery-ui-timepicker-i18n' ), RWMB_VER, true );
38
+ wp_localize_script( 'rwmb-time', 'RWMB_Timepicker', array(
39
+ 'locale' => $locale,
40
+ 'localeShort' => $locale_short,
41
+ ) );
42
  }
43
 
44
  /**
52
  static function html( $meta, $field )
53
  {
54
  return sprintf(
55
+ '<input type="text" class="rwmb-time" name="%s" value="%s" id="%s" size="%s" data-options="%s">',
56
  $field['field_name'],
57
  $meta,
58
  isset( $field['clone'] ) && $field['clone'] ? '' : $field['id'],
79
  // Use 'js_options' instead
80
  $field['js_options'] = wp_parse_args( $field['js_options'], array(
81
  'showButtonPanel' => true,
82
+ 'timeFormat' => empty( $field['format'] ) ? 'HH:mm' : $field['format'],
83
  ) );
84
 
85
  return $field;
inc/fields/user.php CHANGED
@@ -7,18 +7,8 @@ require_once RWMB_FIELDS_DIR . 'select-advanced.php';
7
 
8
  if ( ! class_exists( 'RWMB_User_Field' ) )
9
  {
10
- class RWMB_User_Field extends RWMB_Field
11
  {
12
- /**
13
- * Enqueue scripts and styles
14
- *
15
- * @return void
16
- */
17
- static function admin_enqueue_scripts()
18
- {
19
- RWMB_Select_Advanced_Field::admin_enqueue_scripts();
20
- }
21
-
22
  /**
23
  * Get field HTML
24
  *
@@ -50,16 +40,13 @@ if ( ! class_exists( 'RWMB_User_Field' ) )
50
  */
51
  static function normalize_field( $field )
52
  {
53
-
54
- $default_post_type = __( 'User', 'meta-box' );
55
-
56
  $field = wp_parse_args( $field, array(
57
  'field_type' => 'select_advanced',
58
  'parent' => false,
59
  'query_args' => array(),
60
  ) );
61
 
62
- $field['std'] = empty( $field['std'] ) ? sprintf( __( 'Select a %s', 'meta-box' ), $default_post_type ) : $field['std'];
63
 
64
  $field['query_args'] = wp_parse_args( $field['query_args'], array(
65
  'orderby' => 'display_name',
@@ -79,48 +66,6 @@ if ( ! class_exists( 'RWMB_User_Field' ) )
79
  }
80
  }
81
 
82
- /**
83
- * Get meta value
84
- * If field is cloneable, value is saved as a single entry in DB
85
- * Otherwise value is saved as multiple entries (for backward compatibility)
86
- *
87
- * @see "save" method for better understanding
88
- *
89
- * @param $post_id
90
- * @param $saved
91
- * @param $field
92
- *
93
- * @return array
94
- */
95
- static function meta( $post_id, $saved, $field )
96
- {
97
- if ( isset( $field['parent'] ) && $field['parent'] )
98
- {
99
- $post = get_post( $post_id );
100
-
101
- return $post->post_parent;
102
- }
103
-
104
- return RWMB_Select_Field::meta( $post_id, $saved, $field );
105
- }
106
-
107
- /**
108
- * Save meta value
109
- * If field is cloneable, value is saved as a single entry in DB
110
- * Otherwise value is saved as multiple entries (for backward compatibility)
111
- *
112
- * TODO: A good way to ALWAYS save values in single entry in DB, while maintaining backward compatibility
113
- *
114
- * @param $new
115
- * @param $old
116
- * @param $post_id
117
- * @param $field
118
- */
119
- static function save( $new, $old, $post_id, $field )
120
- {
121
- return RWMB_Select_Field::save( $new, $old, $post_id, $field );
122
- }
123
-
124
  /**
125
  * Get users
126
  *
@@ -139,5 +84,20 @@ if ( ! class_exists( 'RWMB_User_Field' ) )
139
 
140
  return $options;
141
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  }
143
  }
7
 
8
  if ( ! class_exists( 'RWMB_User_Field' ) )
9
  {
10
+ class RWMB_User_Field extends RWMB_Select_Advanced_Field
11
  {
 
 
 
 
 
 
 
 
 
 
12
  /**
13
  * Get field HTML
14
  *
40
  */
41
  static function normalize_field( $field )
42
  {
 
 
 
43
  $field = wp_parse_args( $field, array(
44
  'field_type' => 'select_advanced',
45
  'parent' => false,
46
  'query_args' => array(),
47
  ) );
48
 
49
+ $field['std'] = empty( $field['std'] ) ? __( 'Select an user', 'meta-box' ) : $field['std'];
50
 
51
  $field['query_args'] = wp_parse_args( $field['query_args'], array(
52
  'orderby' => 'display_name',
66
  }
67
  }
68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  /**
70
  * Get users
71
  *
84
 
85
  return $options;
86
  }
87
+
88
+ /**
89
+ * Get option label to display in the frontend
90
+ *
91
+ * @param int $value Option value
92
+ * @param int $index Array index
93
+ * @param array $field Field parameter
94
+ *
95
+ * @return string
96
+ */
97
+ static function get_option_label( &$value, $index, $field )
98
+ {
99
+ $user = get_userdata( $value );
100
+ $value = '<a href="' . get_author_posts_url( $value ) . '">' . $user->display_name . '</a>';
101
+ }
102
  }
103
  }
inc/fields/wysiwyg.php CHANGED
@@ -75,6 +75,18 @@ if ( ! class_exists( 'RWMB_Wysiwyg_Field' ) )
75
  return $editor;
76
  }
77
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  /**
79
  * Normalize parameters for field
80
  *
75
  return $editor;
76
  }
77
 
78
+ /**
79
+ * Escape meta for field output
80
+ *
81
+ * @param mixed $meta
82
+ *
83
+ * @return mixed
84
+ */
85
+ static function esc_meta( $meta )
86
+ {
87
+ return $meta;
88
+ }
89
+
90
  /**
91
  * Normalize parameters for field
92
  *
inc/helpers.php CHANGED
@@ -15,110 +15,33 @@ if ( ! class_exists( 'RWMB_Helper' ) )
15
  class RWMB_Helper
16
  {
17
  /**
18
- * Do actions when class is loaded
 
 
19
  *
20
- * @return void
21
- */
22
- static function on_load()
23
- {
24
- add_shortcode( 'rwmb_meta', array( __CLASS__, 'shortcode' ) );
25
- }
26
-
27
- /**
28
- * Shortcode to display meta value
29
- *
30
- * @param $atts Array of shortcode attributes, same as meta() function, but has more "meta_key" parameter
31
- *
32
- * @see meta() function below
33
  *
34
- * @return string
35
  */
36
- static function shortcode( $atts )
37
  {
38
- $atts = wp_parse_args( $atts, array(
39
- 'type' => 'text',
40
- 'post_id' => get_the_ID(),
41
- ) );
42
- if ( empty( $atts['meta_key'] ) )
43
- return '';
44
-
45
- $meta = self::meta( $atts['meta_key'], $atts, $atts['post_id'] );
46
 
47
- // Get uploaded files info
48
- if ( in_array( $atts['type'], array( 'file', 'file_advanced' ) ) )
49
  {
50
- $content = '<ul>';
51
- foreach ( $meta as $file )
52
  {
53
- $content .= sprintf(
54
- '<li><a href="%s" title="%s">%s</a></li>',
55
- $file['url'],
56
- $file['title'],
57
- $file['name']
58
- );
59
- }
60
- $content .= '</ul>';
61
- }
62
-
63
- // Get uploaded images info
64
- elseif ( in_array( $atts['type'], array( 'image', 'plupload_image', 'thickbox_image', 'image_advanced' ) ) )
65
- {
66
- $content = '<ul>';
67
- foreach ( $meta as $image )
68
- {
69
- // Link thumbnail to full size image?
70
- if ( isset( $atts['link'] ) && $atts['link'] )
71
- {
72
- $content .= sprintf(
73
- '<li><a href="%s" title="%s"><img src="%s" alt="%s" title="%s" /></a></li>',
74
- $image['full_url'],
75
- $image['title'],
76
- $image['url'],
77
- $image['alt'],
78
- $image['title']
79
- );
80
- }
81
- else
82
  {
83
- $content .= sprintf(
84
- '<li><img src="%s" alt="%s" title="%s" /></li>',
85
- $image['url'],
86
- $image['alt'],
87
- $image['title']
88
- );
89
  }
90
  }
91
- $content .= '</ul>';
92
- }
93
-
94
- // Get post terms
95
- elseif ( 'taxonomy' == $atts['type'] )
96
- {
97
- $content = '<ul>';
98
- foreach ( $meta as $term )
99
- {
100
- $content .= sprintf(
101
- '<li><a href="%s" title="%s">%s</a></li>',
102
- get_term_link( $term, $atts['taxonomy'] ),
103
- $term->name,
104
- $term->name
105
- );
106
- }
107
- $content .= '</ul>';
108
- }
109
-
110
- // Normal multiple fields: checkbox_list, select with multiple values
111
- elseif ( is_array( $meta ) )
112
- {
113
- $content = '<ul><li>' . implode( '</li><li>', $meta ) . '</li></ul>';
114
  }
115
 
116
- else
117
- {
118
- $content = $meta;
119
- }
120
-
121
- return apply_filters( 'rwmb_shortcode', $content );
122
  }
123
 
124
  /**
@@ -133,15 +56,15 @@ if ( ! class_exists( 'RWMB_Helper' ) )
133
  static function meta( $key, $args = array(), $post_id = null )
134
  {
135
  $post_id = empty( $post_id ) ? get_the_ID() : $post_id;
136
-
137
- $args = wp_parse_args( $args, array(
138
- 'type' => 'text',
139
- )
140
- );
141
 
142
  // Set 'multiple' for fields based on 'type'
143
  if ( ! isset( $args['multiple'] ) )
 
144
  $args['multiple'] = in_array( $args['type'], array( 'checkbox_list', 'file', 'file_advanced', 'image', 'image_advanced', 'plupload_image', 'thickbox_image' ) );
 
145
 
146
  $meta = get_post_meta( $post_id, $key, ! $args['multiple'] );
147
 
@@ -153,41 +76,38 @@ if ( ! class_exists( 'RWMB_Helper' ) )
153
  $files = array();
154
  foreach ( $meta as $id )
155
  {
156
- $files[$id] = self::file_info( $id );
 
 
 
 
157
  }
158
  $meta = $files;
159
  }
160
  }
161
-
162
  // Get uploaded images info
163
  elseif ( in_array( $args['type'], array( 'image', 'plupload_image', 'thickbox_image', 'image_advanced' ) ) )
164
  {
165
- global $wpdb;
166
-
167
- $meta = $wpdb->get_col( $wpdb->prepare( "
168
- SELECT meta_value FROM $wpdb->postmeta
169
- WHERE post_id = %d AND meta_key = '%s'
170
- ORDER BY meta_id ASC
171
- ", $post_id, $key ) );
172
-
173
  if ( is_array( $meta ) && ! empty( $meta ) )
174
  {
175
  $images = array();
176
  foreach ( $meta as $id )
177
  {
178
- $images[$id] = self::image_info( $id, $args );
 
 
 
 
179
  }
180
  $meta = $images;
181
  }
182
  }
183
-
184
  // Get terms
185
  elseif ( 'taxonomy_advanced' == $args['type'] )
186
  {
187
  if ( ! empty( $args['taxonomy'] ) )
188
  {
189
  $term_ids = array_map( 'intval', array_filter( explode( ',', $meta . ',' ) ) );
190
-
191
  // Allow to pass more arguments to "get_terms"
192
  $func_args = wp_parse_args( array(
193
  'include' => $term_ids,
@@ -201,208 +121,135 @@ if ( ! class_exists( 'RWMB_Helper' ) )
201
  $meta = array();
202
  }
203
  }
204
-
205
  // Get post terms
206
  elseif ( 'taxonomy' == $args['type'] )
207
  {
208
  $meta = empty( $args['taxonomy'] ) ? array() : wp_get_post_terms( $post_id, $args['taxonomy'] );
209
  }
210
-
211
  // Get map
212
  elseif ( 'map' == $args['type'] )
213
  {
214
- $meta = self::map( $key, $args, $post_id );
215
  }
216
-
217
  return apply_filters( 'rwmb_meta', $meta, $key, $args, $post_id );
218
  }
 
 
219
 
220
- /**
221
- * Get uploaded file information
222
- *
223
- * @param int $id Attachment file ID (post ID). Required.
224
- *
225
- * @return array|bool False if file not found. Array of (id, name, path, url) on success
226
- */
227
- static function file_info( $id )
228
- {
229
- $path = get_attached_file( $id );
 
 
 
 
 
 
230
 
231
- return array(
232
- 'ID' => $id,
233
- 'name' => basename( $path ),
234
- 'path' => $path,
235
- 'url' => wp_get_attachment_url( $id ),
236
- 'title' => get_the_title( $id ),
237
- );
238
- }
 
 
 
 
 
 
 
 
 
 
239
 
240
  /**
241
- * Get uploaded image information
242
  *
243
- * @param int $id Attachment image ID (post ID). Required.
244
- * @param array $args Array of arguments (for size). Required.
245
- *
246
- * @return array|bool False if file not found. Array of (id, name, path, url) on success
247
  */
248
- static function image_info( $id, $args = array() )
249
- {
250
- $args = wp_parse_args( $args, array(
251
- 'size' => 'thumbnail',
252
- ) );
253
 
254
- $img_src = wp_get_attachment_image_src( $id, $args['size'] );
255
- if ( empty( $img_src ) )
256
- return false;
257
 
258
- $attachment = get_post( $id );
259
- $path = get_attached_file( $id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
 
261
- return array(
262
- 'ID' => $id,
263
- 'name' => basename( $path ),
264
- 'path' => $path,
265
- 'url' => $img_src[0],
266
- 'width' => $img_src[1],
267
- 'height' => $img_src[2],
268
- 'full_url' => wp_get_attachment_url( $id ),
269
- 'title' => $attachment->post_title,
270
- 'caption' => $attachment->post_excerpt,
271
- 'description' => $attachment->post_content,
272
- 'alt' => get_post_meta( $id, '_wp_attachment_image_alt', true ),
273
- );
274
- }
275
 
276
  /**
277
- * Display map using Google API
278
- *
279
- * @param string $key Meta key
280
- * @param array $args Map parameter
281
- * @param int|null $post_id Post ID
282
  *
283
- * @return string
 
 
 
284
  */
285
- static function map( $key, $args = array(), $post_id = null )
286
- {
287
- $post_id = empty( $post_id ) ? get_the_ID() : $post_id;
288
- $loc = get_post_meta( $post_id, $key, true );
289
- if ( ! $loc )
290
- return '';
291
-
292
- $parts = array_map( 'trim', explode( ',', $loc ) );
293
-
294
- // No zoom entered, set it to 14 by default
295
- if ( count( $parts ) < 3 )
296
- $parts[2] = 14;
297
-
298
- // Map parameters
299
- $args = wp_parse_args( $args, array(
300
- 'width' => '640px',
301
- 'height' => '480px',
302
- 'marker' => true, // Display marker?
303
- 'marker_title' => '', // Marker title, when hover
304
- 'info_window' => '', // Content of info window (when click on marker). HTML allowed
305
- 'js_options' => array(),
306
- ) );
307
- $args['js_options'] = wp_parse_args( $args['js_options'], array(
308
- 'zoom' => $parts[2], // Default to 'zoom' level set in admin, but can be overwritten
309
- 'mapTypeId' => 'ROADMAP', // Map type, see https://developers.google.com/maps/documentation/javascript/reference#MapTypeId
310
- ) );
311
-
312
- // Counter to display multiple maps on same page
313
- static $counter = 0;
314
-
315
- $html = sprintf(
316
- '<div id="rwmb-map-canvas-%d" style="width:%s;height:%s"></div>',
317
- $counter,
318
- $args['width'],
319
- $args['height']
320
- );
321
-
322
- // Load Google Maps script only when needed
323
- $html .= '<script>if ( typeof google !== "object" || typeof google.maps !== "object" )
324
- document.write(\'<script src="//maps.google.com/maps/api/js?sensor=false"><\/script>\')</script>';
325
- $html .= '<script>
326
- ( function()
327
- {
328
- ';
329
-
330
- $html .= sprintf( '
331
- var center = new google.maps.LatLng( %s, %s ),
332
- mapOptions = %s,
333
- map;
334
-
335
- switch ( mapOptions.mapTypeId )
336
- {
337
- case "ROADMAP":
338
- mapOptions.mapTypeId = google.maps.MapTypeId.ROADMAP;
339
- break;
340
- case "SATELLITE":
341
- mapOptions.mapTypeId = google.maps.MapTypeId.SATELLITE;
342
- break;
343
- case "HYBRID":
344
- mapOptions.mapTypeId = google.maps.MapTypeId.HYBRID;
345
- break;
346
- case "TERRAIN":
347
- mapOptions.mapTypeId = google.maps.MapTypeId.TERRAIN;
348
- break;
349
- }
350
- mapOptions.center = center;
351
- map = new google.maps.Map( document.getElementById( "rwmb-map-canvas-%d" ), mapOptions );
352
- ',
353
- $parts[0], $parts[1],
354
- json_encode( $args['js_options'] ),
355
- $counter
356
- );
357
 
358
- if ( $args['marker'] )
359
- {
360
- $html .= sprintf( '
361
- var marker = new google.maps.Marker( {
362
- position: center,
363
- map: map%s
364
- } );',
365
- $args['marker_title'] ? ', title: "' . $args['marker_title'] . '"' : ''
366
- );
367
 
368
- if ( $args['info_window'] )
369
- {
370
- $html .= sprintf( '
371
- var infoWindow = new google.maps.InfoWindow( {
372
- content: "%s"
373
- } );
374
-
375
- google.maps.event.addListener( marker, "click", function()
376
- {
377
- infoWindow.open( map, marker );
378
- } );',
379
- $args['info_window']
380
- );
381
- }
382
- }
383
 
384
- $html .= '} )();
385
- </script>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
386
 
387
- $counter ++;
 
 
388
 
389
- return $html;
390
- }
391
  }
392
 
393
- RWMB_Helper::on_load();
394
- }
395
-
396
- /**
397
- * Get post meta
398
- *
399
- * @param string $key Meta key. Required.
400
- * @param int|null $post_id Post ID. null for current post. Optional
401
- * @param array $args Array of arguments. Optional.
402
- *
403
- * @return mixed
404
- */
405
- function rwmb_meta( $key, $args = array(), $post_id = null )
406
- {
407
- return RWMB_Helper::meta( $key, $args, $post_id );
408
  }
15
  class RWMB_Helper
16
  {
17
  /**
18
+ * Find field by field ID
19
+ * This function finds field in meta boxes registered by 'rwmb_meta_boxes' filter
20
+ * Note: if users use old code to add meta boxes, this function might not work properly
21
  *
22
+ * @param string $field_id Field ID
 
 
 
 
 
 
 
 
 
 
 
 
23
  *
24
+ * @return array|false Field params (array) if success. False otherwise.
25
  */
26
+ static function find_field( $field_id )
27
  {
28
+ // Get all meta boxes registered with 'rwmb_meta_boxes' hook
29
+ $meta_boxes = apply_filters( 'rwmb_meta_boxes', array() );
 
 
 
 
 
 
30
 
31
+ // Find field
32
+ foreach ( $meta_boxes as $meta_box )
33
  {
34
+ $meta_box = RW_Meta_Box::normalize( $meta_box );
35
+ foreach ( $meta_box['fields'] as $field )
36
  {
37
+ if ( $field_id == $field['id'] )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  {
39
+ return $field;
 
 
 
 
 
40
  }
41
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  }
43
 
44
+ return false;
 
 
 
 
 
45
  }
46
 
47
  /**
56
  static function meta( $key, $args = array(), $post_id = null )
57
  {
58
  $post_id = empty( $post_id ) ? get_the_ID() : $post_id;
59
+ $args = wp_parse_args( $args, array(
60
+ 'type' => 'text',
61
+ ) );
 
 
62
 
63
  // Set 'multiple' for fields based on 'type'
64
  if ( ! isset( $args['multiple'] ) )
65
+ {
66
  $args['multiple'] = in_array( $args['type'], array( 'checkbox_list', 'file', 'file_advanced', 'image', 'image_advanced', 'plupload_image', 'thickbox_image' ) );
67
+ }
68
 
69
  $meta = get_post_meta( $post_id, $key, ! $args['multiple'] );
70
 
76
  $files = array();
77
  foreach ( $meta as $id )
78
  {
79
+ // Get only info of existing attachments
80
+ if ( get_attached_file( $id ) )
81
+ {
82
+ $files[$id] = RWMB_File_Field::file_info( $id );
83
+ }
84
  }
85
  $meta = $files;
86
  }
87
  }
 
88
  // Get uploaded images info
89
  elseif ( in_array( $args['type'], array( 'image', 'plupload_image', 'thickbox_image', 'image_advanced' ) ) )
90
  {
 
 
 
 
 
 
 
 
91
  if ( is_array( $meta ) && ! empty( $meta ) )
92
  {
93
  $images = array();
94
  foreach ( $meta as $id )
95
  {
96
+ // Get only info of existing attachments
97
+ if ( get_attached_file( $id ) )
98
+ {
99
+ $images[$id] = RWMB_Image_Field::file_info( $id, $args );
100
+ }
101
  }
102
  $meta = $images;
103
  }
104
  }
 
105
  // Get terms
106
  elseif ( 'taxonomy_advanced' == $args['type'] )
107
  {
108
  if ( ! empty( $args['taxonomy'] ) )
109
  {
110
  $term_ids = array_map( 'intval', array_filter( explode( ',', $meta . ',' ) ) );
 
111
  // Allow to pass more arguments to "get_terms"
112
  $func_args = wp_parse_args( array(
113
  'include' => $term_ids,
121
  $meta = array();
122
  }
123
  }
 
124
  // Get post terms
125
  elseif ( 'taxonomy' == $args['type'] )
126
  {
127
  $meta = empty( $args['taxonomy'] ) ? array() : wp_get_post_terms( $post_id, $args['taxonomy'] );
128
  }
 
129
  // Get map
130
  elseif ( 'map' == $args['type'] )
131
  {
132
+ $meta = RWMB_Map_Field::the_value( array( 'id' => $key, 'multiple' => false ), $args, $post_id );
133
  }
 
134
  return apply_filters( 'rwmb_meta', $meta, $key, $args, $post_id );
135
  }
136
+ }
137
+ }
138
 
139
+ if ( ! function_exists( 'rwmb_meta' ) )
140
+ {
141
+ /**
142
+ * Get post meta
143
+ *
144
+ * @param string $key Meta key. Required.
145
+ * @param int|null $post_id Post ID. null for current post. Optional
146
+ * @param array $args Array of arguments. Optional.
147
+ *
148
+ * @return mixed
149
+ */
150
+ function rwmb_meta( $key, $args = array(), $post_id = null )
151
+ {
152
+ return RWMB_Helper::meta( $key, $args, $post_id );
153
+ }
154
+ }
155
 
156
+ if ( ! function_exists( 'rwmb_get_field' ) )
157
+ {
158
+ /**
159
+ * Get value of custom field.
160
+ * This is used to replace old version of rwmb_meta key.
161
+ *
162
+ * @param string $field_id Field ID. Required.
163
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
164
+ * @param int|null $post_id Post ID. null for current post. Optional.
165
+ *
166
+ * @return mixed false if field doesn't exist. Field value otherwise.
167
+ */
168
+ function rwmb_get_field( $field_id, $args = array(), $post_id = null )
169
+ {
170
+ $field = RWMB_Helper::find_field( $field_id );
171
+
172
+ // Get field value
173
+ $value = $field ? call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'get_value' ), $field, $args, $post_id ) : false;
174
 
175
  /**
176
+ * Allow developers to change the returned value of field
177
  *
178
+ * @param mixed $value Field value
179
+ * @param array $field Field parameter
180
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
181
+ * @param int|null $post_id Post ID. null for current post. Optional.
182
  */
183
+ $value = apply_filters( 'rwmb_get_field', $value, $field, $args, $post_id );
 
 
 
 
184
 
185
+ return $value;
186
+ }
187
+ }
188
 
189
+ if ( ! function_exists( 'rwmb_the_field' ) )
190
+ {
191
+ /**
192
+ * Display the value of a field
193
+ *
194
+ * @param string $field_id Field ID. Required.
195
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
196
+ * @param int|null $post_id Post ID. null for current post. Optional.
197
+ * @param bool $echo Display field meta value? Default `true` which works in almost all cases. We use `false` for the [rwmb_meta] shortcode
198
+ *
199
+ * @return string
200
+ */
201
+ function rwmb_the_field( $field_id, $args = array(), $post_id = null, $echo = true )
202
+ {
203
+ // Find field
204
+ $field = RWMB_Helper::find_field( $field_id );
205
 
206
+ if ( ! $field )
207
+ return '';
208
+
209
+ $output = call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'the_value' ), $field, $args, $post_id );
 
 
 
 
 
 
 
 
 
 
210
 
211
  /**
212
+ * Allow developers to change the returned value of field
 
 
 
 
213
  *
214
+ * @param mixed $value Field HTML output
215
+ * @param array $field Field parameter
216
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
217
+ * @param int|null $post_id Post ID. null for current post. Optional.
218
  */
219
+ $output = apply_filters( 'rwmb_the_field', $output, $field, $args, $post_id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
 
221
+ if ( $echo )
222
+ echo $output;
 
 
 
 
 
 
 
223
 
224
+ return $output;
225
+ }
226
+ }
 
 
 
 
 
 
 
 
 
 
 
 
227
 
228
+ if ( ! function_exists( 'rwmb_meta_shortcode' ) )
229
+ {
230
+ /**
231
+ * Shortcode to display meta value
232
+ *
233
+ * @param $atts Array of shortcode attributes, same as meta() function, but has more "meta_key" parameter
234
+ *
235
+ * @see meta() function below
236
+ *
237
+ * @return string
238
+ */
239
+ function rwmb_meta_shortcode( $atts )
240
+ {
241
+ $atts = wp_parse_args( $atts, array(
242
+ 'post_id' => get_the_ID(),
243
+ ) );
244
+ if ( empty( $atts['meta_key'] ) )
245
+ return '';
246
 
247
+ $field_id = $atts['meta_key'];
248
+ $post_id = $atts['post_id'];
249
+ unset( $atts['meta_key'], $atts['post_id'] );
250
 
251
+ return rwmb_the_field( $field_id, $atts, $post_id, false );
 
252
  }
253
 
254
+ add_shortcode( 'rwmb_meta', 'rwmb_meta_shortcode' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
  }
inc/init.php CHANGED
@@ -14,6 +14,11 @@ add_action( 'admin_init', 'rwmb_register_meta_boxes' );
14
  function rwmb_register_meta_boxes()
15
  {
16
  $meta_boxes = apply_filters( 'rwmb_meta_boxes', array() );
 
 
 
 
 
17
  foreach ( $meta_boxes as $meta_box )
18
  {
19
  new RW_Meta_Box( $meta_box );
14
  function rwmb_register_meta_boxes()
15
  {
16
  $meta_boxes = apply_filters( 'rwmb_meta_boxes', array() );
17
+
18
+ // Prevent errors showing if invalid value is returned from the filter above
19
+ if ( empty( $meta_boxes ) || ! is_array( $meta_boxes ) )
20
+ return;
21
+
22
  foreach ( $meta_boxes as $meta_box )
23
  {
24
  new RW_Meta_Box( $meta_box );
inc/meta-box.php CHANGED
@@ -302,9 +302,10 @@ if ( ! class_exists( 'RW_Meta_Box' ) )
302
 
303
  foreach ( $this->fields as $field )
304
  {
305
- $name = $field['id'];
306
- $old = get_post_meta( $post_id, $name, ! $field['multiple'] );
307
- $new = isset( $_POST[$name] ) ? $_POST[$name] : ( $field['multiple'] ? array() : '' );
 
308
 
309
  // Allow field class change the value
310
  $new = call_user_func( array( self::get_class_name( $field ), 'value' ), $new, $old, $post_id, $field );
@@ -382,7 +383,7 @@ if ( ! class_exists( 'RW_Meta_Box' ) )
382
  */
383
  static function normalize_fields( $fields )
384
  {
385
- foreach ( $fields as &$field )
386
  {
387
  $field = wp_parse_args( $field, array(
388
  'id' => '',
@@ -398,8 +399,17 @@ if ( ! class_exists( 'RW_Meta_Box' ) )
398
  'placeholder' => '',
399
  ) );
400
 
 
 
 
 
 
 
 
 
 
401
  // Allow field class add/change default field values
402
- $field = call_user_func( array( self::get_class_name( $field ), 'normalize_field' ), $field );
403
 
404
  if ( isset( $field['fields'] ) )
405
  $field['fields'] = self::normalize_fields( $field['fields'] );
@@ -408,6 +418,8 @@ if ( ! class_exists( 'RW_Meta_Box' ) )
408
  $field = apply_filters( 'rwmb_normalize_field', $field );
409
  $field = apply_filters( "rwmb_normalize_{$field['type']}_field", $field );
410
  $field = apply_filters( "rwmb_normalize_{$field['id']}_field", $field );
 
 
411
  }
412
 
413
  return $fields;
302
 
303
  foreach ( $this->fields as $field )
304
  {
305
+ $name = $field['id'];
306
+ $single = $field['clone'] || ! $field['multiple'];
307
+ $old = get_post_meta( $post_id, $name, $single );
308
+ $new = isset( $_POST[$name] ) ? $_POST[$name] : ( $single ? '' : array() );
309
 
310
  // Allow field class change the value
311
  $new = call_user_func( array( self::get_class_name( $field ), 'value' ), $new, $old, $post_id, $field );
383
  */
384
  static function normalize_fields( $fields )
385
  {
386
+ foreach ( $fields as $k => $field )
387
  {
388
  $field = wp_parse_args( $field, array(
389
  'id' => '',
399
  'placeholder' => '',
400
  ) );
401
 
402
+ $class = self::get_class_name( $field );
403
+
404
+ // Make sure field has correct 'type', ignore warning error when users forget to set field type or set incorrect one
405
+ if ( false === $class )
406
+ {
407
+ unset( $fields[$k] );
408
+ continue;
409
+ }
410
+
411
  // Allow field class add/change default field values
412
+ $field = call_user_func( array( $class, 'normalize_field' ), $field );
413
 
414
  if ( isset( $field['fields'] ) )
415
  $field['fields'] = self::normalize_fields( $field['fields'] );
418
  $field = apply_filters( 'rwmb_normalize_field', $field );
419
  $field = apply_filters( "rwmb_normalize_{$field['type']}_field", $field );
420
  $field = apply_filters( "rwmb_normalize_{$field['id']}_field", $field );
421
+
422
+ $fields[$k] = $field;
423
  }
424
 
425
  return $fields;
js/autocomplete.js CHANGED
@@ -36,7 +36,7 @@ jQuery( function ( $ )
36
  {
37
  $result.append(
38
  '<div class="rwmb-autocomplete-result">' +
39
- '<div class="label">' + ui.item.label + '</div>' +
40
  '<div class="actions">' + RWMB_Autocomplete.delete + '</div>' +
41
  '<input type="hidden" class="rwmb-autocomplete-value" name="' + name + '" value="' + ui.item.value + '">' +
42
  '</div>'
36
  {
37
  $result.append(
38
  '<div class="rwmb-autocomplete-result">' +
39
+ '<div class="label">' + ( typeof ui.item.excerpt !== 'undefined' ? ui.item.excerpt : ui.item.label ) + '</div>' +
40
  '<div class="actions">' + RWMB_Autocomplete.delete + '</div>' +
41
  '<input type="hidden" class="rwmb-autocomplete-value" name="' + name + '" value="' + ui.item.value + '">' +
42
  '</div>'
js/clone.js CHANGED
@@ -9,7 +9,7 @@ jQuery( function ( $ )
9
  */
10
  function clone( $container )
11
  {
12
- var $clone_last = $container.find( '.rwmb-clone:last' ),
13
  $clone = $clone_last.clone(),
14
  $input;
15
 
@@ -216,13 +216,13 @@ jQuery( function ( $ )
216
 
217
 
218
  // Add more clones
219
- $( '.add-clone' ).on( 'click', function ( e )
220
  {
221
  e.preventDefault();
222
 
223
- var $input = $( this ).parents( '.rwmb-input' );
224
 
225
- if ( $( this ).parents( '.rwmb-field' ).hasClass( 'rwmb-wysiwyg-wrapper' ) )
226
  {
227
  cloneWYSIWYG( $input );
228
  }
@@ -240,7 +240,7 @@ jQuery( function ( $ )
240
  e.preventDefault();
241
 
242
  var $this = $( this ),
243
- $input = $this.parents( '.rwmb-input' );
244
 
245
  // Remove clone only if there're 2 or more of them
246
  if ( $input.find( '.rwmb-clone' ).length <= 1 )
9
  */
10
  function clone( $container )
11
  {
12
+ var $clone_last = $container.children( '.rwmb-clone:last' ),
13
  $clone = $clone_last.clone(),
14
  $input;
15
 
216
 
217
 
218
  // Add more clones
219
+ $( '#poststuff' ).on( 'click', '.add-clone', function ( e )
220
  {
221
  e.preventDefault();
222
 
223
+ var $input = $( this ).closest( '.rwmb-input' );
224
 
225
+ if ( $( this ).closest( '.rwmb-field' ).hasClass( 'rwmb-wysiwyg-wrapper' ) )
226
  {
227
  cloneWYSIWYG( $input );
228
  }
240
  e.preventDefault();
241
 
242
  var $this = $( this ),
243
+ $input = $this.closest( '.rwmb-input' );
244
 
245
  // Remove clone only if there're 2 or more of them
246
  if ( $input.find( '.rwmb-clone' ).length <= 1 )
js/datetime.js CHANGED
@@ -6,7 +6,7 @@ jQuery( function ( $ )
6
  * Update datetime picker element
7
  * Used for static & dynamic added elements (when clone)
8
  */
9
- function rwmb_update_datetime_picker()
10
  {
11
  var $this = $( this ),
12
  options = $this.data( 'options' );
@@ -16,6 +16,16 @@ jQuery( function ( $ )
16
 
17
  }
18
 
19
- $( ':input.rwmb-datetime' ).each( rwmb_update_datetime_picker );
20
- $( '.rwmb-input' ).on( 'clone', ':input.rwmb-datetime', rwmb_update_datetime_picker );
 
 
 
 
 
 
 
 
 
 
21
  } );
6
  * Update datetime picker element
7
  * Used for static & dynamic added elements (when clone)
8
  */
9
+ function update()
10
  {
11
  var $this = $( this ),
12
  options = $this.data( 'options' );
16
 
17
  }
18
 
19
+ // Set language if available
20
+ if ( $.timepicker.regional.hasOwnProperty( RWMB_Datetimepicker.locale ) )
21
+ {
22
+ $.timepicker.setDefaults( $.timepicker.regional[RWMB_Datetimepicker.locale] );
23
+ }
24
+ else if ( $.timepicker.regional.hasOwnProperty( RWMB_Datetimepicker.localeShort ) )
25
+ {
26
+ $.timepicker.setDefaults( $.timepicker.regional[RWMB_Datetimepicker.localeShort] );
27
+ }
28
+
29
+ $( ':input.rwmb-datetime' ).each( update );
30
+ $( '.rwmb-input' ).on( 'clone', ':input.rwmb-datetime', update );
31
  } );
js/jqueryui/jquery-ui-timepicker-addon-i18n.min.js ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ /*! jQuery Timepicker Addon - v1.5.0 - 2014-09-01
2
+ * http://trentrichardson.com/examples/timepicker
3
+ * Copyright (c) 2014 Trent Richardson; Licensed MIT */
4
+ (function(e){e.timepicker.regional.af={timeOnlyTitle:"Kies Tyd",timeText:"Tyd ",hourText:"Ure ",minuteText:"Minute",secondText:"Sekondes",millisecText:"Millisekondes",microsecText:"Mikrosekondes",timezoneText:"Tydsone",currentText:"Huidige Tyd",closeText:"Klaar",timeFormat:"HH:mm",amNames:["AM","A"],pmNames:["PM","P"],isRTL:!1},e.timepicker.regional.am={timeOnlyTitle:"Ընտրեք ժամանակը",timeText:"Ժամանակը",hourText:"Ժամ",minuteText:"Րոպե",secondText:"Վարկյան",millisecText:"Միլիվարկյան",microsecText:"Միկրովարկյան",timezoneText:"Ժամային գոտին",currentText:"Այժմ",closeText:"Փակել",timeFormat:"HH:mm",amNames:["AM","A"],pmNames:["PM","P"],isRTL:!1},e.timepicker.regional.bg={timeOnlyTitle:"Изберете време",timeText:"Време",hourText:"Час",minuteText:"Минути",secondText:"Секунди",millisecText:"Милисекунди",microsecText:"Микросекунди",timezoneText:"Часови пояс",currentText:"Сега",closeText:"Затвори",timeFormat:"HH:mm",amNames:["AM","A"],pmNames:["PM","P"],isRTL:!1},e.timepicker.regional.ca={timeOnlyTitle:"Escollir una hora",timeText:"Hora",hourText:"Hores",minuteText:"Minuts",secondText:"Segons",millisecText:"Milisegons",microsecText:"Microsegons",timezoneText:"Fus horari",currentText:"Ara",closeText:"Tancar",timeFormat:"HH:mm",amNames:["AM","A"],pmNames:["PM","P"],isRTL:!1},e.timepicker.regional.cs={timeOnlyTitle:"Vyberte čas",timeText:"Čas",hourText:"Hodiny",minuteText:"Minuty",secondText:"Vteřiny",millisecText:"Milisekundy",microsecText:"Mikrosekundy",timezoneText:"Časové pásmo",currentText:"Nyní",closeText:"Zavřít",timeFormat:"HH:mm",amNames:["dop.","AM","A"],pmNames:["odp.","PM","P"],isRTL:!1},e.timepicker.regional.da={timeOnlyTitle:"Vælg tid",timeText:"Tid",hourText:"Time",minuteText:"Minut",secondText:"Sekund",millisecText:"Millisekund",microsecText:"Mikrosekund",timezoneText:"Tidszone",currentText:"Nu",closeText:"Luk",timeFormat:"HH:mm",amNames:["am","AM","A"],pmNames:["pm","PM","P"],isRTL:!1},e.timepicker.regional.de={timeOnlyTitle:"Zeit wählen",timeText:"Zeit",hourText:"Stunde",minuteText:"Minute",secondText:"Sekunde",millisecText:"Millisekunde",microsecText:"Mikrosekunde",timezoneText:"Zeitzone",currentText:"Jetzt",closeText:"Fertig",timeFormat:"HH:mm",amNames:["vorm.","AM","A"],pmNames:["nachm.","PM","P"],isRTL:!1},e.timepicker.regional.el={timeOnlyTitle:"Επιλογή ώρας",timeText:"Ώρα",hourText:"Ώρες",minuteText:"Λεπτά",secondText:"Δευτερόλεπτα",millisecText:"μιλιδευτερόλεπτο",microsecText:"Microseconds",timezoneText:"Ζώνη ώρας",currentText:"Τώρα",closeText:"Κλείσιμο",timeFormat:"HH:mm",amNames:["π.μ.","AM","A"],pmNames:["μ.μ.","PM","P"],isRTL:!1},e.timepicker.regional.es={timeOnlyTitle:"Elegir una hora",timeText:"Hora",hourText:"Horas",minuteText:"Minutos",secondText:"Segundos",millisecText:"Milisegundos",microsecText:"Microsegundos",timezoneText:"Uso horario",currentText:"Hoy",closeText:"Cerrar",timeFormat:"HH:mm",amNames:["a.m.","AM","A"],pmNames:["p.m.","PM","P"],isRTL:!1},e.timepicker.regional.et={timeOnlyTitle:"Vali aeg",timeText:"Aeg",hourText:"Tund",minuteText:"Minut",secondText:"Sekund",millisecText:"Millisekundis",microsecText:"Mikrosekundis",timezoneText:"Ajavöönd",currentText:"Praegu",closeText:"Valmis",timeFormat:"HH:mm",amNames:["AM","A"],pmNames:["PM","P"],isRTL:!1},e.timepicker.regional.eu={timeOnlyTitle:"Aukeratu ordua",timeText:"Ordua",hourText:"Orduak",minuteText:"Minutuak",secondText:"Segundoak",millisecText:"Milisegundoak",microsecText:"Mikrosegundoak",timezoneText:"Ordu-eremua",currentText:"Orain",closeText:"Itxi",timeFormat:"HH:mm",amNames:["a.m.","AM","A"],pmNames:["p.m.","PM","P"],isRTL:!1},e.timepicker.regional.fi={timeOnlyTitle:"Valitse aika",timeText:"Aika",hourText:"Tunti",minuteText:"Minuutti",secondText:"Sekunti",millisecText:"Millisekunnin",microsecText:"Mikrosekuntia",timezoneText:"Aikavyöhyke",currentText:"Nyt",closeText:"Sulje",timeFormat:"HH:mm",amNames:["ap.","AM","A"],pmNames:["ip.","PM","P"],isRTL:!1},e.timepicker.regional.fr={timeOnlyTitle:"Choisir une heure",timeText:"Heure",hourText:"Heures",minuteText:"Minutes",secondText:"Secondes",millisecText:"Millisecondes",microsecText:"Microsecondes",timezoneText:"Fuseau horaire",currentText:"Maintenant",closeText:"Terminé",timeFormat:"HH:mm",amNames:["AM","A"],pmNames:["PM","P"],isRTL:!1},e.timepicker.regional.gl={timeOnlyTitle:"Elixir unha hora",timeText:"Hora",hourText:"Horas",minuteText:"Minutos",secondText:"Segundos",millisecText:"Milisegundos",microsecText:"Microssegundos",timezoneText:"Fuso horario",currentText:"Agora",closeText:"Pechar",timeFormat:"HH:mm",amNames:["a.m.","AM","A"],pmNames:["p.m.","PM","P"],isRTL:!1},e.timepicker.regional.he={timeOnlyTitle:"בחירת זמן",timeText:"שעה",hourText:"שעות",minuteText:"דקות",secondText:"שניות",millisecText:"אלפית השנייה",microsecText:"מיקרו",timezoneText:"אזור זמן",currentText:"עכשיו",closeText:"סגור",timeFormat:"HH:mm",amNames:['לפנה"צ',"AM","A"],pmNames:['אחה"צ',"PM","P"],isRTL:!0},e.timepicker.regional.hr={timeOnlyTitle:"Odaberi vrijeme",timeText:"Vrijeme",hourText:"Sati",minuteText:"Minute",secondText:"Sekunde",millisecText:"Milisekunde",microsecText:"Mikrosekunde",timezoneText:"Vremenska zona",currentText:"Sada",closeText:"Gotovo",timeFormat:"HH:mm",amNames:["a.m.","AM","A"],pmNames:["p.m.","PM","P"],isRTL:!1},e.timepicker.regional.hu={timeOnlyTitle:"Válasszon időpontot",timeText:"Idő",hourText:"Óra",minuteText:"Perc",secondText:"Másodperc",millisecText:"Milliszekundumos",microsecText:"Ezredmásodperc",timezoneText:"Időzóna",currentText:"Most",closeText:"Kész",timeFormat:"HH:mm",amNames:["de.","AM","A"],pmNames:["du.","PM","P"],isRTL:!1},e.timepicker.regional.id={timeOnlyTitle:"Pilih Waktu",timeText:"Waktu",hourText:"Pukul",minuteText:"Menit",secondText:"Detik",millisecText:"Milidetik",microsecText:"Mikrodetik",timezoneText:"Zona Waktu",currentText:"Sekarang",closeText:"OK",timeFormat:"HH:mm",amNames:["AM","A"],pmNames:["PM","P"],isRTL:!1},e.timepicker.regional.it={timeOnlyTitle:"Scegli orario",timeText:"Orario",hourText:"Ora",minuteText:"Minuti",secondText:"Secondi",millisecText:"Millisecondi",microsecText:"Microsecondi",timezoneText:"Fuso orario",currentText:"Adesso",closeText:"Chiudi",timeFormat:"HH:mm",amNames:["m.","AM","A"],pmNames:["p.","PM","P"],isRTL:!1},e.timepicker.regional.ja={timeOnlyTitle:"時間を選択",timeText:"時間",hourText:"時",minuteText:"分",secondText:"秒",millisecText:"ミリ秒",microsecText:"マイクロ秒",timezoneText:"タイムゾーン",currentText:"現時刻",closeText:"閉じる",timeFormat:"HH:mm",amNames:["午前","AM","A"],pmNames:["午後","PM","P"],isRTL:!1},e.timepicker.regional.ko={timeOnlyTitle:"시간 선택",timeText:"시간",hourText:"시",minuteText:"분",secondText:"초",millisecText:"밀리초",microsecText:"마이크로",timezoneText:"표준 시간대",currentText:"현재 시각",closeText:"닫기",timeFormat:"tt h:mm",amNames:["오전","AM","A"],pmNames:["오후","PM","P"],isRTL:!1},e.timepicker.regional.lt={timeOnlyTitle:"Pasirinkite laiką",timeText:"Laikas",hourText:"Valandos",minuteText:"Minutės",secondText:"Sekundės",millisecText:"Milisekundės",microsecText:"Mikrosekundės",timezoneText:"Laiko zona",currentText:"Dabar",closeText:"Uždaryti",timeFormat:"HH:mm",amNames:["priešpiet","AM","A"],pmNames:["popiet","PM","P"],isRTL:!1},e.timepicker.regional.nl={timeOnlyTitle:"Tijdstip",timeText:"Tijd",hourText:"Uur",minuteText:"Minuut",secondText:"Seconde",millisecText:"Milliseconde",microsecText:"Microseconde",timezoneText:"Tijdzone",currentText:"Vandaag",closeText:"Sluiten",timeFormat:"HH:mm",amNames:["AM","A"],pmNames:["PM","P"],isRTL:!1},e.timepicker.regional.no={timeOnlyTitle:"Velg tid",timeText:"Tid",hourText:"Time",minuteText:"Minutt",secondText:"Sekund",millisecText:"Millisekund",microsecText:"mikrosekund",timezoneText:"Tidssone",currentText:"Nå",closeText:"Lukk",timeFormat:"HH:mm",amNames:["am","AM","A"],pmNames:["pm","PM","P"],isRTL:!1},e.timepicker.regional.pl={timeOnlyTitle:"Wybierz godzinę",timeText:"Czas",hourText:"Godzina",minuteText:"Minuta",secondText:"Sekunda",millisecText:"Milisekunda",microsecText:"Mikrosekunda",timezoneText:"Strefa czasowa",currentText:"Teraz",closeText:"Gotowe",timeFormat:"HH:mm",amNames:["AM","A"],pmNames:["PM","P"],isRTL:!1},e.timepicker.regional["pt-BR"]={timeOnlyTitle:"Escolha o horário",timeText:"Horário",hourText:"Hora",minuteText:"Minutos",secondText:"Segundos",millisecText:"Milissegundos",microsecText:"Microssegundos",timezoneText:"Fuso horário",currentText:"Agora",closeText:"Fechar",timeFormat:"HH:mm",amNames:["a.m.","AM","A"],pmNames:["p.m.","PM","P"],isRTL:!1},e.timepicker.regional.pt={timeOnlyTitle:"Escolha uma hora",timeText:"Hora",hourText:"Horas",minuteText:"Minutos",secondText:"Segundos",millisecText:"Milissegundos",microsecText:"Microssegundos",timezoneText:"Fuso horário",currentText:"Agora",closeText:"Fechar",timeFormat:"HH:mm",amNames:["a.m.","AM","A"],pmNames:["p.m.","PM","P"],isRTL:!1},e.timepicker.regional.ro={timeOnlyTitle:"Alegeţi o oră",timeText:"Timp",hourText:"Ore",minuteText:"Minute",secondText:"Secunde",millisecText:"Milisecunde",microsecText:"Microsecunde",timezoneText:"Fus orar",currentText:"Acum",closeText:"Închide",timeFormat:"HH:mm",amNames:["AM","A"],pmNames:["PM","P"],isRTL:!1},e.timepicker.regional.ru={timeOnlyTitle:"Выберите время",timeText:"Время",hourText:"Часы",minuteText:"Минуты",secondText:"Секунды",millisecText:"Миллисекунды",microsecText:"Микросекунды",timezoneText:"Часовой пояс",currentText:"Сейчас",closeText:"Закрыть",timeFormat:"HH:mm",amNames:["AM","A"],pmNames:["PM","P"],isRTL:!1},e.timepicker.regional.sk={timeOnlyTitle:"Zvoľte čas",timeText:"Čas",hourText:"Hodiny",minuteText:"Minúty",secondText:"Sekundy",millisecText:"Milisekundy",microsecText:"Mikrosekundy",timezoneText:"Časové pásmo",currentText:"Teraz",closeText:"Zavrieť",timeFormat:"H:m",amNames:["dop.","AM","A"],pmNames:["pop.","PM","P"],isRTL:!1},e.timepicker.regional.sl={timeOnlyTitle:"Izberite čas",timeText:"Čas",hourText:"Ura",minuteText:"Minute",secondText:"Sekunde",millisecText:"Milisekunde",microsecText:"Mikrosekunde",timezoneText:"Časovni pas",currentText:"Sedaj",closeText:"Zapri",timeFormat:"HH:mm",amNames:["dop.","AM","A"],pmNames:["pop.","PM","P"],isRTL:!1},e.timepicker.regional["sr-RS"]={timeOnlyTitle:"Одаберите време",timeText:"Време",hourText:"Сати",minuteText:"Минути",secondText:"Секунде",millisecText:"Милисекунде",microsecText:"Микросекунде",timezoneText:"Временска зона",currentText:"Сада",closeText:"Затвори",timeFormat:"HH:mm",amNames:["AM","A"],pmNames:["PM","P"],isRTL:!1},e.timepicker.regional["sr-YU"]={timeOnlyTitle:"Odaberite vreme",timeText:"Vreme",hourText:"Sati",minuteText:"Minuti",secondText:"Sekunde",millisecText:"Milisekunde",microsecText:"Mikrosekunde",timezoneText:"Vremenska zona",currentText:"Sada",closeText:"Zatvori",timeFormat:"HH:mm",amNames:["AM","A"],pmNames:["PM","P"],isRTL:!1},e.timepicker.regional.sv={timeOnlyTitle:"Välj en tid",timeText:"Tid",hourText:"Timme",minuteText:"Minut",secondText:"Sekund",millisecText:"Millisekund",microsecText:"Mikrosekund",timezoneText:"Tidszon",currentText:"Nu",closeText:"Stäng",timeFormat:"HH:mm",amNames:["AM","A"],pmNames:["PM","P"],isRTL:!1},e.timepicker.regional.th={timeOnlyTitle:"เลือกเวลา",timeText:"เวลา ",hourText:"ชั่วโมง ",minuteText:"นาที",secondText:"วินาที",millisecText:"มิลลิวินาที",microsecText:"ไมโคริวินาที",timezoneText:"เขตเวลา",currentText:"เวลาปัจจุบัน",closeText:"ปิด",timeFormat:"hh:mm tt"},e.timepicker.regional.tr={timeOnlyTitle:"Zaman Seçiniz",timeText:"Zaman",hourText:"Saat",minuteText:"Dakika",secondText:"Saniye",millisecText:"Milisaniye",microsecText:"Mikrosaniye",timezoneText:"Zaman Dilimi",currentText:"Şu an",closeText:"Tamam",timeFormat:"HH:mm",amNames:["ÖÖ","Ö"],pmNames:["ÖS","S"],isRTL:!1},e.timepicker.regional.uk={timeOnlyTitle:"Виберіть час",timeText:"Час",hourText:"Години",minuteText:"Хвилини",secondText:"Секунди",millisecText:"Мілісекунди",microsecText:"Мікросекунди",timezoneText:"Часовий пояс",currentText:"Зараз",closeText:"Закрити",timeFormat:"HH:mm",amNames:["AM","A"],pmNames:["PM","P"],isRTL:!1},e.timepicker.regional.vi={timeOnlyTitle:"Chọn giờ",timeText:"Thời gian",hourText:"Giờ",minuteText:"Phút",secondText:"Giây",millisecText:"Mili giây",microsecText:"Micrô giây",timezoneText:"Múi giờ",currentText:"Hiện thời",closeText:"Đóng",timeFormat:"HH:mm",amNames:["SA","S"],pmNames:["CH","C"],isRTL:!1},e.timepicker.regional["zh-CN"]={timeOnlyTitle:"选择时间",timeText:"时间",hourText:"小时",minuteText:"分钟",secondText:"秒钟",millisecText:"毫秒",microsecText:"微秒",timezoneText:"时区",currentText:"现在时间",closeText:"关闭",timeFormat:"HH:mm",amNames:["AM","A"],pmNames:["PM","P"],isRTL:!1},e.timepicker.regional["zh-TW"]={timeOnlyTitle:"選擇時分秒",timeText:"時間",hourText:"時",minuteText:"分",secondText:"秒",millisecText:"毫秒",microsecText:"微秒",timezoneText:"時區",currentText:"現在時間",closeText:"確定",timeFormat:"HH:mm",amNames:["上午","AM","A"],pmNames:["下午","PM","P"],isRTL:!1}})(jQuery);
js/jqueryui/jquery-ui-timepicker-addon.js DELETED
@@ -1,71 +0,0 @@
1
- /*
2
- * jQuery timepicker addon
3
- * By: Trent Richardson [http://trentrichardson.com]
4
- * Version 0.9.7
5
- * Last Modified: 10/02/2011
6
- *
7
- * Copyright 2011 Trent Richardson
8
- * Dual licensed under the MIT and GPL licenses.
9
- * http://trentrichardson.com/Impromptu/GPL-LICENSE.txt
10
- * http://trentrichardson.com/Impromptu/MIT-LICENSE.txt
11
- *
12
- * HERES THE CSS:
13
- * .ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }
14
- * .ui-timepicker-div dl { text-align: left; }
15
- * .ui-timepicker-div dl dt { height: 25px; }
16
- * .ui-timepicker-div dl dd { margin: -25px 10px 10px 65px; }
17
- * .ui-timepicker-div td { font-size: 90%; }
18
- * .ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; }
19
- */
20
-
21
- (function(e){function m(){this.regional=[];this.regional[""]={currentText:"Now",closeText:"Done",ampm:false,amNames:["AM","A"],pmNames:["PM","P"],timeFormat:"hh:mm tt",timeSuffix:"",timeOnlyTitle:"Choose Time",timeText:"Time",hourText:"Hour",minuteText:"Minute",secondText:"Second",millisecText:"Millisecond",timezoneText:"Time Zone"};this._defaults={showButtonPanel:true,timeOnly:false,showHour:true,showMinute:true,showSecond:false,showMillisec:false,showTimezone:false,showTime:true,stepHour:0.05,stepMinute:0.05,
22
- stepSecond:0.05,stepMillisec:0.5,hour:0,minute:0,second:0,millisec:0,timezone:"+0000",hourMin:0,minuteMin:0,secondMin:0,millisecMin:0,hourMax:23,minuteMax:59,secondMax:59,millisecMax:999,minDateTime:null,maxDateTime:null,onSelect:null,hourGrid:0,minuteGrid:0,secondGrid:0,millisecGrid:0,alwaysSetTime:true,separator:" ",altFieldTimeOnly:true,showTimepicker:true,timezoneIso8609:false,timezoneList:null};e.extend(this._defaults,this.regional[""])}e.extend(e.ui,{timepicker:{version:"0.9.7"}});e.extend(m.prototype,
23
- {$input:null,$altInput:null,$timeObj:null,inst:null,hour_slider:null,minute_slider:null,second_slider:null,millisec_slider:null,timezone_select:null,hour:0,minute:0,second:0,millisec:0,timezone:"+0000",hourMinOriginal:null,minuteMinOriginal:null,secondMinOriginal:null,millisecMinOriginal:null,hourMaxOriginal:null,minuteMaxOriginal:null,secondMaxOriginal:null,millisecMaxOriginal:null,ampm:"",formattedDate:"",formattedTime:"",formattedDateTime:"",timezoneList:null,setDefaults:function(c){var a=this._defaults,
24
- c=c||{};e.extend(a,c);for(var b in c)if(c[b]===null||c[b]===void 0)a[b]=c[b];return this},_newInst:function(c,a){var b=new m,d={},f;for(f in this._defaults){var g=c.attr("time:"+f);if(g)try{d[f]=eval(g)}catch(j){d[f]=g}}b._defaults=e.extend({},this._defaults,d,a,{beforeShow:function(c,d){e.isFunction(a.beforeShow)&&a.beforeShow(c,d,b)},onChangeMonthYear:function(d,f,g){b._updateDateTime(g);e.isFunction(a.onChangeMonthYear)&&a.onChangeMonthYear.call(c[0],d,f,g,b)},onClose:function(d,f){b.timeDefined===
25
- true&&c.val()!=""&&b._updateDateTime(f);e.isFunction(a.onClose)&&a.onClose.call(c[0],d,f,b)},timepicker:b});b.amNames=e.map(b._defaults.amNames,function(a){return a.toUpperCase()});b.pmNames=e.map(b._defaults.pmNames,function(a){return a.toUpperCase()});if(b._defaults.timezoneList===null){d=[];for(f=-11;f<=12;f++)d.push((f>=0?"+":"-")+("0"+Math.abs(f).toString()).slice(-2)+"00");b._defaults.timezoneIso8609&&(d=e.map(d,function(a){return a=="+0000"?"Z":a.substring(0,3)+":"+a.substring(3)}));b._defaults.timezoneList=
26
- d}b.hour=b._defaults.hour;b.minute=b._defaults.minute;b.second=b._defaults.second;b.millisec=b._defaults.millisec;b.ampm="";b.$input=c;if(a.altField)b.$altInput=e(a.altField).css({cursor:"pointer"}).focus(function(){c.trigger("focus")});if(b._defaults.minDate==0||b._defaults.minDateTime==0)b._defaults.minDate=new Date;if(b._defaults.maxDate==0||b._defaults.maxDateTime==0)b._defaults.maxDate=new Date;if(b._defaults.minDate!==void 0&&b._defaults.minDate instanceof Date)b._defaults.minDateTime=new Date(b._defaults.minDate.getTime());
27
- if(b._defaults.minDateTime!==void 0&&b._defaults.minDateTime instanceof Date)b._defaults.minDate=new Date(b._defaults.minDateTime.getTime());if(b._defaults.maxDate!==void 0&&b._defaults.maxDate instanceof Date)b._defaults.maxDateTime=new Date(b._defaults.maxDate.getTime());if(b._defaults.maxDateTime!==void 0&&b._defaults.maxDateTime instanceof Date)b._defaults.maxDate=new Date(b._defaults.maxDateTime.getTime());return b},_addTimePicker:function(c){this.timeDefined=this._parseTime(this.$altInput&&
28
- this._defaults.altFieldTimeOnly?this.$input.val()+" "+this.$altInput.val():this.$input.val());this._limitMinMaxDateTime(c,false);this._injectTimePicker()},_parseTime:function(c,a){var b=this._defaults.timeFormat.toString().replace(/h{1,2}/ig,"(\\d?\\d)").replace(/m{1,2}/ig,"(\\d?\\d)").replace(/s{1,2}/ig,"(\\d?\\d)").replace(/l{1}/ig,"(\\d?\\d?\\d)").replace(/t{1,2}/ig,this._getPatternAmpm()).replace(/z{1}/ig,"(z|[-+]\\d\\d:?\\d\\d)?").replace(/\s/g,"\\s?")+this._defaults.timeSuffix+"$",d=this._getFormatPositions(),
29
- f="";if(!this.inst)this.inst=e.datepicker._getInst(this.$input[0]);if(a||!this._defaults.timeOnly)b=".{"+e.datepicker._get(this.inst,"dateFormat").length+",}"+this._defaults.separator.replace(RegExp("[.*+?|()\\[\\]{}\\\\]","g"),"\\$&")+b;if(b=c.match(RegExp(b,"i"))){if(d.t!==-1)b[d.t]===void 0||b[d.t].length===0?this.ampm=f="":(f=e.inArray(b[d.t].toUpperCase(),this.amNames)!==-1?"AM":"PM",this.ampm=this._defaults[f=="AM"?"amNames":"pmNames"][0]);if(d.h!==-1)this.hour=f=="AM"&&b[d.h]=="12"?0:f=="PM"&&
30
- b[d.h]!="12"?(parseFloat(b[d.h])+12).toFixed(0):Number(b[d.h]);if(d.m!==-1)this.minute=Number(b[d.m]);if(d.s!==-1)this.second=Number(b[d.s]);if(d.l!==-1)this.millisec=Number(b[d.l]);if(d.z!==-1&&b[d.z]!==void 0){d=b[d.z].toUpperCase();switch(d.length){case 1:d=this._defaults.timezoneIso8609?"Z":"+0000";break;case 5:this._defaults.timezoneIso8609&&(d=d.substring(1)=="0000"?"Z":d.substring(0,3)+":"+d.substring(3));break;case 6:this._defaults.timezoneIso8609?d.substring(1)=="00:00"&&(d="Z"):d=d=="Z"||
31
- d.substring(1)=="00:00"?"+0000":d.replace(/:/,"")}this.timezone=d}return true}return false},_getPatternAmpm:function(){var c=[];o=this._defaults;o.amNames&&e.merge(c,o.amNames);o.pmNames&&e.merge(c,o.pmNames);c=e.map(c,function(a){return a.replace(/[.*+?|()\[\]{}\\]/g,"\\$&")});return"("+c.join("|")+")?"},_getFormatPositions:function(){var c=this._defaults.timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|t{1,2}|z)/g),a={h:-1,m:-1,s:-1,l:-1,t:-1,z:-1};if(c)for(var b=0;b<c.length;b++)a[c[b].toString().charAt(0)]==
32
- -1&&(a[c[b].toString().charAt(0)]=b+1);return a},_injectTimePicker:function(){var c=this.inst.dpDiv,a=this._defaults,b=this,d=(a.hourMax-(a.hourMax-a.hourMin)%a.stepHour).toFixed(0),f=(a.minuteMax-(a.minuteMax-a.minuteMin)%a.stepMinute).toFixed(0),g=(a.secondMax-(a.secondMax-a.secondMin)%a.stepSecond).toFixed(0),j=(a.millisecMax-(a.millisecMax-a.millisecMin)%a.stepMillisec).toFixed(0),h=this.inst.id.toString().replace(/([^A-Za-z0-9_])/g,"");if(c.find("div#ui-timepicker-div-"+h).length===0&&a.showTimepicker){var i=
33
- '<div class="ui-timepicker-div" id="ui-timepicker-div-'+h+'"><dl><dt class="ui_tpicker_time_label" id="ui_tpicker_time_label_'+h+'"'+(a.showTime?"":' style="display:none;"')+">"+a.timeText+'</dt><dd class="ui_tpicker_time" id="ui_tpicker_time_'+h+'"'+(a.showTime?"":' style="display:none;"')+'></dd><dt class="ui_tpicker_hour_label" id="ui_tpicker_hour_label_'+h+'"'+(a.showHour?"":' style="display:none;"')+">"+a.hourText+"</dt>",q=0,r=0,m=0,s=0,l;if(a.showHour&&a.hourGrid>0){i+='<dd class="ui_tpicker_hour"><div id="ui_tpicker_hour_'+
34
- h+'"'+(a.showHour?"":' style="display:none;"')+'></div><div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>';for(var k=a.hourMin;k<=d;k+=parseInt(a.hourGrid,10)){q++;var n=a.ampm&&k>12?k-12:k;n<10&&(n="0"+n);a.ampm&&(k==0?n="12a":n+=k<12?"a":"p");i+="<td>"+n+"</td>"}i+="</tr></table></div></dd>"}else i+='<dd class="ui_tpicker_hour" id="ui_tpicker_hour_'+h+'"'+(a.showHour?"":' style="display:none;"')+"></dd>";i+='<dt class="ui_tpicker_minute_label" id="ui_tpicker_minute_label_'+
35
- h+'"'+(a.showMinute?"":' style="display:none;"')+">"+a.minuteText+"</dt>";if(a.showMinute&&a.minuteGrid>0){i+='<dd class="ui_tpicker_minute ui_tpicker_minute_'+a.minuteGrid+'"><div id="ui_tpicker_minute_'+h+'"'+(a.showMinute?"":' style="display:none;"')+'></div><div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>';for(k=a.minuteMin;k<=f;k+=parseInt(a.minuteGrid,10))r++,i+="<td>"+(k<10?"0":"")+k+"</td>";i+="</tr></table></div></dd>"}else i+='<dd class="ui_tpicker_minute" id="ui_tpicker_minute_'+
36
- h+'"'+(a.showMinute?"":' style="display:none;"')+"></dd>";i+='<dt class="ui_tpicker_second_label" id="ui_tpicker_second_label_'+h+'"'+(a.showSecond?"":' style="display:none;"')+">"+a.secondText+"</dt>";if(a.showSecond&&a.secondGrid>0){i+='<dd class="ui_tpicker_second ui_tpicker_second_'+a.secondGrid+'"><div id="ui_tpicker_second_'+h+'"'+(a.showSecond?"":' style="display:none;"')+'></div><div style="padding-left: 1px"><table><tr>';for(var p=a.secondMin;p<=g;p+=parseInt(a.secondGrid,10))m++,i+="<td>"+
37
- (p<10?"0":"")+p+"</td>";i+="</tr></table></div></dd>"}else i+='<dd class="ui_tpicker_second" id="ui_tpicker_second_'+h+'"'+(a.showSecond?"":' style="display:none;"')+"></dd>";i+='<dt class="ui_tpicker_millisec_label" id="ui_tpicker_millisec_label_'+h+'"'+(a.showMillisec?"":' style="display:none;"')+">"+a.millisecText+"</dt>";if(a.showMillisec&&a.millisecGrid>0){i+='<dd class="ui_tpicker_millisec ui_tpicker_millisec_'+a.millisecGrid+'"><div id="ui_tpicker_millisec_'+h+'"'+(a.showMillisec?"":' style="display:none;"')+
38
- '></div><div style="padding-left: 1px"><table><tr>';for(k=a.millisecMin;k<=j;k+=parseInt(a.millisecGrid,10))s++,i+="<td>"+(k<10?"0":"")+p+"</td>";i+="</tr></table></div></dd>"}else i+='<dd class="ui_tpicker_millisec" id="ui_tpicker_millisec_'+h+'"'+(a.showMillisec?"":' style="display:none;"')+"></dd>";i+='<dt class="ui_tpicker_timezone_label" id="ui_tpicker_timezone_label_'+h+'"'+(a.showTimezone?"":' style="display:none;"')+">"+a.timezoneText+"</dt>";i+='<dd class="ui_tpicker_timezone" id="ui_tpicker_timezone_'+
39
- h+'"'+(a.showTimezone?"":' style="display:none;"')+"></dd>";i+="</dl></div>";$tp=e(i);a.timeOnly===true&&($tp.prepend('<div class="ui-widget-header ui-helper-clearfix ui-corner-all"><div class="ui-datepicker-title">'+a.timeOnlyTitle+"</div></div>"),c.find(".ui-datepicker-header, .ui-datepicker-calendar").hide());this.hour_slider=$tp.find("#ui_tpicker_hour_"+h).slider({orientation:"horizontal",value:this.hour,min:a.hourMin,max:d,step:a.stepHour,slide:function(a,c){b.hour_slider.slider("option","value",
40
- c.value);b._onTimeChange()}});this.minute_slider=$tp.find("#ui_tpicker_minute_"+h).slider({orientation:"horizontal",value:this.minute,min:a.minuteMin,max:f,step:a.stepMinute,slide:function(a,c){b.minute_slider.slider("option","value",c.value);b._onTimeChange()}});this.second_slider=$tp.find("#ui_tpicker_second_"+h).slider({orientation:"horizontal",value:this.second,min:a.secondMin,max:g,step:a.stepSecond,slide:function(a,c){b.second_slider.slider("option","value",c.value);b._onTimeChange()}});this.millisec_slider=
41
- $tp.find("#ui_tpicker_millisec_"+h).slider({orientation:"horizontal",value:this.millisec,min:a.millisecMin,max:j,step:a.stepMillisec,slide:function(a,c){b.millisec_slider.slider("option","value",c.value);b._onTimeChange()}});this.timezone_select=$tp.find("#ui_tpicker_timezone_"+h).append("<select></select>").find("select");e.fn.append.apply(this.timezone_select,e.map(a.timezoneList,function(a){return e("<option />").val(typeof a=="object"?a.value:a).text(typeof a=="object"?a.label:a)}));this.timezone_select.val(typeof this.timezone!=
42
- "undefined"&&this.timezone!=null&&this.timezone!=""?this.timezone:a.timezone);this.timezone_select.change(function(){b._onTimeChange()});a.showHour&&a.hourGrid>0&&(l=100*q*a.hourGrid/(d-a.hourMin),$tp.find(".ui_tpicker_hour table").css({width:l+"%",marginLeft:l/(-2*q)+"%",borderCollapse:"collapse"}).find("td").each(function(){e(this).click(function(){var c=e(this).html();if(a.ampm)var d=c.substring(2).toLowerCase(),c=parseInt(c.substring(0,2),10),c=d=="a"?c==12?0:c:c==12?12:c+12;b.hour_slider.slider("option",
43
- "value",c);b._onTimeChange();b._onSelectHandler()}).css({cursor:"pointer",width:100/q+"%",textAlign:"center",overflow:"hidden"})}));a.showMinute&&a.minuteGrid>0&&(l=100*r*a.minuteGrid/(f-a.minuteMin),$tp.find(".ui_tpicker_minute table").css({width:l+"%",marginLeft:l/(-2*r)+"%",borderCollapse:"collapse"}).find("td").each(function(){e(this).click(function(){b.minute_slider.slider("option","value",e(this).html());b._onTimeChange();b._onSelectHandler()}).css({cursor:"pointer",width:100/r+"%",textAlign:"center",
44
- overflow:"hidden"})}));a.showSecond&&a.secondGrid>0&&$tp.find(".ui_tpicker_second table").css({width:l+"%",marginLeft:l/(-2*m)+"%",borderCollapse:"collapse"}).find("td").each(function(){e(this).click(function(){b.second_slider.slider("option","value",e(this).html());b._onTimeChange();b._onSelectHandler()}).css({cursor:"pointer",width:100/m+"%",textAlign:"center",overflow:"hidden"})});a.showMillisec&&a.millisecGrid>0&&$tp.find(".ui_tpicker_millisec table").css({width:l+"%",marginLeft:l/(-2*s)+"%",
45
- borderCollapse:"collapse"}).find("td").each(function(){e(this).click(function(){b.millisec_slider.slider("option","value",e(this).html());b._onTimeChange();b._onSelectHandler()}).css({cursor:"pointer",width:100/s+"%",textAlign:"center",overflow:"hidden"})});d=c.find(".ui-datepicker-buttonpane");d.length?d.before($tp):c.append($tp);this.$timeObj=$tp.find("#ui_tpicker_time_"+h);if(this.inst!==null)c=this.timeDefined,this._onTimeChange(),this.timeDefined=c;c=function(){b._onSelectHandler()};this.hour_slider.bind("slidestop",
46
- c);this.minute_slider.bind("slidestop",c);this.second_slider.bind("slidestop",c);this.millisec_slider.bind("slidestop",c)}},_limitMinMaxDateTime:function(c,a){var b=this._defaults,d=new Date(c.selectedYear,c.selectedMonth,c.selectedDay);if(this._defaults.showTimepicker){if(e.datepicker._get(c,"minDateTime")!==null&&e.datepicker._get(c,"minDateTime")!==void 0&&d){var f=e.datepicker._get(c,"minDateTime"),g=new Date(f.getFullYear(),f.getMonth(),f.getDate(),0,0,0,0);if(this.hourMinOriginal===null||this.minuteMinOriginal===
47
- null||this.secondMinOriginal===null||this.millisecMinOriginal===null)this.hourMinOriginal=b.hourMin,this.minuteMinOriginal=b.minuteMin,this.secondMinOriginal=b.secondMin,this.millisecMinOriginal=b.millisecMin;if(c.settings.timeOnly||g.getTime()==d.getTime())if(this._defaults.hourMin=f.getHours(),this.hour<=this._defaults.hourMin)if(this.hour=this._defaults.hourMin,this._defaults.minuteMin=f.getMinutes(),this.minute<=this._defaults.minuteMin)this.minute=this._defaults.minuteMin,this._defaults.secondMin=
48
- f.getSeconds();else if(this.second<=this._defaults.secondMin)this.second=this._defaults.secondMin,this._defaults.millisecMin=f.getMilliseconds();else{if(this.millisec<this._defaults.millisecMin)this.millisec=this._defaults.millisecMin;this._defaults.millisecMin=this.millisecMinOriginal}else this._defaults.minuteMin=this.minuteMinOriginal,this._defaults.secondMin=this.secondMinOriginal,this._defaults.millisecMin=this.millisecMinOriginal;else this._defaults.hourMin=this.hourMinOriginal,this._defaults.minuteMin=
49
- this.minuteMinOriginal,this._defaults.secondMin=this.secondMinOriginal,this._defaults.millisecMin=this.millisecMinOriginal}if(e.datepicker._get(c,"maxDateTime")!==null&&e.datepicker._get(c,"maxDateTime")!==void 0&&d){f=e.datepicker._get(c,"maxDateTime");g=new Date(f.getFullYear(),f.getMonth(),f.getDate(),0,0,0,0);if(this.hourMaxOriginal===null||this.minuteMaxOriginal===null||this.secondMaxOriginal===null)this.hourMaxOriginal=b.hourMax,this.minuteMaxOriginal=b.minuteMax,this.secondMaxOriginal=b.secondMax,
50
- this.millisecMaxOriginal=b.millisecMax;if(c.settings.timeOnly||g.getTime()==d.getTime())if(this._defaults.hourMax=f.getHours(),this.hour>=this._defaults.hourMax)if(this.hour=this._defaults.hourMax,this._defaults.minuteMax=f.getMinutes(),this.minute>=this._defaults.minuteMax)this.minute=this._defaults.minuteMax,this._defaults.secondMax=f.getSeconds();else if(this.second>=this._defaults.secondMax)this.second=this._defaults.secondMax,this._defaults.millisecMax=f.getMilliseconds();else{if(this.millisec>
51
- this._defaults.millisecMax)this.millisec=this._defaults.millisecMax;this._defaults.millisecMax=this.millisecMaxOriginal}else this._defaults.minuteMax=this.minuteMaxOriginal,this._defaults.secondMax=this.secondMaxOriginal,this._defaults.millisecMax=this.millisecMaxOriginal;else this._defaults.hourMax=this.hourMaxOriginal,this._defaults.minuteMax=this.minuteMaxOriginal,this._defaults.secondMax=this.secondMaxOriginal,this._defaults.millisecMax=this.millisecMaxOriginal}a!==void 0&&a===true&&(b=(this._defaults.hourMax-
52
- (this._defaults.hourMax-this._defaults.hourMin)%this._defaults.stepHour).toFixed(0),d=(this._defaults.minuteMax-(this._defaults.minuteMax-this._defaults.minuteMin)%this._defaults.stepMinute).toFixed(0),f=(this._defaults.secondMax-(this._defaults.secondMax-this._defaults.secondMin)%this._defaults.stepSecond).toFixed(0),g=(this._defaults.millisecMax-(this._defaults.millisecMax-this._defaults.millisecMin)%this._defaults.stepMillisec).toFixed(0),this.hour_slider&&this.hour_slider.slider("option",{min:this._defaults.hourMin,
53
- max:b}).slider("value",this.hour),this.minute_slider&&this.minute_slider.slider("option",{min:this._defaults.minuteMin,max:d}).slider("value",this.minute),this.second_slider&&this.second_slider.slider("option",{min:this._defaults.secondMin,max:f}).slider("value",this.second),this.millisec_slider&&this.millisec_slider.slider("option",{min:this._defaults.millisecMin,max:g}).slider("value",this.millisec))}},_onTimeChange:function(){var c=this.hour_slider?this.hour_slider.slider("value"):false,a=this.minute_slider?
54
- this.minute_slider.slider("value"):false,b=this.second_slider?this.second_slider.slider("value"):false,d=this.millisec_slider?this.millisec_slider.slider("value"):false,f=this.timezone_select?this.timezone_select.val():false,g=this._defaults;typeof c=="object"&&(c=false);typeof a=="object"&&(a=false);typeof b=="object"&&(b=false);typeof d=="object"&&(d=false);typeof f=="object"&&(f=false);c!==false&&(c=parseInt(c,10));a!==false&&(a=parseInt(a,10));b!==false&&(b=parseInt(b,10));d!==false&&(d=parseInt(d,
55
- 10));var j=g[c<12?"amNames":"pmNames"][0],h=c!=this.hour||a!=this.minute||b!=this.second||d!=this.millisec||this.ampm.length>0&&c<12!=(e.inArray(this.ampm.toUpperCase(),this.amNames)!==-1)||f!=this.timezone;if(h){if(c!==false)this.hour=c;if(a!==false)this.minute=a;if(b!==false)this.second=b;if(d!==false)this.millisec=d;if(f!==false)this.timezone=f;if(!this.inst)this.inst=e.datepicker._getInst(this.$input[0]);this._limitMinMaxDateTime(this.inst,true)}if(g.ampm)this.ampm=j;this._formatTime();this.$timeObj&&
56
- this.$timeObj.text(this.formattedTime+g.timeSuffix);this.timeDefined=true;h&&this._updateDateTime()},_onSelectHandler:function(){var c=this._defaults.onSelect,a=this.$input?this.$input[0]:null;c&&a&&c.apply(a,[this.formattedDateTime,this])},_formatTime:function(c,a,b){if(b==void 0)b=this._defaults.ampm;var c=c||{hour:this.hour,minute:this.minute,second:this.second,millisec:this.millisec,ampm:this.ampm,timezone:this.timezone},d=(a||this._defaults.timeFormat).toString(),f=parseInt(c.hour,10);b&&(!e.inArray(c.ampm.toUpperCase(),
57
- this.amNames)!==-1&&(f%=12),f===0&&(f=12));d=d.replace(/(?:hh?|mm?|ss?|[tT]{1,2}|[lz])/g,function(a){switch(a.toLowerCase()){case "hh":return("0"+f).slice(-2);case "h":return f;case "mm":return("0"+c.minute).slice(-2);case "m":return c.minute;case "ss":return("0"+c.second).slice(-2);case "s":return c.second;case "l":return("00"+c.millisec).slice(-3);case "z":return c.timezone;case "t":case "tt":if(b){var d=c.ampm;a.length==1&&(d=d.charAt(0));return a.charAt(0)=="T"?d.toUpperCase():d.toLowerCase()}return""}});
58
- if(arguments.length)return d;else this.formattedTime=d},_updateDateTime:function(c){c=this.inst||c;dt=new Date(c.selectedYear,c.selectedMonth,c.selectedDay);dateFmt=e.datepicker._get(c,"dateFormat");formatCfg=e.datepicker._getFormatConfig(c);timeAvailable=dt!==null&&this.timeDefined;var a=this.formattedDate=e.datepicker.formatDate(dateFmt,dt===null?new Date:dt,formatCfg);if(!(c.lastVal!==void 0&&c.lastVal.length>0&&this.$input.val().length===0)){if(this._defaults.timeOnly===true)a=this.formattedTime;
59
- else if(this._defaults.timeOnly!==true&&(this._defaults.alwaysSetTime||timeAvailable))a+=this._defaults.separator+this.formattedTime+this._defaults.timeSuffix;this.formattedDateTime=a;this._defaults.showTimepicker?this.$altInput&&this._defaults.altFieldTimeOnly===true?(this.$altInput.val(this.formattedTime),this.$input.val(this.formattedDate)):(this.$altInput&&this.$altInput.val(a),this.$input.val(a)):this.$input.val(this.formattedDate);this.$input.trigger("change")}}});e.fn.extend({timepicker:function(c){var c=
60
- c||{},a=arguments;typeof c=="object"&&(a[0]=e.extend(c,{timeOnly:true}));return e(this).each(function(){e.fn.datetimepicker.apply(e(this),a)})},datetimepicker:function(c){var c=c||{},a=arguments;return typeof c=="string"?c=="getDate"?e.fn.datepicker.apply(e(this[0]),a):this.each(function(){var b=e(this);b.datepicker.apply(b,a)}):this.each(function(){var a=e(this);a.datepicker(e.timepicker._newInst(a,c)._defaults)})}});e.datepicker._base_selectDate=e.datepicker._selectDate;e.datepicker._selectDate=
61
- function(c,a){var b=this._getInst(e(c)[0]),d=this._get(b,"timepicker");d?(d._limitMinMaxDateTime(b,true),b.inline=b.stay_open=true,this._base_selectDate(c,a),b.inline=b.stay_open=false,this._notifyChange(b),this._updateDatepicker(b)):this._base_selectDate(c,a)};e.datepicker._base_updateDatepicker=e.datepicker._updateDatepicker;e.datepicker._updateDatepicker=function(c){var a=c.input[0];if(!e.datepicker._curInst||!(e.datepicker._curInst!=c&&e.datepicker._datepickerShowing&&e.datepicker._lastInput!=
62
- a))if(typeof c.stay_open!=="boolean"||c.stay_open===false)this._base_updateDatepicker(c),(a=this._get(c,"timepicker"))&&a._addTimePicker(c)};e.datepicker._base_doKeyPress=e.datepicker._doKeyPress;e.datepicker._doKeyPress=function(c){var a=e.datepicker._getInst(c.target),b=e.datepicker._get(a,"timepicker");if(b&&e.datepicker._get(a,"constrainInput")){var d=b._defaults.ampm,a=e.datepicker._possibleChars(e.datepicker._get(a,"dateFormat")),b=b._defaults.timeFormat.toString().replace(/[hms]/g,"").replace(/TT/g,
63
- d?"APM":"").replace(/Tt/g,d?"AaPpMm":"").replace(/tT/g,d?"AaPpMm":"").replace(/T/g,d?"AP":"").replace(/tt/g,d?"apm":"").replace(/t/g,d?"ap":"")+" "+b._defaults.separator+b._defaults.timeSuffix+(b._defaults.showTimezone?b._defaults.timezoneList.join(""):"")+b._defaults.amNames.join("")+b._defaults.pmNames.join("")+a,d=String.fromCharCode(c.charCode===void 0?c.keyCode:c.charCode);return c.ctrlKey||d<" "||!a||b.indexOf(d)>-1}return e.datepicker._base_doKeyPress(c)};e.datepicker._base_doKeyUp=e.datepicker._doKeyUp;
64
- e.datepicker._doKeyUp=function(c){var a=e.datepicker._getInst(c.target),b=e.datepicker._get(a,"timepicker");if(b&&b._defaults.timeOnly&&a.input.val()!=a.lastVal)try{e.datepicker._updateDatepicker(a)}catch(d){e.datepicker.log(d)}return e.datepicker._base_doKeyUp(c)};e.datepicker._base_gotoToday=e.datepicker._gotoToday;e.datepicker._gotoToday=function(c){var a=this._getInst(e(c)[0]),b=a.dpDiv;this._base_gotoToday(c);var c=new Date,d=this._get(a,"timepicker");if(d._defaults.showTimezone&&d.timezone_select){var f=
65
- c.getTimezoneOffset(),g=f>0?"-":"+",f=Math.abs(f),j=f%60,f=g+("0"+(f-j)/60).slice(-2)+("0"+j).slice(-2);d._defaults.timezoneIso8609&&(f=f.substring(0,3)+":"+f.substring(3));d.timezone_select.val(f)}this._setTime(a,c);e(".ui-datepicker-today",b).click()};e.datepicker._disableTimepickerDatepicker=function(c){var a=this._getInst(c),b=this._get(a,"timepicker");e(c).datepicker("getDate");if(b)b._defaults.showTimepicker=false,b._updateDateTime(a)};e.datepicker._enableTimepickerDatepicker=function(c){var a=
66
- this._getInst(c),b=this._get(a,"timepicker");e(c).datepicker("getDate");if(b)b._defaults.showTimepicker=true,b._addTimePicker(a),b._updateDateTime(a)};e.datepicker._setTime=function(c,a){var b=this._get(c,"timepicker");if(b){var d=b._defaults,e=a?a.getHours():d.hour,g=a?a.getMinutes():d.minute,j=a?a.getSeconds():d.second,h=a?a.getMilliseconds():d.millisec;if(e<d.hourMin||e>d.hourMax||g<d.minuteMin||g>d.minuteMax||j<d.secondMin||j>d.secondMax||h<d.millisecMin||h>d.millisecMax)e=d.hourMin,g=d.minuteMin,
67
- j=d.secondMin,h=d.millisecMin;b.hour=e;b.minute=g;b.second=j;b.millisec=h;b.hour_slider&&b.hour_slider.slider("value",e);b.minute_slider&&b.minute_slider.slider("value",g);b.second_slider&&b.second_slider.slider("value",j);b.millisec_slider&&b.millisec_slider.slider("value",h);b._onTimeChange();b._updateDateTime(c)}};e.datepicker._setTimeDatepicker=function(c,a,b){var c=this._getInst(c),d=this._get(c,"timepicker");d&&(this._setDateFromField(c),a&&(typeof a=="string"?(d._parseTime(a,b),a=new Date,
68
- a.setHours(d.hour,d.minute,d.second,d.millisec)):a=new Date(a.getTime()),a.toString()=="Invalid Date"&&(a=void 0),this._setTime(c,a)))};e.datepicker._base_setDateDatepicker=e.datepicker._setDateDatepicker;e.datepicker._setDateDatepicker=function(c,a){var b=this._getInst(c),d=a instanceof Date?new Date(a.getTime()):a;this._updateDatepicker(b);this._base_setDateDatepicker.apply(this,arguments);this._setTimeDatepicker(c,d,true)};e.datepicker._base_getDateDatepicker=e.datepicker._getDateDatepicker;e.datepicker._getDateDatepicker=
69
- function(c,a){var b=this._getInst(c),d=this._get(b,"timepicker");return d?(this._setDateFromField(b,a),(b=this._getDate(b))&&d._parseTime(e(c).val(),d.timeOnly)&&b.setHours(d.hour,d.minute,d.second,d.millisec),b):this._base_getDateDatepicker(c,a)};e.datepicker._base_parseDate=e.datepicker.parseDate;e.datepicker.parseDate=function(c,a,b){var d;try{d=this._base_parseDate(c,a,b)}catch(e){d=this._base_parseDate(c,a.substring(0,a.length-(e.length-e.indexOf(":")-2)),b)}return d};e.datepicker._base_formatDate=
70
- e.datepicker._formatDate;e.datepicker._formatDate=function(c,a,b,d){var e=this._get(c,"timepicker");return e?(a&&this._base_formatDate(c,a,b,d),e._updateDateTime(),e.$input.val()):this._base_formatDate(c)};e.datepicker._base_optionDatepicker=e.datepicker._optionDatepicker;e.datepicker._optionDatepicker=function(c,a,b){var d=this._get(this._getInst(c),"timepicker");if(d){var e,g,j;if(typeof a=="string")a==="minDate"||a==="minDateTime"?e=b:a==="maxDate"||a==="maxDateTime"?g=b:a==="onSelect"&&(j=b);
71
- else if(typeof a=="object")if(a.minDate)e=a.minDate;else if(a.minDateTime)e=a.minDateTime;else if(a.maxDate)g=a.maxDate;else if(a.maxDateTime)g=a.maxDateTime;if(e)e=e==0?new Date:new Date(e),d._defaults.minDate=e,d._defaults.minDateTime=e;else if(g)g=g==0?new Date:new Date(g),d._defaults.maxDate=g,d._defaults.maxDateTime=g;else if(j)d._defaults.onSelect=j}this._base_optionDatepicker(c,a,b)};e.timepicker=new m;e.timepicker.version="0.9.7"})(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/jquery-ui-timepicker-addon.min.js ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ /*! jQuery Timepicker Addon - v1.5.0 - 2014-09-01
2
+ * http://trentrichardson.com/examples/timepicker
3
+ * Copyright (c) 2014 Trent Richardson; Licensed MIT */
4
+ (function($){if($.ui.timepicker=$.ui.timepicker||{},!$.ui.timepicker.version){$.extend($.ui,{timepicker:{version:"1.5.0"}});var Timepicker=function(){this.regional=[],this.regional[""]={currentText:"Now",closeText:"Done",amNames:["AM","A"],pmNames:["PM","P"],timeFormat:"HH:mm",timeSuffix:"",timeOnlyTitle:"Choose Time",timeText:"Time",hourText:"Hour",minuteText:"Minute",secondText:"Second",millisecText:"Millisecond",microsecText:"Microsecond",timezoneText:"Time Zone",isRTL:!1},this._defaults={showButtonPanel:!0,timeOnly:!1,timeOnlyShowDate:!1,showHour:null,showMinute:null,showSecond:null,showMillisec:null,showMicrosec:null,showTimezone:null,showTime:!0,stepHour:1,stepMinute:1,stepSecond:1,stepMillisec:1,stepMicrosec:1,hour:0,minute:0,second:0,millisec:0,microsec:0,timezone:null,hourMin:0,minuteMin:0,secondMin:0,millisecMin:0,microsecMin:0,hourMax:23,minuteMax:59,secondMax:59,millisecMax:999,microsecMax:999,minDateTime:null,maxDateTime:null,maxTime:null,minTime:null,onSelect:null,hourGrid:0,minuteGrid:0,secondGrid:0,millisecGrid:0,microsecGrid:0,alwaysSetTime:!0,separator:" ",altFieldTimeOnly:!0,altTimeFormat:null,altSeparator:null,altTimeSuffix:null,altRedirectFocus:!0,pickerTimeFormat:null,pickerTimeSuffix:null,showTimepicker:!0,timezoneList:null,addSliderAccess:!1,sliderAccessArgs:null,controlType:"slider",defaultValue:null,parse:"strict"},$.extend(this._defaults,this.regional[""])};$.extend(Timepicker.prototype,{$input:null,$altInput:null,$timeObj:null,inst:null,hour_slider:null,minute_slider:null,second_slider:null,millisec_slider:null,microsec_slider:null,timezone_select:null,maxTime:null,minTime:null,hour:0,minute:0,second:0,millisec:0,microsec:0,timezone:null,hourMinOriginal:null,minuteMinOriginal:null,secondMinOriginal:null,millisecMinOriginal:null,microsecMinOriginal:null,hourMaxOriginal:null,minuteMaxOriginal:null,secondMaxOriginal:null,millisecMaxOriginal:null,microsecMaxOriginal:null,ampm:"",formattedDate:"",formattedTime:"",formattedDateTime:"",timezoneList:null,units:["hour","minute","second","millisec","microsec"],support:{},control:null,setDefaults:function(e){return extendRemove(this._defaults,e||{}),this},_newInst:function($input,opts){var tp_inst=new Timepicker,inlineSettings={},fns={},overrides,i;for(var attrName in this._defaults)if(this._defaults.hasOwnProperty(attrName)){var attrValue=$input.attr("time:"+attrName);if(attrValue)try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}overrides={beforeShow:function(e,t){return $.isFunction(tp_inst._defaults.evnts.beforeShow)?tp_inst._defaults.evnts.beforeShow.call($input[0],e,t,tp_inst):void 0},onChangeMonthYear:function(e,t,i){tp_inst._updateDateTime(i),$.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)&&tp_inst._defaults.evnts.onChangeMonthYear.call($input[0],e,t,i,tp_inst)},onClose:function(e,t){tp_inst.timeDefined===!0&&""!==$input.val()&&tp_inst._updateDateTime(t),$.isFunction(tp_inst._defaults.evnts.onClose)&&tp_inst._defaults.evnts.onClose.call($input[0],e,t,tp_inst)}};for(i in overrides)overrides.hasOwnProperty(i)&&(fns[i]=opts[i]||null);tp_inst._defaults=$.extend({},this._defaults,inlineSettings,opts,overrides,{evnts:fns,timepicker:tp_inst}),tp_inst.amNames=$.map(tp_inst._defaults.amNames,function(e){return e.toUpperCase()}),tp_inst.pmNames=$.map(tp_inst._defaults.pmNames,function(e){return e.toUpperCase()}),tp_inst.support=detectSupport(tp_inst._defaults.timeFormat+(tp_inst._defaults.pickerTimeFormat?tp_inst._defaults.pickerTimeFormat:"")+(tp_inst._defaults.altTimeFormat?tp_inst._defaults.altTimeFormat:"")),"string"==typeof tp_inst._defaults.controlType?("slider"===tp_inst._defaults.controlType&&$.ui.slider===void 0&&(tp_inst._defaults.controlType="select"),tp_inst.control=tp_inst._controls[tp_inst._defaults.controlType]):tp_inst.control=tp_inst._defaults.controlType;var timezoneList=[-720,-660,-600,-570,-540,-480,-420,-360,-300,-270,-240,-210,-180,-120,-60,0,60,120,180,210,240,270,300,330,345,360,390,420,480,525,540,570,600,630,660,690,720,765,780,840];null!==tp_inst._defaults.timezoneList&&(timezoneList=tp_inst._defaults.timezoneList);var tzl=timezoneList.length,tzi=0,tzv=null;if(tzl>0&&"object"!=typeof timezoneList[0])for(;tzl>tzi;tzi++)tzv=timezoneList[tzi],timezoneList[tzi]={value:tzv,label:$.timepicker.timezoneOffsetString(tzv,tp_inst.support.iso8601)};return tp_inst._defaults.timezoneList=timezoneList,tp_inst.timezone=null!==tp_inst._defaults.timezone?$.timepicker.timezoneOffsetNumber(tp_inst._defaults.timezone):-1*(new Date).getTimezoneOffset(),tp_inst.hour=tp_inst._defaults.hour<tp_inst._defaults.hourMin?tp_inst._defaults.hourMin:tp_inst._defaults.hour>tp_inst._defaults.hourMax?tp_inst._defaults.hourMax:tp_inst._defaults.hour,tp_inst.minute=tp_inst._defaults.minute<tp_inst._defaults.minuteMin?tp_inst._defaults.minuteMin:tp_inst._defaults.minute>tp_inst._defaults.minuteMax?tp_inst._defaults.minuteMax:tp_inst._defaults.minute,tp_inst.second=tp_inst._defaults.second<tp_inst._defaults.secondMin?tp_inst._defaults.secondMin:tp_inst._defaults.second>tp_inst._defaults.secondMax?tp_inst._defaults.secondMax:tp_inst._defaults.second,tp_inst.millisec=tp_inst._defaults.millisec<tp_inst._defaults.millisecMin?tp_inst._defaults.millisecMin:tp_inst._defaults.millisec>tp_inst._defaults.millisecMax?tp_inst._defaults.millisecMax:tp_inst._defaults.millisec,tp_inst.microsec=tp_inst._defaults.microsec<tp_inst._defaults.microsecMin?tp_inst._defaults.microsecMin:tp_inst._defaults.microsec>tp_inst._defaults.microsecMax?tp_inst._defaults.microsecMax:tp_inst._defaults.microsec,tp_inst.ampm="",tp_inst.$input=$input,tp_inst._defaults.altField&&(tp_inst.$altInput=$(tp_inst._defaults.altField),tp_inst._defaults.altRedirectFocus===!0&&tp_inst.$altInput.css({cursor:"pointer"}).focus(function(){$input.trigger("focus")})),(0===tp_inst._defaults.minDate||0===tp_inst._defaults.minDateTime)&&(tp_inst._defaults.minDate=new Date),(0===tp_inst._defaults.maxDate||0===tp_inst._defaults.maxDateTime)&&(tp_inst._defaults.maxDate=new Date),void 0!==tp_inst._defaults.minDate&&tp_inst._defaults.minDate instanceof Date&&(tp_inst._defaults.minDateTime=new Date(tp_inst._defaults.minDate.getTime())),void 0!==tp_inst._defaults.minDateTime&&tp_inst._defaults.minDateTime instanceof Date&&(tp_inst._defaults.minDate=new Date(tp_inst._defaults.minDateTime.getTime())),void 0!==tp_inst._defaults.maxDate&&tp_inst._defaults.maxDate instanceof Date&&(tp_inst._defaults.maxDateTime=new Date(tp_inst._defaults.maxDate.getTime())),void 0!==tp_inst._defaults.maxDateTime&&tp_inst._defaults.maxDateTime instanceof Date&&(tp_inst._defaults.maxDate=new Date(tp_inst._defaults.maxDateTime.getTime())),tp_inst.$input.bind("focus",function(){tp_inst._onFocus()}),tp_inst},_addTimePicker:function(e){var t=this.$altInput&&this._defaults.altFieldTimeOnly?this.$input.val()+" "+this.$altInput.val():this.$input.val();this.timeDefined=this._parseTime(t),this._limitMinMaxDateTime(e,!1),this._injectTimePicker()},_parseTime:function(e,t){if(this.inst||(this.inst=$.datepicker._getInst(this.$input[0])),t||!this._defaults.timeOnly){var i=$.datepicker._get(this.inst,"dateFormat");try{var s=parseDateTimeInternal(i,this._defaults.timeFormat,e,$.datepicker._getFormatConfig(this.inst),this._defaults);if(!s.timeObj)return!1;$.extend(this,s.timeObj)}catch(a){return $.timepicker.log("Error parsing the date/time string: "+a+"\ndate/time string = "+e+"\ntimeFormat = "+this._defaults.timeFormat+"\ndateFormat = "+i),!1}return!0}var n=$.datepicker.parseTime(this._defaults.timeFormat,e,this._defaults);return n?($.extend(this,n),!0):!1},_injectTimePicker:function(){var e=this.inst.dpDiv,t=this.inst.settings,i=this,s="",a="",n=null,r={},l={},o=null,c=0,u=0;if(0===e.find("div.ui-timepicker-div").length&&t.showTimepicker){var m=' style="display:none;"',d='<div class="ui-timepicker-div'+(t.isRTL?" ui-timepicker-rtl":"")+'"><dl>'+'<dt class="ui_tpicker_time_label"'+(t.showTime?"":m)+">"+t.timeText+"</dt>"+'<dd class="ui_tpicker_time"'+(t.showTime?"":m)+"></dd>";for(c=0,u=this.units.length;u>c;c++){if(s=this.units[c],a=s.substr(0,1).toUpperCase()+s.substr(1),n=null!==t["show"+a]?t["show"+a]:this.support[s],r[s]=parseInt(t[s+"Max"]-(t[s+"Max"]-t[s+"Min"])%t["step"+a],10),l[s]=0,d+='<dt class="ui_tpicker_'+s+'_label"'+(n?"":m)+">"+t[s+"Text"]+"</dt>"+'<dd class="ui_tpicker_'+s+'"><div class="ui_tpicker_'+s+'_slider"'+(n?"":m)+"></div>",n&&t[s+"Grid"]>0){if(d+='<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>',"hour"===s)for(var h=t[s+"Min"];r[s]>=h;h+=parseInt(t[s+"Grid"],10)){l[s]++;var p=$.datepicker.formatTime(this.support.ampm?"hht":"HH",{hour:h},t);d+='<td data-for="'+s+'">'+p+"</td>"}else for(var _=t[s+"Min"];r[s]>=_;_+=parseInt(t[s+"Grid"],10))l[s]++,d+='<td data-for="'+s+'">'+(10>_?"0":"")+_+"</td>";d+="</tr></table></div>"}d+="</dd>"}var f=null!==t.showTimezone?t.showTimezone:this.support.timezone;d+='<dt class="ui_tpicker_timezone_label"'+(f?"":m)+">"+t.timezoneText+"</dt>",d+='<dd class="ui_tpicker_timezone" '+(f?"":m)+"></dd>",d+="</dl></div>";var g=$(d);for(t.timeOnly===!0&&(g.prepend('<div class="ui-widget-header ui-helper-clearfix ui-corner-all"><div class="ui-datepicker-title">'+t.timeOnlyTitle+"</div>"+"</div>"),e.find(".ui-datepicker-header, .ui-datepicker-calendar").hide()),c=0,u=i.units.length;u>c;c++)s=i.units[c],a=s.substr(0,1).toUpperCase()+s.substr(1),n=null!==t["show"+a]?t["show"+a]:this.support[s],i[s+"_slider"]=i.control.create(i,g.find(".ui_tpicker_"+s+"_slider"),s,i[s],t[s+"Min"],r[s],t["step"+a]),n&&t[s+"Grid"]>0&&(o=100*l[s]*t[s+"Grid"]/(r[s]-t[s+"Min"]),g.find(".ui_tpicker_"+s+" table").css({width:o+"%",marginLeft:t.isRTL?"0":o/(-2*l[s])+"%",marginRight:t.isRTL?o/(-2*l[s])+"%":"0",borderCollapse:"collapse"}).find("td").click(function(){var e=$(this),t=e.html(),a=parseInt(t.replace(/[^0-9]/g),10),n=t.replace(/[^apm]/gi),r=e.data("for");"hour"===r&&(-1!==n.indexOf("p")&&12>a?a+=12:-1!==n.indexOf("a")&&12===a&&(a=0)),i.control.value(i,i[r+"_slider"],s,a),i._onTimeChange(),i._onSelectHandler()}).css({cursor:"pointer",width:100/l[s]+"%",textAlign:"center",overflow:"hidden"}));if(this.timezone_select=g.find(".ui_tpicker_timezone").append("<select></select>").find("select"),$.fn.append.apply(this.timezone_select,$.map(t.timezoneList,function(e){return $("<option />").val("object"==typeof e?e.value:e).text("object"==typeof e?e.label:e)})),this.timezone!==void 0&&null!==this.timezone&&""!==this.timezone){var M=-1*new Date(this.inst.selectedYear,this.inst.selectedMonth,this.inst.selectedDay,12).getTimezoneOffset();M===this.timezone?selectLocalTimezone(i):this.timezone_select.val(this.timezone)}else this.hour!==void 0&&null!==this.hour&&""!==this.hour?this.timezone_select.val(t.timezone):selectLocalTimezone(i);this.timezone_select.change(function(){i._onTimeChange(),i._onSelectHandler()});var v=e.find(".ui-datepicker-buttonpane");if(v.length?v.before(g):e.append(g),this.$timeObj=g.find(".ui_tpicker_time"),null!==this.inst){var k=this.timeDefined;this._onTimeChange(),this.timeDefined=k}if(this._defaults.addSliderAccess){var T=this._defaults.sliderAccessArgs,D=this._defaults.isRTL;T.isRTL=D,setTimeout(function(){if(0===g.find(".ui-slider-access").length){g.find(".ui-slider:visible").sliderAccess(T);var e=g.find(".ui-slider-access:eq(0)").outerWidth(!0);e&&g.find("table:visible").each(function(){var t=$(this),i=t.outerWidth(),s=(""+t.css(D?"marginRight":"marginLeft")).replace("%",""),a=i-e,n=s*a/i+"%",r={width:a,marginRight:0,marginLeft:0};r[D?"marginRight":"marginLeft"]=n,t.css(r)})}},10)}i._limitMinMaxDateTime(this.inst,!0)}},_limitMinMaxDateTime:function(e,t){var i=this._defaults,s=new Date(e.selectedYear,e.selectedMonth,e.selectedDay);if(this._defaults.showTimepicker){if(null!==$.datepicker._get(e,"minDateTime")&&void 0!==$.datepicker._get(e,"minDateTime")&&s){var a=$.datepicker._get(e,"minDateTime"),n=new Date(a.getFullYear(),a.getMonth(),a.getDate(),0,0,0,0);(null===this.hourMinOriginal||null===this.minuteMinOriginal||null===this.secondMinOriginal||null===this.millisecMinOriginal||null===this.microsecMinOriginal)&&(this.hourMinOriginal=i.hourMin,this.minuteMinOriginal=i.minuteMin,this.secondMinOriginal=i.secondMin,this.millisecMinOriginal=i.millisecMin,this.microsecMinOriginal=i.microsecMin),e.settings.timeOnly||n.getTime()===s.getTime()?(this._defaults.hourMin=a.getHours(),this.hour<=this._defaults.hourMin?(this.hour=this._defaults.hourMin,this._defaults.minuteMin=a.getMinutes(),this.minute<=this._defaults.minuteMin?(this.minute=this._defaults.minuteMin,this._defaults.secondMin=a.getSeconds(),this.second<=this._defaults.secondMin?(this.second=this._defaults.secondMin,this._defaults.millisecMin=a.getMilliseconds(),this.millisec<=this._defaults.millisecMin?(this.millisec=this._defaults.millisecMin,this._defaults.microsecMin=a.getMicroseconds()):(this.microsec<this._defaults.microsecMin&&(this.microsec=this._defaults.microsecMin),this._defaults.microsecMin=this.microsecMinOriginal)):(this._defaults.millisecMin=this.millisecMinOriginal,this._defaults.microsecMin=this.microsecMinOriginal)):(this._defaults.secondMin=this.secondMinOriginal,this._defaults.millisecMin=this.millisecMinOriginal,this._defaults.microsecMin=this.microsecMinOriginal)):(this._defaults.minuteMin=this.minuteMinOriginal,this._defaults.secondMin=this.secondMinOriginal,this._defaults.millisecMin=this.millisecMinOriginal,this._defaults.microsecMin=this.microsecMinOriginal)):(this._defaults.hourMin=this.hourMinOriginal,this._defaults.minuteMin=this.minuteMinOriginal,this._defaults.secondMin=this.secondMinOriginal,this._defaults.millisecMin=this.millisecMinOriginal,this._defaults.microsecMin=this.microsecMinOriginal)}if(null!==$.datepicker._get(e,"maxDateTime")&&void 0!==$.datepicker._get(e,"maxDateTime")&&s){var r=$.datepicker._get(e,"maxDateTime"),l=new Date(r.getFullYear(),r.getMonth(),r.getDate(),0,0,0,0);(null===this.hourMaxOriginal||null===this.minuteMaxOriginal||null===this.secondMaxOriginal||null===this.millisecMaxOriginal)&&(this.hourMaxOriginal=i.hourMax,this.minuteMaxOriginal=i.minuteMax,this.secondMaxOriginal=i.secondMax,this.millisecMaxOriginal=i.millisecMax,this.microsecMaxOriginal=i.microsecMax),e.settings.timeOnly||l.getTime()===s.getTime()?(this._defaults.hourMax=r.getHours(),this.hour>=this._defaults.hourMax?(this.hour=this._defaults.hourMax,this._defaults.minuteMax=r.getMinutes(),this.minute>=this._defaults.minuteMax?(this.minute=this._defaults.minuteMax,this._defaults.secondMax=r.getSeconds(),this.second>=this._defaults.secondMax?(this.second=this._defaults.secondMax,this._defaults.millisecMax=r.getMilliseconds(),this.millisec>=this._defaults.millisecMax?(this.millisec=this._defaults.millisecMax,this._defaults.microsecMax=r.getMicroseconds()):(this.microsec>this._defaults.microsecMax&&(this.microsec=this._defaults.microsecMax),this._defaults.microsecMax=this.microsecMaxOriginal)):(this._defaults.millisecMax=this.millisecMaxOriginal,this._defaults.microsecMax=this.microsecMaxOriginal)):(this._defaults.secondMax=this.secondMaxOriginal,this._defaults.millisecMax=this.millisecMaxOriginal,this._defaults.microsecMax=this.microsecMaxOriginal)):(this._defaults.minuteMax=this.minuteMaxOriginal,this._defaults.secondMax=this.secondMaxOriginal,this._defaults.millisecMax=this.millisecMaxOriginal,this._defaults.microsecMax=this.microsecMaxOriginal)):(this._defaults.hourMax=this.hourMaxOriginal,this._defaults.minuteMax=this.minuteMaxOriginal,this._defaults.secondMax=this.secondMaxOriginal,this._defaults.millisecMax=this.millisecMaxOriginal,this._defaults.microsecMax=this.microsecMaxOriginal)}if(null!==e.settings.minTime){var o=new Date("01/01/1970 "+e.settings.minTime);this.hour<o.getHours()?(this.hour=this._defaults.hourMin=o.getHours(),this.minute=this._defaults.minuteMin=o.getMinutes()):this.hour===o.getHours()&&this.minute<o.getMinutes()?this.minute=this._defaults.minuteMin=o.getMinutes():this._defaults.hourMin<o.getHours()?(this._defaults.hourMin=o.getHours(),this._defaults.minuteMin=o.getMinutes()):this._defaults.minuteMin=this._defaults.hourMin===o.getHours()===this.hour&&this._defaults.minuteMin<o.getMinutes()?o.getMinutes():0}if(null!==e.settings.maxTime){var c=new Date("01/01/1970 "+e.settings.maxTime);this.hour>c.getHours()?(this.hour=this._defaults.hourMax=c.getHours(),this.minute=this._defaults.minuteMax=c.getMinutes()):this.hour===c.getHours()&&this.minute>c.getMinutes()?this.minute=this._defaults.minuteMax=c.getMinutes():this._defaults.hourMax>c.getHours()?(this._defaults.hourMax=c.getHours(),this._defaults.minuteMax=c.getMinutes()):this._defaults.minuteMax=this._defaults.hourMax===c.getHours()===this.hour&&this._defaults.minuteMax>c.getMinutes()?c.getMinutes():59}if(void 0!==t&&t===!0){var u=parseInt(this._defaults.hourMax-(this._defaults.hourMax-this._defaults.hourMin)%this._defaults.stepHour,10),m=parseInt(this._defaults.minuteMax-(this._defaults.minuteMax-this._defaults.minuteMin)%this._defaults.stepMinute,10),d=parseInt(this._defaults.secondMax-(this._defaults.secondMax-this._defaults.secondMin)%this._defaults.stepSecond,10),h=parseInt(this._defaults.millisecMax-(this._defaults.millisecMax-this._defaults.millisecMin)%this._defaults.stepMillisec,10),p=parseInt(this._defaults.microsecMax-(this._defaults.microsecMax-this._defaults.microsecMin)%this._defaults.stepMicrosec,10);this.hour_slider&&(this.control.options(this,this.hour_slider,"hour",{min:this._defaults.hourMin,max:u,step:this._defaults.stepHour}),this.control.value(this,this.hour_slider,"hour",this.hour-this.hour%this._defaults.stepHour)),this.minute_slider&&(this.control.options(this,this.minute_slider,"minute",{min:this._defaults.minuteMin,max:m,step:this._defaults.stepMinute}),this.control.value(this,this.minute_slider,"minute",this.minute-this.minute%this._defaults.stepMinute)),this.second_slider&&(this.control.options(this,this.second_slider,"second",{min:this._defaults.secondMin,max:d,step:this._defaults.stepSecond}),this.control.value(this,this.second_slider,"second",this.second-this.second%this._defaults.stepSecond)),this.millisec_slider&&(this.control.options(this,this.millisec_slider,"millisec",{min:this._defaults.millisecMin,max:h,step:this._defaults.stepMillisec}),this.control.value(this,this.millisec_slider,"millisec",this.millisec-this.millisec%this._defaults.stepMillisec)),this.microsec_slider&&(this.control.options(this,this.microsec_slider,"microsec",{min:this._defaults.microsecMin,max:p,step:this._defaults.stepMicrosec}),this.control.value(this,this.microsec_slider,"microsec",this.microsec-this.microsec%this._defaults.stepMicrosec))}}},_onTimeChange:function(){if(this._defaults.showTimepicker){var e=this.hour_slider?this.control.value(this,this.hour_slider,"hour"):!1,t=this.minute_slider?this.control.value(this,this.minute_slider,"minute"):!1,i=this.second_slider?this.control.value(this,this.second_slider,"second"):!1,s=this.millisec_slider?this.control.value(this,this.millisec_slider,"millisec"):!1,a=this.microsec_slider?this.control.value(this,this.microsec_slider,"microsec"):!1,n=this.timezone_select?this.timezone_select.val():!1,r=this._defaults,l=r.pickerTimeFormat||r.timeFormat,o=r.pickerTimeSuffix||r.timeSuffix;"object"==typeof e&&(e=!1),"object"==typeof t&&(t=!1),"object"==typeof i&&(i=!1),"object"==typeof s&&(s=!1),"object"==typeof a&&(a=!1),"object"==typeof n&&(n=!1),e!==!1&&(e=parseInt(e,10)),t!==!1&&(t=parseInt(t,10)),i!==!1&&(i=parseInt(i,10)),s!==!1&&(s=parseInt(s,10)),a!==!1&&(a=parseInt(a,10)),n!==!1&&(n=""+n);var c=r[12>e?"amNames":"pmNames"][0],u=e!==parseInt(this.hour,10)||t!==parseInt(this.minute,10)||i!==parseInt(this.second,10)||s!==parseInt(this.millisec,10)||a!==parseInt(this.microsec,10)||this.ampm.length>0&&12>e!=(-1!==$.inArray(this.ampm.toUpperCase(),this.amNames))||null!==this.timezone&&n!==""+this.timezone;u&&(e!==!1&&(this.hour=e),t!==!1&&(this.minute=t),i!==!1&&(this.second=i),s!==!1&&(this.millisec=s),a!==!1&&(this.microsec=a),n!==!1&&(this.timezone=n),this.inst||(this.inst=$.datepicker._getInst(this.$input[0])),this._limitMinMaxDateTime(this.inst,!0)),this.support.ampm&&(this.ampm=c),this.formattedTime=$.datepicker.formatTime(r.timeFormat,this,r),this.$timeObj&&(l===r.timeFormat?this.$timeObj.text(this.formattedTime+o):this.$timeObj.text($.datepicker.formatTime(l,this,r)+o)),this.timeDefined=!0,u&&this._updateDateTime()}},_onSelectHandler:function(){var e=this._defaults.onSelect||this.inst.settings.onSelect,t=this.$input?this.$input[0]:null;e&&t&&e.apply(t,[this.formattedDateTime,this])},_updateDateTime:function(e){e=this.inst||e;var t=e.currentYear>0?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(e.selectedYear,e.selectedMonth,e.selectedDay),i=$.datepicker._daylightSavingAdjust(t),s=$.datepicker._get(e,"dateFormat"),a=$.datepicker._getFormatConfig(e),n=null!==i&&this.timeDefined;this.formattedDate=$.datepicker.formatDate(s,null===i?new Date:i,a);var r=this.formattedDate;if(""===e.lastVal&&(e.currentYear=e.selectedYear,e.currentMonth=e.selectedMonth,e.currentDay=e.selectedDay),this._defaults.timeOnly===!0&&this._defaults.timeOnlyShowDate===!1?r=this.formattedTime:(this._defaults.timeOnly!==!0&&(this._defaults.alwaysSetTime||n)||this._defaults.timeOnly===!0&&this._defaults.timeOnlyShowDate===!0)&&(r+=this._defaults.separator+this.formattedTime+this._defaults.timeSuffix),this.formattedDateTime=r,this._defaults.showTimepicker)if(this.$altInput&&this._defaults.timeOnly===!1&&this._defaults.altFieldTimeOnly===!0)this.$altInput.val(this.formattedTime),this.$input.val(this.formattedDate);else if(this.$altInput){this.$input.val(r);var l="",o=null!==this._defaults.altSeparator?this._defaults.altSeparator:this._defaults.separator,c=null!==this._defaults.altTimeSuffix?this._defaults.altTimeSuffix:this._defaults.timeSuffix;this._defaults.timeOnly||(l=this._defaults.altFormat?$.datepicker.formatDate(this._defaults.altFormat,null===i?new Date:i,a):this.formattedDate,l&&(l+=o)),l+=null!==this._defaults.altTimeFormat?$.datepicker.formatTime(this._defaults.altTimeFormat,this,this._defaults)+c:this.formattedTime+c,this.$altInput.val(l)}else this.$input.val(r);else this.$input.val(this.formattedDate);this.$input.trigger("change")},_onFocus:function(){if(!this.$input.val()&&this._defaults.defaultValue){this.$input.val(this._defaults.defaultValue);var e=$.datepicker._getInst(this.$input.get(0)),t=$.datepicker._get(e,"timepicker");if(t&&t._defaults.timeOnly&&e.input.val()!==e.lastVal)try{$.datepicker._updateDatepicker(e)}catch(i){$.timepicker.log(i)}}},_controls:{slider:{create:function(e,t,i,s,a,n,r){var l=e._defaults.isRTL;return t.prop("slide",null).slider({orientation:"horizontal",value:l?-1*s:s,min:l?-1*n:a,max:l?-1*a:n,step:r,slide:function(t,s){e.control.value(e,$(this),i,l?-1*s.value:s.value),e._onTimeChange()},stop:function(){e._onSelectHandler()}})},options:function(e,t,i,s,a){if(e._defaults.isRTL){if("string"==typeof s)return"min"===s||"max"===s?void 0!==a?t.slider(s,-1*a):Math.abs(t.slider(s)):t.slider(s);var n=s.min,r=s.max;return s.min=s.max=null,void 0!==n&&(s.max=-1*n),void 0!==r&&(s.min=-1*r),t.slider(s)}return"string"==typeof s&&void 0!==a?t.slider(s,a):t.slider(s)},value:function(e,t,i,s){return e._defaults.isRTL?void 0!==s?t.slider("value",-1*s):Math.abs(t.slider("value")):void 0!==s?t.slider("value",s):t.slider("value")}},select:{create:function(e,t,i,s,a,n,r){for(var l='<select class="ui-timepicker-select ui-state-default ui-corner-all" data-unit="'+i+'" data-min="'+a+'" data-max="'+n+'" data-step="'+r+'">',o=e._defaults.pickerTimeFormat||e._defaults.timeFormat,c=a;n>=c;c+=r)l+='<option value="'+c+'"'+(c===s?" selected":"")+">",l+="hour"===i?$.datepicker.formatTime($.trim(o.replace(/[^ht ]/gi,"")),{hour:c},e._defaults):"millisec"===i||"microsec"===i||c>=10?c:"0"+(""+c),l+="</option>";return l+="</select>",t.children("select").remove(),$(l).appendTo(t).change(function(){e._onTimeChange(),e._onSelectHandler()}),t},options:function(e,t,i,s,a){var n={},r=t.children("select");if("string"==typeof s){if(void 0===a)return r.data(s);n[s]=a}else n=s;return e.control.create(e,t,r.data("unit"),r.val(),n.min||r.data("min"),n.max||r.data("max"),n.step||r.data("step"))},value:function(e,t,i,s){var a=t.children("select");return void 0!==s?a.val(s):a.val()}}}}),$.fn.extend({timepicker:function(e){e=e||{};var t=Array.prototype.slice.call(arguments);return"object"==typeof e&&(t[0]=$.extend(e,{timeOnly:!0})),$(this).each(function(){$.fn.datetimepicker.apply($(this),t)})},datetimepicker:function(e){e=e||{};var t=arguments;return"string"==typeof e?"getDate"===e||"option"===e&&2===t.length&&"string"==typeof t[1]?$.fn.datepicker.apply($(this[0]),t):this.each(function(){var e=$(this);e.datepicker.apply(e,t)}):this.each(function(){var t=$(this);t.datepicker($.timepicker._newInst(t,e)._defaults)})}}),$.datepicker.parseDateTime=function(e,t,i,s,a){var n=parseDateTimeInternal(e,t,i,s,a);if(n.timeObj){var r=n.timeObj;n.date.setHours(r.hour,r.minute,r.second,r.millisec),n.date.setMicroseconds(r.microsec)}return n.date},$.datepicker.parseTime=function(e,t,i){var s=extendRemove(extendRemove({},$.timepicker._defaults),i||{});-1!==e.replace(/\'.*?\'/g,"").indexOf("Z");var a=function(e,t,i){var s,a=function(e,t){var i=[];return e&&$.merge(i,e),t&&$.merge(i,t),i=$.map(i,function(e){return e.replace(/[.*+?|()\[\]{}\\]/g,"\\$&")}),"("+i.join("|")+")?"},n=function(e){var t=e.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|c{1}|t{1,2}|z|'.*?')/g),i={h:-1,m:-1,s:-1,l:-1,c:-1,t:-1,z:-1};if(t)for(var s=0;t.length>s;s++)-1===i[(""+t[s]).charAt(0)]&&(i[(""+t[s]).charAt(0)]=s+1);return i},r="^"+(""+e).replace(/([hH]{1,2}|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g,function(e){var t=e.length;switch(e.charAt(0).toLowerCase()){case"h":return 1===t?"(\\d?\\d)":"(\\d{"+t+"})";case"m":return 1===t?"(\\d?\\d)":"(\\d{"+t+"})";case"s":return 1===t?"(\\d?\\d)":"(\\d{"+t+"})";case"l":return"(\\d?\\d?\\d)";case"c":return"(\\d?\\d?\\d)";case"z":return"(z|[-+]\\d\\d:?\\d\\d|\\S+)?";case"t":return a(i.amNames,i.pmNames);default:return"("+e.replace(/\'/g,"").replace(/(\.|\$|\^|\\|\/|\(|\)|\[|\]|\?|\+|\*)/g,function(e){return"\\"+e})+")?"}}).replace(/\s/g,"\\s?")+i.timeSuffix+"$",l=n(e),o="";s=t.match(RegExp(r,"i"));var c={hour:0,minute:0,second:0,millisec:0,microsec:0};return s?(-1!==l.t&&(void 0===s[l.t]||0===s[l.t].length?(o="",c.ampm=""):(o=-1!==$.inArray(s[l.t].toUpperCase(),i.amNames)?"AM":"PM",c.ampm=i["AM"===o?"amNames":"pmNames"][0])),-1!==l.h&&(c.hour="AM"===o&&"12"===s[l.h]?0:"PM"===o&&"12"!==s[l.h]?parseInt(s[l.h],10)+12:Number(s[l.h])),-1!==l.m&&(c.minute=Number(s[l.m])),-1!==l.s&&(c.second=Number(s[l.s])),-1!==l.l&&(c.millisec=Number(s[l.l])),-1!==l.c&&(c.microsec=Number(s[l.c])),-1!==l.z&&void 0!==s[l.z]&&(c.timezone=$.timepicker.timezoneOffsetNumber(s[l.z])),c):!1},n=function(e,t,i){try{var s=new Date("2012-01-01 "+t);if(isNaN(s.getTime())&&(s=new Date("2012-01-01T"+t),isNaN(s.getTime())&&(s=new Date("01/01/2012 "+t),isNaN(s.getTime()))))throw"Unable to parse time with native Date: "+t;return{hour:s.getHours(),minute:s.getMinutes(),second:s.getSeconds(),millisec:s.getMilliseconds(),microsec:s.getMicroseconds(),timezone:-1*s.getTimezoneOffset()}}catch(n){try{return a(e,t,i)}catch(r){$.timepicker.log("Unable to parse \ntimeString: "+t+"\ntimeFormat: "+e)}}return!1};return"function"==typeof s.parse?s.parse(e,t,s):"loose"===s.parse?n(e,t,s):a(e,t,s)},$.datepicker.formatTime=function(e,t,i){i=i||{},i=$.extend({},$.timepicker._defaults,i),t=$.extend({hour:0,minute:0,second:0,millisec:0,microsec:0,timezone:null},t);var s=e,a=i.amNames[0],n=parseInt(t.hour,10);return n>11&&(a=i.pmNames[0]),s=s.replace(/(?:HH?|hh?|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g,function(e){switch(e){case"HH":return("0"+n).slice(-2);case"H":return n;case"hh":return("0"+convert24to12(n)).slice(-2);case"h":return convert24to12(n);case"mm":return("0"+t.minute).slice(-2);case"m":return t.minute;case"ss":return("0"+t.second).slice(-2);case"s":return t.second;case"l":return("00"+t.millisec).slice(-3);case"c":return("00"+t.microsec).slice(-3);case"z":return $.timepicker.timezoneOffsetString(null===t.timezone?i.timezone:t.timezone,!1);case"Z":return $.timepicker.timezoneOffsetString(null===t.timezone?i.timezone:t.timezone,!0);case"T":return a.charAt(0).toUpperCase();case"TT":return a.toUpperCase();case"t":return a.charAt(0).toLowerCase();case"tt":return a.toLowerCase();default:return e.replace(/'/g,"")}})},$.datepicker._base_selectDate=$.datepicker._selectDate,$.datepicker._selectDate=function(e,t){var i,s=this._getInst($(e)[0]),a=this._get(s,"timepicker");a&&s.settings.showTimepicker?(a._limitMinMaxDateTime(s,!0),i=s.inline,s.inline=s.stay_open=!0,this._base_selectDate(e,t),s.inline=i,s.stay_open=!1,this._notifyChange(s),this._updateDatepicker(s)):this._base_selectDate(e,t)},$.datepicker._base_updateDatepicker=$.datepicker._updateDatepicker,$.datepicker._updateDatepicker=function(e){var t=e.input[0];if(!($.datepicker._curInst&&$.datepicker._curInst!==e&&$.datepicker._datepickerShowing&&$.datepicker._lastInput!==t||"boolean"==typeof e.stay_open&&e.stay_open!==!1)){this._base_updateDatepicker(e);var i=this._get(e,"timepicker");i&&i._addTimePicker(e)}},$.datepicker._base_doKeyPress=$.datepicker._doKeyPress,$.datepicker._doKeyPress=function(e){var t=$.datepicker._getInst(e.target),i=$.datepicker._get(t,"timepicker");if(i&&$.datepicker._get(t,"constrainInput")){var s=i.support.ampm,a=null!==i._defaults.showTimezone?i._defaults.showTimezone:i.support.timezone,n=$.datepicker._possibleChars($.datepicker._get(t,"dateFormat")),r=(""+i._defaults.timeFormat).replace(/[hms]/g,"").replace(/TT/g,s?"APM":"").replace(/Tt/g,s?"AaPpMm":"").replace(/tT/g,s?"AaPpMm":"").replace(/T/g,s?"AP":"").replace(/tt/g,s?"apm":"").replace(/t/g,s?"ap":"")+" "+i._defaults.separator+i._defaults.timeSuffix+(a?i._defaults.timezoneList.join(""):"")+i._defaults.amNames.join("")+i._defaults.pmNames.join("")+n,l=String.fromCharCode(void 0===e.charCode?e.keyCode:e.charCode);return e.ctrlKey||" ">l||!n||r.indexOf(l)>-1}return $.datepicker._base_doKeyPress(e)},$.datepicker._base_updateAlternate=$.datepicker._updateAlternate,$.datepicker._updateAlternate=function(e){var t=this._get(e,"timepicker");if(t){var i=t._defaults.altField;if(i){var s=(t._defaults.altFormat||t._defaults.dateFormat,this._getDate(e)),a=$.datepicker._getFormatConfig(e),n="",r=t._defaults.altSeparator?t._defaults.altSeparator:t._defaults.separator,l=t._defaults.altTimeSuffix?t._defaults.altTimeSuffix:t._defaults.timeSuffix,o=null!==t._defaults.altTimeFormat?t._defaults.altTimeFormat:t._defaults.timeFormat;n+=$.datepicker.formatTime(o,t,t._defaults)+l,t._defaults.timeOnly||t._defaults.altFieldTimeOnly||null===s||(n=t._defaults.altFormat?$.datepicker.formatDate(t._defaults.altFormat,s,a)+r+n:t.formattedDate+r+n),$(i).val(e.input.val()?n:"")}}else $.datepicker._base_updateAlternate(e)},$.datepicker._base_doKeyUp=$.datepicker._doKeyUp,$.datepicker._doKeyUp=function(e){var t=$.datepicker._getInst(e.target),i=$.datepicker._get(t,"timepicker");if(i&&i._defaults.timeOnly&&t.input.val()!==t.lastVal)try{$.datepicker._updateDatepicker(t)}catch(s){$.timepicker.log(s)}return $.datepicker._base_doKeyUp(e)},$.datepicker._base_gotoToday=$.datepicker._gotoToday,$.datepicker._gotoToday=function(e){var t=this._getInst($(e)[0]);t.dpDiv,this._base_gotoToday(e);var i=this._get(t,"timepicker");selectLocalTimezone(i);var s=new Date;this._setTime(t,s),this._setDate(t,s)},$.datepicker._disableTimepickerDatepicker=function(e){var t=this._getInst(e);if(t){var i=this._get(t,"timepicker");$(e).datepicker("getDate"),i&&(t.settings.showTimepicker=!1,i._defaults.showTimepicker=!1,i._updateDateTime(t))}},$.datepicker._enableTimepickerDatepicker=function(e){var t=this._getInst(e);if(t){var i=this._get(t,"timepicker");$(e).datepicker("getDate"),i&&(t.settings.showTimepicker=!0,i._defaults.showTimepicker=!0,i._addTimePicker(t),i._updateDateTime(t))}},$.datepicker._setTime=function(e,t){var i=this._get(e,"timepicker");if(i){var s=i._defaults;
5
+ i.hour=t?t.getHours():s.hour,i.minute=t?t.getMinutes():s.minute,i.second=t?t.getSeconds():s.second,i.millisec=t?t.getMilliseconds():s.millisec,i.microsec=t?t.getMicroseconds():s.microsec,i._limitMinMaxDateTime(e,!0),i._onTimeChange(),i._updateDateTime(e)}},$.datepicker._setTimeDatepicker=function(e,t,i){var s=this._getInst(e);if(s){var a=this._get(s,"timepicker");if(a){this._setDateFromField(s);var n;t&&("string"==typeof t?(a._parseTime(t,i),n=new Date,n.setHours(a.hour,a.minute,a.second,a.millisec),n.setMicroseconds(a.microsec)):(n=new Date(t.getTime()),n.setMicroseconds(t.getMicroseconds())),"Invalid Date"==""+n&&(n=void 0),this._setTime(s,n))}}},$.datepicker._base_setDateDatepicker=$.datepicker._setDateDatepicker,$.datepicker._setDateDatepicker=function(e,t){var i=this._getInst(e),s=t;if(i){"string"==typeof t&&(s=new Date(t),s.getTime()||(this._base_setDateDatepicker.apply(this,arguments),s=$(e).datepicker("getDate")));var a,n=this._get(i,"timepicker");s instanceof Date?(a=new Date(s.getTime()),a.setMicroseconds(s.getMicroseconds())):a=s,n&&a&&(n.support.timezone||null!==n._defaults.timezone||(n.timezone=-1*a.getTimezoneOffset()),s=$.timepicker.timezoneAdjust(s,n.timezone),a=$.timepicker.timezoneAdjust(a,n.timezone)),this._updateDatepicker(i),this._base_setDateDatepicker.apply(this,arguments),this._setTimeDatepicker(e,a,!0)}},$.datepicker._base_getDateDatepicker=$.datepicker._getDateDatepicker,$.datepicker._getDateDatepicker=function(e,t){var i=this._getInst(e);if(i){var s=this._get(i,"timepicker");if(s){void 0===i.lastVal&&this._setDateFromField(i,t);var a=this._getDate(i);return a&&s._parseTime($(e).val(),s.timeOnly)&&(a.setHours(s.hour,s.minute,s.second,s.millisec),a.setMicroseconds(s.microsec),null!=s.timezone&&(s.support.timezone||null!==s._defaults.timezone||(s.timezone=-1*a.getTimezoneOffset()),a=$.timepicker.timezoneAdjust(a,s.timezone))),a}return this._base_getDateDatepicker(e,t)}},$.datepicker._base_parseDate=$.datepicker.parseDate,$.datepicker.parseDate=function(e,t,i){var s;try{s=this._base_parseDate(e,t,i)}catch(a){if(!(a.indexOf(":")>=0))throw a;s=this._base_parseDate(e,t.substring(0,t.length-(a.length-a.indexOf(":")-2)),i),$.timepicker.log("Error parsing the date string: "+a+"\ndate string = "+t+"\ndate format = "+e)}return s},$.datepicker._base_formatDate=$.datepicker._formatDate,$.datepicker._formatDate=function(e){var t=this._get(e,"timepicker");return t?(t._updateDateTime(e),t.$input.val()):this._base_formatDate(e)},$.datepicker._base_optionDatepicker=$.datepicker._optionDatepicker,$.datepicker._optionDatepicker=function(e,t,i){var s,a=this._getInst(e);if(!a)return null;var n=this._get(a,"timepicker");if(n){var r,l,o,c,u=null,m=null,d=null,h=n._defaults.evnts,p={};if("string"==typeof t){if("minDate"===t||"minDateTime"===t)u=i;else if("maxDate"===t||"maxDateTime"===t)m=i;else if("onSelect"===t)d=i;else if(h.hasOwnProperty(t)){if(i===void 0)return h[t];p[t]=i,s={}}}else if("object"==typeof t){t.minDate?u=t.minDate:t.minDateTime?u=t.minDateTime:t.maxDate?m=t.maxDate:t.maxDateTime&&(m=t.maxDateTime);for(r in h)h.hasOwnProperty(r)&&t[r]&&(p[r]=t[r])}for(r in p)p.hasOwnProperty(r)&&(h[r]=p[r],s||(s=$.extend({},t)),delete s[r]);if(s&&isEmptyObject(s))return;if(u?(u=0===u?new Date:new Date(u),n._defaults.minDate=u,n._defaults.minDateTime=u):m?(m=0===m?new Date:new Date(m),n._defaults.maxDate=m,n._defaults.maxDateTime=m):d&&(n._defaults.onSelect=d),u||m)return c=$(e),o=c.datetimepicker("getDate"),l=this._base_optionDatepicker.call($.datepicker,e,s||t,i),c.datetimepicker("setDate",o),l}return void 0===i?this._base_optionDatepicker.call($.datepicker,e,t):this._base_optionDatepicker.call($.datepicker,e,s||t,i)};var isEmptyObject=function(e){var t;for(t in e)if(e.hasOwnProperty(t))return!1;return!0},extendRemove=function(e,t){$.extend(e,t);for(var i in t)(null===t[i]||void 0===t[i])&&(e[i]=t[i]);return e},detectSupport=function(e){var t=e.replace(/'.*?'/g,"").toLowerCase(),i=function(e,t){return-1!==e.indexOf(t)?!0:!1};return{hour:i(t,"h"),minute:i(t,"m"),second:i(t,"s"),millisec:i(t,"l"),microsec:i(t,"c"),timezone:i(t,"z"),ampm:i(t,"t")&&i(e,"h"),iso8601:i(e,"Z")}},convert24to12=function(e){return e%=12,0===e&&(e=12),e+""},computeEffectiveSetting=function(e,t){return e&&e[t]?e[t]:$.timepicker._defaults[t]},splitDateTime=function(e,t){var i=computeEffectiveSetting(t,"separator"),s=computeEffectiveSetting(t,"timeFormat"),a=s.split(i),n=a.length,r=e.split(i),l=r.length;return l>1?{dateString:r.splice(0,l-n).join(i),timeString:r.splice(0,n).join(i)}:{dateString:e,timeString:""}},parseDateTimeInternal=function(e,t,i,s,a){var n,r,l;if(r=splitDateTime(i,a),n=$.datepicker._base_parseDate(e,r.dateString,s),""===r.timeString)return{date:n};if(l=$.datepicker.parseTime(t,r.timeString,a),!l)throw"Wrong time format";return{date:n,timeObj:l}},selectLocalTimezone=function(e,t){if(e&&e.timezone_select){var i=t||new Date;e.timezone_select.val(-i.getTimezoneOffset())}};$.timepicker=new Timepicker,$.timepicker.timezoneOffsetString=function(e,t){if(isNaN(e)||e>840||-720>e)return e;var i=e,s=i%60,a=(i-s)/60,n=t?":":"",r=(i>=0?"+":"-")+("0"+Math.abs(a)).slice(-2)+n+("0"+Math.abs(s)).slice(-2);return"+00:00"===r?"Z":r},$.timepicker.timezoneOffsetNumber=function(e){var t=(""+e).replace(":","");return"Z"===t.toUpperCase()?0:/^(\-|\+)\d{4}$/.test(t)?("-"===t.substr(0,1)?-1:1)*(60*parseInt(t.substr(1,2),10)+parseInt(t.substr(3,2),10)):e},$.timepicker.timezoneAdjust=function(e,t){var i=$.timepicker.timezoneOffsetNumber(t);return isNaN(i)||e.setMinutes(e.getMinutes()+-e.getTimezoneOffset()-i),e},$.timepicker.timeRange=function(e,t,i){return $.timepicker.handleRange("timepicker",e,t,i)},$.timepicker.datetimeRange=function(e,t,i){$.timepicker.handleRange("datetimepicker",e,t,i)},$.timepicker.dateRange=function(e,t,i){$.timepicker.handleRange("datepicker",e,t,i)},$.timepicker.handleRange=function(e,t,i,s){function a(a,n){var r=t[e]("getDate"),l=i[e]("getDate"),o=a[e]("getDate");if(null!==r){var c=new Date(r.getTime()),u=new Date(r.getTime());c.setMilliseconds(c.getMilliseconds()+s.minInterval),u.setMilliseconds(u.getMilliseconds()+s.maxInterval),s.minInterval>0&&c>l?i[e]("setDate",c):s.maxInterval>0&&l>u?i[e]("setDate",u):r>l&&n[e]("setDate",o)}}function n(t,i,a){if(t.val()){var n=t[e].call(t,"getDate");null!==n&&s.minInterval>0&&("minDate"===a&&n.setMilliseconds(n.getMilliseconds()+s.minInterval),"maxDate"===a&&n.setMilliseconds(n.getMilliseconds()-s.minInterval)),n.getTime&&i[e].call(i,"option",a,n)}}s=$.extend({},{minInterval:0,maxInterval:0,start:{},end:{}},s);var r=!1;return"timepicker"===e&&(r=!0,e="datetimepicker"),$.fn[e].call(t,$.extend({timeOnly:r,onClose:function(){a($(this),i)},onSelect:function(){n($(this),i,"minDate")}},s,s.start)),$.fn[e].call(i,$.extend({timeOnly:r,onClose:function(){a($(this),t)},onSelect:function(){n($(this),t,"maxDate")}},s,s.end)),a(t,i),n(t,i,"minDate"),n(i,t,"maxDate"),$([t.get(0),i.get(0)])},$.timepicker.log=function(){window.console&&window.console.log.apply(window.console,Array.prototype.slice.call(arguments))},$.timepicker._util={_extendRemove:extendRemove,_isEmptyObject:isEmptyObject,_convert24to12:convert24to12,_detectSupport:detectSupport,_selectLocalTimezone:selectLocalTimezone,_computeEffectiveSetting:computeEffectiveSetting,_splitDateTime:splitDateTime,_parseDateTimeInternal:parseDateTimeInternal},Date.prototype.getMicroseconds||(Date.prototype.microseconds=0,Date.prototype.getMicroseconds=function(){return this.microseconds},Date.prototype.setMicroseconds=function(e){return this.setMilliseconds(this.getMilliseconds()+Math.floor(e/1e3)),this.microseconds=e%1e3,this}),$.timepicker.version="1.5.0"}})(jQuery);
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-af.js DELETED
@@ -1,20 +0,0 @@
1
- /* Afrikaans translation for the jQuery Timepicker Addon */
2
- /* Written by Deon Heyns */
3
- (function($) {
4
- $.timepicker.regional['af'] = {
5
- timeOnlyTitle: 'Kies Tyd',
6
- timeText: 'Tyd ',
7
- hourText: 'Ure ',
8
- minuteText: 'Minute',
9
- secondText: 'Sekondes',
10
- millisecText: 'Millisekondes',
11
- timezoneText: 'Tydsone',
12
- currentText: 'Huidige Tyd',
13
- closeText: 'Klaar',
14
- timeFormat: 'HH:mm',
15
- amNames: ['AM', 'A'],
16
- pmNames: ['PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['af']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-bg.js DELETED
@@ -1,20 +0,0 @@
1
- /* Bulgarian translation for the jQuery Timepicker Addon */
2
- /* Written by Plamen Kovandjiev */
3
- (function($) {
4
- $.timepicker.regional['bg'] = {
5
- timeOnlyTitle: 'Изберете време',
6
- timeText: 'Време',
7
- hourText: 'Час',
8
- minuteText: 'Минути',
9
- secondText: 'Секунди',
10
- millisecText: 'Милисекунди',
11
- timezoneText: 'Часови пояс',
12
- currentText: 'Сега',
13
- closeText: 'Затвори',
14
- timeFormat: 'HH:mm',
15
- amNames: ['AM', 'A'],
16
- pmNames: ['PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['bg']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-ca.js DELETED
@@ -1,20 +0,0 @@
1
- /* Catalan translation for the jQuery Timepicker Addon */
2
- /* Written by Sergi Faber */
3
- (function($) {
4
- $.timepicker.regional['ca'] = {
5
- timeOnlyTitle: 'Escollir una hora',
6
- timeText: 'Hora',
7
- hourText: 'Hores',
8
- minuteText: 'Minuts',
9
- secondText: 'Segons',
10
- millisecText: 'Milisegons',
11
- timezoneText: 'Fus horari',
12
- currentText: 'Ara',
13
- closeText: 'Tancar',
14
- timeFormat: 'HH:mm',
15
- amNames: ['AM', 'A'],
16
- pmNames: ['PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['ca']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-cs.js DELETED
@@ -1,20 +0,0 @@
1
- /* Czech translation for the jQuery Timepicker Addon */
2
- /* Written by Ondřej Vodáček */
3
- (function($) {
4
- $.timepicker.regional['cs'] = {
5
- timeOnlyTitle: 'Vyberte čas',
6
- timeText: 'Čas',
7
- hourText: 'Hodiny',
8
- minuteText: 'Minuty',
9
- secondText: 'Vteřiny',
10
- millisecText: 'Milisekundy',
11
- timezoneText: 'Časové pásmo',
12
- currentText: 'Nyní',
13
- closeText: 'Zavřít',
14
- timeFormat: 'HH:mm',
15
- amNames: ['dop.', 'AM', 'A'],
16
- pmNames: ['odp.', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['cs']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-de.js DELETED
@@ -1,20 +0,0 @@
1
- /* German translation for the jQuery Timepicker Addon */
2
- /* Written by Marvin */
3
- (function($) {
4
- $.timepicker.regional['de'] = {
5
- timeOnlyTitle: 'Zeit Wählen',
6
- timeText: 'Zeit',
7
- hourText: 'Stunde',
8
- minuteText: 'Minute',
9
- secondText: 'Sekunde',
10
- millisecText: 'Millisekunde',
11
- timezoneText: 'Zeitzone',
12
- currentText: 'Jetzt',
13
- closeText: 'Fertig',
14
- timeFormat: 'HH:mm',
15
- amNames: ['vorm.', 'AM', 'A'],
16
- pmNames: ['nachm.', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['de']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-el.js DELETED
@@ -1,20 +0,0 @@
1
- /* Hellenic translation for the jQuery Timepicker Addon */
2
- /* Written by Christos Pontikis */
3
- (function($) {
4
- $.timepicker.regional['el'] = {
5
- timeOnlyTitle: 'Επιλογή ώρας',
6
- timeText: 'Ώρα',
7
- hourText: 'Ώρες',
8
- minuteText: 'Λεπτά',
9
- secondText: 'Δευτερόλεπτα',
10
- millisecText: 'μιλιδευτερόλεπτο',
11
- timezoneText: 'Ζώνη ώρας',
12
- currentText: 'Τώρα',
13
- closeText: 'Κλείσιμο',
14
- timeFormat: 'HH:mm',
15
- amNames: ['π.μ.', 'AM', 'A'],
16
- pmNames: ['μ.μ.', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['el']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-es.js DELETED
@@ -1,20 +0,0 @@
1
- /* Spanish translation for the jQuery Timepicker Addon */
2
- /* Written by Ianaré Sévi */
3
- (function($) {
4
- $.timepicker.regional['es'] = {
5
- timeOnlyTitle: 'Elegir una hora',
6
- timeText: 'Hora',
7
- hourText: 'Horas',
8
- minuteText: 'Minutos',
9
- secondText: 'Segundos',
10
- millisecText: 'Milisegundos',
11
- timezoneText: 'Huso horario',
12
- currentText: 'Ahora',
13
- closeText: 'Cerrar',
14
- timeFormat: 'HH:mm',
15
- amNames: ['a.m.', 'AM', 'A'],
16
- pmNames: ['p.m.', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['es']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-et.js DELETED
@@ -1,20 +0,0 @@
1
- /* Estonian translation for the jQuery Timepicker Addon */
2
- /* Written by Karl Sutt (karl@sutt.ee) */
3
- (function($) {
4
- $.timepicker.regional['et'] = {
5
- timeOnlyTitle: 'Vali aeg',
6
- timeText: 'Aeg',
7
- hourText: 'Tund',
8
- minuteText: 'Minut',
9
- secondText: 'Sekund',
10
- millisecText: 'Millisekundis',
11
- timezoneText: 'Ajavöönd',
12
- currentText: 'Praegu',
13
- closeText: 'Valmis',
14
- timeFormat: 'HH:mm',
15
- amNames: ['AM', 'A'],
16
- pmNames: ['PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['et']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-eu.js DELETED
@@ -1,20 +0,0 @@
1
- /* Basque trannslation for JQuery Timepicker Addon
2
- /* Translated by Xabi Fer */
3
- (function($) {
4
- $.timepicker.regional['eu'] = {
5
- timeOnlyTitle: 'Aukeratu ordua',
6
- timeText: 'Ordua',
7
- hourText: 'Orduak',
8
- minuteText: 'Minutuak',
9
- secondText: 'Segunduak',
10
- millisecText: 'Milisegunduak',
11
- timezoneText: 'Ordu-eremua',
12
- currentText: 'Orain',
13
- closeText: 'Itxi',
14
- timeFormat: 'HH:mm',
15
- amNames: ['a.m.', 'AM', 'A'],
16
- pmNames: ['p.m.', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['eu']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-fi.js DELETED
@@ -1,20 +0,0 @@
1
- /* Finnish translation for the jQuery Timepicker Addon */
2
- /* Written by Juga Paazmaya (http://github.com/paazmaya) */
3
- (function($) {
4
- $.timepicker.regional['fi'] = {
5
- timeOnlyTitle: 'Valitse aika',
6
- timeText: 'Aika',
7
- hourText: 'Tunti',
8
- minuteText: 'Minuutti',
9
- secondText: 'Sekunti',
10
- millisecText: 'Millisekunnin',
11
- timezoneText: 'Aikavyöhyke',
12
- currentText: 'Nyt',
13
- closeText: 'Sulje',
14
- timeFormat: 'HH:mm',
15
- amNames: ['ap.', 'AM', 'A'],
16
- pmNames: ['ip.', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['fi']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-fr.js DELETED
@@ -1,20 +0,0 @@
1
- /* French translation for the jQuery Timepicker Addon */
2
- /* Written by Thomas Lété */
3
- (function($) {
4
- $.timepicker.regional['fr'] = {
5
- timeOnlyTitle: 'Choisir une heure',
6
- timeText: 'Heure',
7
- hourText: 'Heures',
8
- minuteText: 'Minutes',
9
- secondText: 'Secondes',
10
- millisecText: 'Millisecondes',
11
- timezoneText: 'Fuseau horaire',
12
- currentText: 'Maintenant',
13
- closeText: 'Terminé',
14
- timeFormat: 'HH:mm',
15
- amNames: ['AM', 'A'],
16
- pmNames: ['PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['fr']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-gl.js DELETED
@@ -1,20 +0,0 @@
1
- /* Galician translation for the jQuery Timepicker Addon */
2
- /* Written by David Barral */
3
- (function($) {
4
- $.timepicker.regional['gl'] = {
5
- timeOnlyTitle: 'Elixir unha hora',
6
- timeText: 'Hora',
7
- hourText: 'Horas',
8
- minuteText: 'Minutos',
9
- secondText: 'Segundos',
10
- millisecText: 'Milisegundos',
11
- timezoneText: 'Fuso horario',
12
- currentText: 'Agora',
13
- closeText: 'Pechar',
14
- timeFormat: 'HH:mm',
15
- amNames: ['a.m.', 'AM', 'A'],
16
- pmNames: ['p.m.', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['gl']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-he.js DELETED
@@ -1,20 +0,0 @@
1
- /* Hebrew translation for the jQuery Timepicker Addon */
2
- /* Written by Lior Lapid */
3
- (function($) {
4
- $.timepicker.regional["he"] = {
5
- timeOnlyTitle: "בחירת זמן",
6
- timeText: "שעה",
7
- hourText: "שעות",
8
- minuteText: "דקות",
9
- secondText: "שניות",
10
- millisecText: "אלפית השנייה",
11
- timezoneText: "אזור זמן",
12
- currentText: "עכשיו",
13
- closeText:"סגור",
14
- timeFormat: "HH:mm",
15
- amNames: ['לפנה"צ', 'AM', 'A'],
16
- pmNames: ['אחה"צ', 'PM', 'P'],
17
- isRTL: true
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional["he"]);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-hu.js DELETED
@@ -1,20 +0,0 @@
1
- /* Hungarian translation for the jQuery Timepicker Addon */
2
- /* Written by Vas Gábor */
3
- (function($) {
4
- $.timepicker.regional['hu'] = {
5
- timeOnlyTitle: 'Válasszon időpontot',
6
- timeText: 'Idő',
7
- hourText: 'Óra',
8
- minuteText: 'Perc',
9
- secondText: 'Másodperc',
10
- millisecText: 'Milliszekundumos',
11
- timezoneText: 'Időzóna',
12
- currentText: 'Most',
13
- closeText: 'Kész',
14
- timeFormat: 'HH:mm',
15
- amNames: ['de.', 'AM', 'A'],
16
- pmNames: ['du.', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['hu']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-id.js DELETED
@@ -1,20 +0,0 @@
1
- /* Indonesian translation for the jQuery Timepicker Addon */
2
- /* Written by Nia */
3
- (function($) {
4
- $.timepicker.regional['id'] = {
5
- timeOnlyTitle: 'Pilih Waktu',
6
- timeText: 'Waktu',
7
- hourText: 'Pukul',
8
- minuteText: 'Menit',
9
- secondText: 'Detik',
10
- millisecText: 'Milidetik',
11
- timezoneText: 'Zona Waktu',
12
- currentText: 'Sekarang',
13
- closeText: 'OK',
14
- timeFormat: 'HH:mm',
15
- amNames: ['AM', 'A'],
16
- pmNames: ['PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['id']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-it.js DELETED
@@ -1,20 +0,0 @@
1
- /* Italian translation for the jQuery Timepicker Addon */
2
- /* Written by Marco "logicoder" Del Tongo */
3
- (function($) {
4
- $.timepicker.regional['it'] = {
5
- timeOnlyTitle: 'Scegli orario',
6
- timeText: 'Orario',
7
- hourText: 'Ora',
8
- minuteText: 'Minuto',
9
- secondText: 'Secondo',
10
- millisecText: 'Millisecondo',
11
- timezoneText: 'Fuso orario',
12
- currentText: 'Adesso',
13
- closeText: 'Chiudi',
14
- timeFormat: 'HH:mm',
15
- amNames: ['m.', 'AM', 'A'],
16
- pmNames: ['p.', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['it']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-ja.js DELETED
@@ -1,20 +0,0 @@
1
- /* Japanese translation for the jQuery Timepicker Addon */
2
- /* Written by Jun Omae */
3
- (function($) {
4
- $.timepicker.regional['ja'] = {
5
- timeOnlyTitle: '時間を選択',
6
- timeText: '時間',
7
- hourText: '時',
8
- minuteText: '分',
9
- secondText: '秒',
10
- millisecText: 'ミリ秒',
11
- timezoneText: 'タイムゾーン',
12
- currentText: '現時刻',
13
- closeText: '閉じる',
14
- timeFormat: 'HH:mm',
15
- amNames: ['午前', 'AM', 'A'],
16
- pmNames: ['午後', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['ja']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-ko.js DELETED
@@ -1,20 +0,0 @@
1
- /* Korean translation for the jQuery Timepicker Addon */
2
- /* Written by Genie */
3
- (function($) {
4
- $.timepicker.regional['ko'] = {
5
- timeOnlyTitle: '시간 선택',
6
- timeText: '시간',
7
- hourText: '시',
8
- minuteText: '분',
9
- secondText: '초',
10
- millisecText: '밀리초',
11
- timezoneText: '표준 시간대',
12
- currentText: '현재 시각',
13
- closeText: '닫기',
14
- timeFormat: 'tt h:mm',
15
- amNames: ['오전', 'AM', 'A'],
16
- pmNames: ['오후', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['ko']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-lt.js DELETED
@@ -1,20 +0,0 @@
1
- /* Lithuanian translation for the jQuery Timepicker Addon */
2
- /* Written by Irmantas Šiupšinskas */
3
- (function($) {
4
- $.timepicker.regional['lt'] = {
5
- timeOnlyTitle: 'Pasirinkite laiką',
6
- timeText: 'Laikas',
7
- hourText: 'Valandos',
8
- minuteText: 'Minutės',
9
- secondText: 'Sekundės',
10
- millisecText: 'Milisekundės',
11
- timezoneText: 'Laiko zona',
12
- currentText: 'Dabar',
13
- closeText: 'Uždaryti',
14
- timeFormat: 'HH:mm',
15
- amNames: ['priešpiet', 'AM', 'A'],
16
- pmNames: ['popiet', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['lt']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-nl.js DELETED
@@ -1,20 +0,0 @@
1
- /* Dutch translation for the jQuery Timepicker Addon */
2
- /* Written by Martijn van der Lee */
3
- (function($) {
4
- $.timepicker.regional['nl'] = {
5
- timeOnlyTitle: 'Tijdstip',
6
- timeText: 'Tijd',
7
- hourText: 'Uur',
8
- minuteText: 'Minuut',
9
- secondText: 'Seconde',
10
- millisecText: 'Milliseconde',
11
- timezoneText: 'Tijdzone',
12
- currentText: 'Vandaag',
13
- closeText: 'Sluiten',
14
- timeFormat: 'HH:mm',
15
- amNames: ['AM', 'A'],
16
- pmNames: ['PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['nl']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-no.js DELETED
@@ -1,20 +0,0 @@
1
- /* Norwegian translation for the jQuery Timepicker Addon */
2
- /* Written by Morten Hauan (http://hauan.me) */
3
- (function($) {
4
- $.timepicker.regional['no'] = {
5
- timeOnlyTitle: 'Velg tid',
6
- timeText: 'Tid',
7
- hourText: 'Time',
8
- minuteText: 'Minutt',
9
- secondText: 'Sekund',
10
- millisecText: 'Millisekund',
11
- timezoneText: 'Tidssone',
12
- currentText: 'Nå',
13
- closeText: 'Lukk',
14
- timeFormat: 'HH:mm',
15
- amNames: ['am', 'AM', 'A'],
16
- pmNames: ['pm', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['no']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-pl.js DELETED
@@ -1,20 +0,0 @@
1
- /* Polish translation for the jQuery Timepicker Addon */
2
- /* Written by Michał Pena */
3
- (function($) {
4
- $.timepicker.regional['pl'] = {
5
- timeOnlyTitle: 'Wybierz godzinę',
6
- timeText: 'Czas',
7
- hourText: 'Godzina',
8
- minuteText: 'Minuta',
9
- secondText: 'Sekunda',
10
- millisecText: 'Milisekunda',
11
- timezoneText: 'Strefa czasowa',
12
- currentText: 'Teraz',
13
- closeText: 'Gotowe',
14
- timeFormat: 'HH:mm',
15
- amNames: ['AM', 'A'],
16
- pmNames: ['PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['pl']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-pt-BR.js DELETED
@@ -1,20 +0,0 @@
1
- /* Brazilian Portuguese translation for the jQuery Timepicker Addon */
2
- /* Written by Diogo Damiani (diogodamiani@gmail.com) */
3
- (function ($) {
4
- $.timepicker.regional['pt-BR'] = {
5
- timeOnlyTitle: 'Escolha a horário',
6
- timeText: 'Horário',
7
- hourText: 'Hora',
8
- minuteText: 'Minutos',
9
- secondText: 'Segundos',
10
- millisecText: 'Milissegundos',
11
- timezoneText: 'Fuso horário',
12
- currentText: 'Agora',
13
- closeText: 'Fechar',
14
- timeFormat: 'HH:mm',
15
- amNames: ['a.m.', 'AM', 'A'],
16
- pmNames: ['p.m.', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['pt-BR']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-pt.js DELETED
@@ -1,20 +0,0 @@
1
- /* Portuguese translation for the jQuery Timepicker Addon */
2
- /* Written by Luan Almeida */
3
- (function($) {
4
- $.timepicker.regional['pt'] = {
5
- timeOnlyTitle: 'Escolha uma hora',
6
- timeText: 'Hora',
7
- hourText: 'Horas',
8
- minuteText: 'Minutos',
9
- secondText: 'Segundos',
10
- millisecText: 'Milissegundos',
11
- timezoneText: 'Fuso horário',
12
- currentText: 'Agora',
13
- closeText: 'Fechar',
14
- timeFormat: 'HH:mm',
15
- amNames: ['a.m.', 'AM', 'A'],
16
- pmNames: ['p.m.', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['pt']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-ro.js DELETED
@@ -1,20 +0,0 @@
1
- /* Romanian translation for the jQuery Timepicker Addon */
2
- /* Written by Romeo Adrian Cioaba */
3
- (function($) {
4
- $.timepicker.regional['ro'] = {
5
- timeOnlyTitle: 'Alegeţi o oră',
6
- timeText: 'Timp',
7
- hourText: 'Ore',
8
- minuteText: 'Minute',
9
- secondText: 'Secunde',
10
- millisecText: 'Milisecunde',
11
- timezoneText: 'Fus orar',
12
- currentText: 'Acum',
13
- closeText: 'Închide',
14
- timeFormat: 'HH:mm',
15
- amNames: ['AM', 'A'],
16
- pmNames: ['PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['ro']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-ru.js DELETED
@@ -1,20 +0,0 @@
1
- /* Russian translation for the jQuery Timepicker Addon */
2
- /* Written by Trent Richardson */
3
- (function($) {
4
- $.timepicker.regional['ru'] = {
5
- timeOnlyTitle: 'Выберите время',
6
- timeText: 'Время',
7
- hourText: 'Часы',
8
- minuteText: 'Минуты',
9
- secondText: 'Секунды',
10
- millisecText: 'Миллисекунды',
11
- timezoneText: 'Часовой пояс',
12
- currentText: 'Сейчас',
13
- closeText: 'Закрыть',
14
- timeFormat: 'HH:mm',
15
- amNames: ['AM', 'A'],
16
- pmNames: ['PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['ru']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-sk.js DELETED
@@ -1,20 +0,0 @@
1
- /* Slovak translation for the jQuery Timepicker Addon */
2
- /* Written by David Vallner */
3
- (function($) {
4
- $.timepicker.regional['sk'] = {
5
- timeOnlyTitle: 'Zvoľte čas',
6
- timeText: 'Čas',
7
- hourText: 'Hodiny',
8
- minuteText: 'Minúty',
9
- secondText: 'Sekundy',
10
- millisecText: 'Milisekundy',
11
- timezoneText: 'Časové pásmo',
12
- currentText: 'Teraz',
13
- closeText: 'Zavrieť',
14
- timeFormat: 'H:m',
15
- amNames: ['dop.', 'AM', 'A'],
16
- pmNames: ['pop.', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['sk']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-sv.js DELETED
@@ -1,20 +0,0 @@
1
- /* Swedish translation for the jQuery Timepicker Addon */
2
- /* Written by Nevon */
3
- (function($) {
4
- $.timepicker.regional['sv'] = {
5
- timeOnlyTitle: 'Välj en tid',
6
- timeText: 'Timme',
7
- hourText: 'Timmar',
8
- minuteText: 'Minuter',
9
- secondText: 'Sekunder',
10
- millisecText: 'Millisekunder',
11
- timezoneText: 'Tidszon',
12
- currentText: 'Nu',
13
- closeText: 'Stäng',
14
- timeFormat: 'HH:mm',
15
- amNames: ['AM', 'A'],
16
- pmNames: ['PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['sv']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-th.js DELETED
@@ -1,17 +0,0 @@
1
- /* Thai translation for the jQuery Timepicker Addon */
2
- /* Written by Yote Wachirapornpongsa */
3
- (function($) {
4
- $.timepicker.regional['th'] = {
5
- timeOnlyTitle: 'เลือกเวลา',
6
- timeText: 'เวลา ',
7
- hourText: 'ชั่วโมง ',
8
- minuteText: 'นาที',
9
- secondText: 'วินาที',
10
- millisecText: 'มิลลิวินาที',
11
- timezoneText: 'เขตเวลา',
12
- currentText: 'เวลาปัจจุบัน',
13
- closeText: 'ปิด',
14
- timeFormat: 'hh:mm tt'
15
- };
16
- $.timepicker.setDefaults($.timepicker.regional['th']);
17
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-tr.js DELETED
@@ -1,20 +0,0 @@
1
- /* Turkish translation for the jQuery Timepicker Addon */
2
- /* Written by Fehmi Can Saglam, Edited by Goktug Ozturk */
3
- (function($) {
4
- $.timepicker.regional['tr'] = {
5
- timeOnlyTitle: 'Zaman Seçiniz',
6
- timeText: 'Zaman',
7
- hourText: 'Saat',
8
- minuteText: 'Dakika',
9
- secondText: 'Saniye',
10
- millisecText: 'Milisaniye',
11
- timezoneText: 'Zaman Dilimi',
12
- currentText: 'Şu an',
13
- closeText: 'Tamam',
14
- timeFormat: 'HH:mm',
15
- amNames: ['ÖÖ', 'Ö'],
16
- pmNames: ['ÖS', 'S'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['tr']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-uk.js DELETED
@@ -1,20 +0,0 @@
1
- /* Ukrainian translation for the jQuery Timepicker Addon */
2
- /* Written by Sergey Noskov */
3
- (function($) {
4
- $.timepicker.regional['uk'] = {
5
- timeOnlyTitle: 'Виберіть час',
6
- timeText: 'Час',
7
- hourText: 'Години',
8
- minuteText: 'Хвилини',
9
- secondText: 'Секунди',
10
- millisecText: 'Мілісекунди',
11
- timezoneText: 'Часовий пояс',
12
- currentText: 'Зараз',
13
- closeText: 'Закрити',
14
- timeFormat: 'HH:mm',
15
- amNames: ['AM', 'A'],
16
- pmNames: ['PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['uk']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-vi.js DELETED
@@ -1,20 +0,0 @@
1
- /* Vietnamese translation for the jQuery Timepicker Addon */
2
- /* Written by Nguyen Dinh Trung */
3
- (function($) {
4
- $.timepicker.regional['vi'] = {
5
- timeOnlyTitle: 'Chọn giờ',
6
- timeText: 'Thời gian',
7
- hourText: 'Giờ',
8
- minuteText: 'Phút',
9
- secondText: 'Giây',
10
- millisecText: 'Phần nghìn giây',
11
- timezoneText: 'Múi giờ',
12
- currentText: 'Hiện thời',
13
- closeText: 'Đóng',
14
- timeFormat: 'H:m',
15
- amNames: ['SA', 'AM', 'A'],
16
- pmNames: ['CH', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['vi']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-zh-CN.js DELETED
@@ -1,20 +0,0 @@
1
- /* Simplified Chinese translation for the jQuery Timepicker Addon /
2
- / Written by Will Lu */
3
- (function($) {
4
- $.timepicker.regional['zh-CN'] = {
5
- timeOnlyTitle: '选择时间',
6
- timeText: '时间',
7
- hourText: '小时',
8
- minuteText: '分钟',
9
- secondText: '秒钟',
10
- millisecText: '微秒',
11
- timezoneText: '时区',
12
- currentText: '现在时间',
13
- closeText: '关闭',
14
- timeFormat: 'HH:mm',
15
- amNames: ['AM', 'A'],
16
- pmNames: ['PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['zh-CN']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jqueryui/timepicker-i18n/jquery-ui-timepicker-zh-TW.js DELETED
@@ -1,20 +0,0 @@
1
- /* Chinese translation for the jQuery Timepicker Addon */
2
- /* Written by Alang.lin */
3
- (function($) {
4
- $.timepicker.regional['zh-TW'] = {
5
- timeOnlyTitle: '選擇時分秒',
6
- timeText: '時間',
7
- hourText: '時',
8
- minuteText: '分',
9
- secondText: '秒',
10
- millisecText: '毫秒',
11
- timezoneText: '時區',
12
- currentText: '現在時間',
13
- closeText: '確定',
14
- timeFormat: 'HH:mm',
15
- amNames: ['上午', 'AM', 'A'],
16
- pmNames: ['下午', 'PM', 'P'],
17
- isRTL: false
18
- };
19
- $.timepicker.setDefaults($.timepicker.regional['zh-TW']);
20
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/map-frontend.js ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* global google, jQuery */
2
+
3
+ jQuery( function ( $ )
4
+ {
5
+ 'use strict';
6
+
7
+ /**
8
+ * Callback function for Google Maps Lazy Load library to display map
9
+ *
10
+ * @return void
11
+ */
12
+ function displayMap()
13
+ {
14
+ var $container = $( this ),
15
+ options = $container.data( 'map_options' );
16
+
17
+ var mapOptions = options.js_options,
18
+ center = new google.maps.LatLng( options.latitude, options.longitude ),
19
+ map;
20
+
21
+ switch ( mapOptions.mapTypeId )
22
+ {
23
+ case 'ROADMAP':
24
+ mapOptions.mapTypeId = google.maps.MapTypeId.ROADMAP;
25
+ break;
26
+ case 'SATELLITE':
27
+ mapOptions.mapTypeId = google.maps.MapTypeId.SATELLITE;
28
+ break;
29
+ case 'HYBRID':
30
+ mapOptions.mapTypeId = google.maps.MapTypeId.HYBRID;
31
+ break;
32
+ case 'TERRAIN':
33
+ mapOptions.mapTypeId = google.maps.MapTypeId.TERRAIN;
34
+ break;
35
+ }
36
+ mapOptions.center = center;
37
+ map = new google.maps.Map( this, mapOptions );
38
+
39
+ // Set marker
40
+ if ( options.marker )
41
+ {
42
+ var marker = new google.maps.Marker( {
43
+ position: center,
44
+ map : map
45
+ } );
46
+
47
+ // Set marker title
48
+ if ( options.marker_title )
49
+ {
50
+ marker.setTitle( mapOptions.marker_title );
51
+ }
52
+ }
53
+
54
+ // Set info window
55
+ if ( options.info_window )
56
+ {
57
+ var infoWindow = new google.maps.InfoWindow( {
58
+ content : options.info_window,
59
+ minWidth: 200
60
+ } );
61
+
62
+ google.maps.event.addListener( marker, 'click', function ()
63
+ {
64
+ infoWindow.open( map, marker );
65
+ } );
66
+ }
67
+ }
68
+
69
+ // Loop through all map instances and display them
70
+ $( '.rwmb-map-canvas' ).each( displayMap );
71
+ } );
js/map.js CHANGED
@@ -91,6 +91,21 @@
91
  that.geocodeAddress();
92
  return false;
93
  } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  },
95
 
96
  // Autocomplete address
@@ -180,6 +195,7 @@
180
  field.init();
181
 
182
  $( this ).data( 'mapController', field );
 
183
  } );
184
 
185
  $( '.rwmb-input' ).on( 'clone', function ()
91
  that.geocodeAddress();
92
  return false;
93
  } );
94
+
95
+ /**
96
+ * Add a custom event that allows other scripts to refresh the maps when needed
97
+ * For example: when maps is in tabs or hidden div (this is known issue of Google Maps)
98
+ *
99
+ * @see https://developers.google.com/maps/documentation/javascript/reference
100
+ * ('resize' Event)
101
+ */
102
+ $( window ).on( 'rwmb_map_refresh', function()
103
+ {
104
+ if ( that.map )
105
+ {
106
+ google.maps.event.trigger( that.map, 'resize' );
107
+ }
108
+ } );
109
  },
110
 
111
  // Autocomplete address
195
  field.init();
196
 
197
  $( this ).data( 'mapController', field );
198
+
199
  } );
200
 
201
  $( '.rwmb-input' ).on( 'clone', function ()
js/plupload-image.js CHANGED
@@ -136,6 +136,6 @@ jQuery( function ( $ )
136
  */
137
  function addThrobber( file )
138
  {
139
- $( '#' + file.id + '-throbber' ).html( '<img class="rwmb-loader" height="64" width="64" src="' + RWMB.url + '"img/loader.gif">' );
140
  }
141
  } );
136
  */
137
  function addThrobber( file )
138
  {
139
+ $( '#' + file.id + '-throbber' ).html( '<img class="rwmb-loader" height="64" width="64" src="' + RWMB.url + 'img/loader.gif">' );
140
  }
141
  } );
js/time.js CHANGED
@@ -6,15 +6,25 @@ jQuery( function ( $ )
6
  * Update datetime picker element
7
  * Used for static & dynamic added elements (when clone)
8
  */
9
- function rwmb_update_time_picker()
10
  {
11
  var $this = $( this ),
12
  options = $this.data( 'options' );
13
 
14
- $this.siblings( '.ui-datepicker-append' ).remove(); // Remove appended text
15
  $this.removeClass( 'hasDatepicker' ).attr( 'id', '' ).timepicker( options );
16
  }
17
 
18
- $( ':input.rwmb-time' ).each( rwmb_update_time_picker );
19
- $( '.rwmb-input' ).on( 'clone', ':input.rwmb-time', rwmb_update_time_picker );
 
 
 
 
 
 
 
 
 
 
20
  } );
6
  * Update datetime picker element
7
  * Used for static & dynamic added elements (when clone)
8
  */
9
+ function update()
10
  {
11
  var $this = $( this ),
12
  options = $this.data( 'options' );
13
 
14
+ $this.siblings( '.ui-datepicker-append' ).remove(); // Remove appended text
15
  $this.removeClass( 'hasDatepicker' ).attr( 'id', '' ).timepicker( options );
16
  }
17
 
18
+ // Set language if available
19
+ if ( $.timepicker.regional.hasOwnProperty( RWMB_Timepicker.locale ) )
20
+ {
21
+ $.timepicker.setDefaults( $.timepicker.regional[RWMB_Timepicker.locale] );
22
+ }
23
+ else if ( $.timepicker.regional.hasOwnProperty( RWMB_Timepicker.localeShort ) )
24
+ {
25
+ $.timepicker.setDefaults( $.timepicker.regional[RWMB_Timepicker.localeShort] );
26
+ }
27
+
28
+ $( '.rwmb-time' ).each( update );
29
+ $( '.rwmb-input' ).on( 'clone', '.rwmb-time', update );
30
  } );
lang/fr_FR.mo ADDED
Binary file
lang/fr_FR.po ADDED
@@ -0,0 +1,456 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Meta Box\n"
4
+ "POT-Creation-Date: 2015-02-27 16:16+0100\n"
5
+ "PO-Revision-Date: 2015-02-28 09:09+0100\n"
6
+ "Last-Translator: \n"
7
+ "Language-Team: Frédéric Serva <fred.serva@gmail.com>\n"
8
+ "Language: fr\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 1.7.4\n"
13
+ "X-Poedit-Basepath: ..\n"
14
+ "X-Poedit-SourceCharset: UTF-8\n"
15
+ "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;"
16
+ "esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;"
17
+ "_n_noop:1,2;_nx_noop:3c,1,2;__ngettext_noop:1,2\n"
18
+ "Plural-Forms: nplurals=2; plural=(n > 1);\n"
19
+ "X-Poedit-SearchPath-0: .\n"
20
+ "X-Poedit-SearchPathExcluded-0: *.js\n"
21
+
22
+ #: demo/all-custom-post-types.php:15
23
+ msgid "Personal Information"
24
+ msgstr "Informations personnelles"
25
+
26
+ #: demo/all-custom-post-types.php:20
27
+ msgid "Full name"
28
+ msgstr "Nom et prénom"
29
+
30
+ #: demo/better-include.php:16 demo/include-by-ID-or-page-template.php:8
31
+ msgid "Meta Box Title"
32
+ msgstr "Titre de la Meta Box"
33
+
34
+ #: demo/better-include.php:19 demo/include-by-ID-or-page-template.php:14
35
+ msgid "Your images"
36
+ msgstr "Vos images"
37
+
38
+ #: demo/date-time-js-options.php:8
39
+ msgid "Date Time Picker With JS Options"
40
+ msgstr "Sélecteur Date et Heure avec Options JS"
41
+
42
+ #: demo/date-time-js-options.php:12
43
+ msgid "Date"
44
+ msgstr "Date"
45
+
46
+ #: demo/date-time-js-options.php:18 demo/demo.php:193
47
+ msgid "(yyyy-mm-dd)"
48
+ msgstr "(yyyy-mm-dd)"
49
+
50
+ #: demo/date-time-js-options.php:20
51
+ msgid "Select Date"
52
+ msgstr "Sélectionnez la date"
53
+
54
+ #: demo/date-time-js-options.php:21 demo/demo.php:194
55
+ msgid "yy-mm-dd"
56
+ msgstr "yy-mm-dd"
57
+
58
+ #: demo/date-time-js-options.php:27
59
+ msgid "Datetime"
60
+ msgstr "Date & Heure combinées"
61
+
62
+ #: demo/date-time-js-options.php:38
63
+ msgid "Time"
64
+ msgstr "Heure"
65
+
66
+ #: demo/demo.php:42
67
+ msgid "Standard Fields"
68
+ msgstr "Champs standards"
69
+
70
+ #: demo/demo.php:61
71
+ msgid "Text"
72
+ msgstr "Texte"
73
+
74
+ #: demo/demo.php:65
75
+ msgid "Text description"
76
+ msgstr "Description du texte"
77
+
78
+ #: demo/demo.php:68
79
+ msgid "Default text value"
80
+ msgstr "Valeur texte par défaut"
81
+
82
+ #: demo/demo.php:74
83
+ msgid "Checkbox"
84
+ msgstr "Case à cocher"
85
+
86
+ #: demo/demo.php:82
87
+ msgid "Radio"
88
+ msgstr "Bouton Radio"
89
+
90
+ #: demo/demo.php:88 demo/demo.php:99 demo/demo.php:242 demo/demo.php:253
91
+ #: demo/demo.php:302
92
+ msgid "Label1"
93
+ msgstr "Étiquette1"
94
+
95
+ #: demo/demo.php:89 demo/demo.php:100 demo/demo.php:243 demo/demo.php:254
96
+ #: demo/demo.php:303
97
+ msgid "Label2"
98
+ msgstr "Étiquette2"
99
+
100
+ #: demo/demo.php:94 demo/demo.php:297 inc/fields/file-input.php:40
101
+ msgid "Select"
102
+ msgstr "Choisissez"
103
+
104
+ #: demo/demo.php:105 demo/demo.php:308 demo/demo.php:333
105
+ msgid "Select an Item"
106
+ msgstr "Choisissez un élément"
107
+
108
+ #: demo/demo.php:112
109
+ msgid "Hidden value"
110
+ msgstr "Valeur cachée"
111
+
112
+ #: demo/demo.php:116
113
+ msgid "Password"
114
+ msgstr "Mot de passe"
115
+
116
+ #: demo/demo.php:122
117
+ msgid "Textarea"
118
+ msgstr "Zone de texte"
119
+
120
+ #: demo/demo.php:123
121
+ msgid "Textarea description"
122
+ msgstr "Description de la zone de texte"
123
+
124
+ #: demo/demo.php:140
125
+ msgid "Password is required"
126
+ msgstr "Mot de passe requis"
127
+
128
+ #: demo/demo.php:141
129
+ msgid "Password must be at least 7 characters"
130
+ msgstr "Le mot de passe doit comporter au moins 7 caractères."
131
+
132
+ #: demo/demo.php:149
133
+ msgid "Advanced Fields"
134
+ msgstr "Champs spéciaux"
135
+
136
+ #: demo/demo.php:155
137
+ msgid "Heading"
138
+ msgstr "Intertitre"
139
+
140
+ #: demo/demo.php:157
141
+ msgid "Optional description for this heading"
142
+ msgstr "Description facultative pour cet intertitre"
143
+
144
+ #: demo/demo.php:161 demo/slider.php:9
145
+ msgid "Slider"
146
+ msgstr "Slider"
147
+
148
+ #: demo/demo.php:166 demo/slider.php:14
149
+ msgid "$"
150
+ msgstr "$"
151
+
152
+ #: demo/demo.php:167 demo/slider.php:15
153
+ msgid " USD"
154
+ msgstr " USD"
155
+
156
+ #: demo/demo.php:178
157
+ msgid "Number"
158
+ msgstr "Nombre"
159
+
160
+ #: demo/demo.php:187
161
+ msgid "Date picker"
162
+ msgstr "Sélecteur de date"
163
+
164
+ #: demo/demo.php:202
165
+ msgid "Datetime picker"
166
+ msgstr "Sélecteur de Date & Heure combinées"
167
+
168
+ #: demo/demo.php:216
169
+ msgid "Time picker"
170
+ msgstr "Sélecteur d'heure"
171
+
172
+ #: demo/demo.php:231
173
+ msgid "Color picker"
174
+ msgstr "Sélecteur de couleur"
175
+
176
+ #: demo/demo.php:237
177
+ msgid "Checkbox list"
178
+ msgstr "liste de cases à cocher"
179
+
180
+ #: demo/demo.php:248
181
+ msgid "Autocomplete"
182
+ msgstr "Complétion automatique"
183
+
184
+ #: demo/demo.php:263
185
+ msgid "Email"
186
+ msgstr "Email"
187
+
188
+ #: demo/demo.php:265
189
+ msgid "Email description"
190
+ msgstr "Description de l'email"
191
+
192
+ #: demo/demo.php:271
193
+ msgid "Range"
194
+ msgstr "Fourchette"
195
+
196
+ #: demo/demo.php:273
197
+ msgid "Range description"
198
+ msgstr "Description de la fourchette"
199
+
200
+ #: demo/demo.php:282
201
+ msgid "URL"
202
+ msgstr "URL"
203
+
204
+ #: demo/demo.php:284
205
+ msgid "URL description"
206
+ msgstr "Description de l'URL"
207
+
208
+ #: demo/demo.php:290
209
+ msgid "oEmbed"
210
+ msgstr "oEmbed"
211
+
212
+ #: demo/demo.php:292
213
+ msgid "oEmbed description"
214
+ msgstr "Description oEmbed"
215
+
216
+ #: demo/demo.php:312
217
+ msgid "Taxonomy"
218
+ msgstr "Taxonomie"
219
+
220
+ #: demo/demo.php:326
221
+ msgid "Posts (Pages)"
222
+ msgstr "Articles (Pages)"
223
+
224
+ #: demo/demo.php:342
225
+ msgid "WYSIWYG / Rich Text Editor"
226
+ msgstr "Éditeur de texte (WYSIWYG)"
227
+
228
+ #: demo/demo.php:347
229
+ msgid "WYSIWYG default value"
230
+ msgstr "Valeur par défaut WYSIWYG"
231
+
232
+ #: demo/demo.php:363 demo/force-delete.php:12
233
+ msgid "File Upload"
234
+ msgstr "Mise en ligne d'un fichier"
235
+
236
+ #: demo/demo.php:369
237
+ msgid "File Advanced Upload"
238
+ msgstr "Mise en ligne avancée d'un fichier"
239
+
240
+ #: demo/demo.php:377 demo/force-delete.php:19
241
+ msgid "Image Upload"
242
+ msgstr "Mise en ligne d'une image"
243
+
244
+ #: demo/demo.php:383 demo/force-delete.php:25
245
+ msgid "Thickbox Image Upload"
246
+ msgstr "Mise en ligne d'une image (Thickbox)"
247
+
248
+ #: demo/demo.php:389 demo/force-delete.php:32
249
+ msgid "Plupload Image Upload"
250
+ msgstr "Mise en ligne d'une image (Plupload)"
251
+
252
+ #: demo/demo.php:396
253
+ msgid "Image Advanced Upload"
254
+ msgstr "Mise en ligne avancée d'une image"
255
+
256
+ #: demo/force-delete.php:8
257
+ msgid "Test Meta Box"
258
+ msgstr "Test de Meta Box"
259
+
260
+ #: demo/image-select.php:6
261
+ msgid "Image Select Demo"
262
+ msgstr "Démo de Sélection d'image"
263
+
264
+ #: demo/image-select.php:10
265
+ msgid "Layout"
266
+ msgstr "Disposition:"
267
+
268
+ #: demo/map.php:6
269
+ msgid "Google Map"
270
+ msgstr "Google Map"
271
+
272
+ #: demo/map.php:10
273
+ msgid "Address"
274
+ msgstr "Adresse"
275
+
276
+ #: demo/map.php:12
277
+ msgid "Hanoi, Vietnam"
278
+ msgstr "Hanoi, Vietnam"
279
+
280
+ #: demo/map.php:16
281
+ msgid "Location"
282
+ msgstr "Localisation"
283
+
284
+ #: demo/oembed.php:6
285
+ msgid "oEmbed Demo"
286
+ msgstr "oEmbed Démo"
287
+
288
+ #: demo/oembed.php:10
289
+ msgid "oEmbed(s)"
290
+ msgstr "oEmbed (s)"
291
+
292
+ #: demo/slider.php:6
293
+ msgid "Slider Demo"
294
+ msgstr "Démo de Slider"
295
+
296
+ #: demo/url.php:6
297
+ msgid "URL Demo"
298
+ msgstr "Démo d'URL"
299
+
300
+ #: demo/url.php:10
301
+ msgid "URL(s)"
302
+ msgstr "URL(s)"
303
+
304
+ #: inc/common.php:53
305
+ msgid "Documentation"
306
+ msgstr "Documentation"
307
+
308
+ #: inc/common.php:54
309
+ msgid "Extensions"
310
+ msgstr "Extensions"
311
+
312
+ #: inc/field.php:225
313
+ msgid "+"
314
+ msgstr "+"
315
+
316
+ #: inc/field.php:235
317
+ msgid "&#8211;"
318
+ msgstr "&#8211;"
319
+
320
+ #: inc/fields/autocomplete.php:18 inc/fields/autocomplete.php:72
321
+ msgid "Delete"
322
+ msgstr "Supprimer"
323
+
324
+ #: inc/fields/button.php:35
325
+ msgid "Click me"
326
+ msgstr "Cliquez-ici"
327
+
328
+ #: inc/fields/file-advanced.php:23
329
+ msgid "Select Files"
330
+ msgstr "Sélectionnez les fichiers"
331
+
332
+ #: inc/fields/file-advanced.php:66
333
+ msgctxt "file upload"
334
+ msgid "Select or Upload Files"
335
+ msgstr "Sélectionnez ou mettez en ligne des fichiers"
336
+
337
+ #: inc/fields/file-advanced.php:103 inc/fields/file.php:168
338
+ msgctxt "file upload"
339
+ msgid "Delete"
340
+ msgstr "Supprimer"
341
+
342
+ #: inc/fields/file-advanced.php:104 inc/fields/file.php:169
343
+ msgctxt "file upload"
344
+ msgid "Edit"
345
+ msgstr "Modifier"
346
+
347
+ #: inc/fields/file-input.php:17
348
+ msgid "Select File"
349
+ msgstr "Choisissez un fichier"
350
+
351
+ #: inc/fields/file-input.php:42
352
+ msgid "Remove"
353
+ msgstr "Supprimer"
354
+
355
+ #: inc/fields/file.php:19
356
+ #, php-format
357
+ msgid "You may only upload maximum %d file"
358
+ msgstr "Vous ne pouvez mettre en ligne qu'un fichier de %d maximum"
359
+
360
+ #: inc/fields/file.php:20
361
+ #, php-format
362
+ msgid "You may only upload maximum %d files"
363
+ msgstr "Vous ne pouvez mettre en ligne que des fichiers de %d maximum"
364
+
365
+ #: inc/fields/file.php:98
366
+ msgid "Error: Cannot delete file"
367
+ msgstr "Erreur : Impossible de supprimer le fichier"
368
+
369
+ #: inc/fields/file.php:111
370
+ msgctxt "file upload"
371
+ msgid "Upload Files"
372
+ msgstr "Mettez en ligne des fichiers"
373
+
374
+ #: inc/fields/file.php:112
375
+ msgctxt "file upload"
376
+ msgid "+ Add new file"
377
+ msgstr "+ Ajouter un nouveau fichier"
378
+
379
+ #: inc/fields/image-advanced.php:23
380
+ msgid "Select Images"
381
+ msgstr "Sélectionner des images"
382
+
383
+ #: inc/fields/image-advanced.php:71
384
+ msgctxt "image upload"
385
+ msgid "Select or Upload Images"
386
+ msgstr "Sélectionnez ou mettez en ligne des images"
387
+
388
+ #: inc/fields/image-advanced.php:108 inc/fields/image.php:136
389
+ msgctxt "image upload"
390
+ msgid "Delete"
391
+ msgstr "Supprimer"
392
+
393
+ #: inc/fields/image-advanced.php:109 inc/fields/image.php:137
394
+ msgctxt "image upload"
395
+ msgid "Edit"
396
+ msgstr "Modifier"
397
+
398
+ #: inc/fields/image.php:70 inc/fields/thickbox-image.php:34
399
+ msgctxt "image upload"
400
+ msgid "Upload Images"
401
+ msgstr "Mettez en ligne des images"
402
+
403
+ #: inc/fields/image.php:71
404
+ msgctxt "image upload"
405
+ msgid "+ Add new image"
406
+ msgstr "+ Ajouter une nouvelle image"
407
+
408
+ #: inc/fields/map.php:48
409
+ msgid "Find Address"
410
+ msgstr "Trouver une adresse"
411
+
412
+ #: inc/fields/oembed.php:55
413
+ msgid "Embed HTML not available."
414
+ msgstr "Intégration du code HTML non disponible."
415
+
416
+ #: inc/fields/oembed.php:77
417
+ msgid "Preview"
418
+ msgstr "Aperçu"
419
+
420
+ #: inc/fields/plupload-image.php:105
421
+ msgctxt "image upload"
422
+ msgid "Drop images here"
423
+ msgstr "Déposez des images ici"
424
+
425
+ #: inc/fields/plupload-image.php:106
426
+ msgctxt "image upload"
427
+ msgid "or"
428
+ msgstr "ou"
429
+
430
+ #: inc/fields/plupload-image.php:107
431
+ msgctxt "image upload"
432
+ msgid "Select Files"
433
+ msgstr "Sélectionnez des fichiers"
434
+
435
+ #: inc/fields/plupload-image.php:182
436
+ msgctxt "image upload"
437
+ msgid "Allowed Image Files"
438
+ msgstr "Types d'images autorisés"
439
+
440
+ #: inc/fields/post.php:52
441
+ msgid "Post"
442
+ msgstr "Article"
443
+
444
+ #: inc/fields/post.php:66 inc/fields/taxonomy.php:40 inc/fields/user.php:62
445
+ #, php-format
446
+ msgid "Select a %s"
447
+ msgstr "Choisissez un %s"
448
+
449
+ #: inc/fields/user.php:54
450
+ msgid "User"
451
+ msgstr "Utilisateur"
452
+
453
+ #: inc/meta-box.php:245
454
+ msgid "Please correct the errors highlighted below and try again."
455
+ msgstr ""
456
+ "Merci de corriger les erreurs mises en évidence ci-dessous et de réessayer."
meta-box.php CHANGED
@@ -1,9 +1,9 @@
1
  <?php
2
  /*
3
  Plugin Name: Meta Box
4
- Plugin URI: http://www.deluxeblogtips.com/meta-box
5
  Description: Create meta box for editing pages in WordPress. Compatible with custom post types since WP 3.0
6
- Version: 4.4.1
7
  Author: Rilwis
8
  Author URI: http://www.deluxeblogtips.com
9
  License: GPL2+
@@ -13,7 +13,7 @@ License: GPL2+
13
  defined( 'ABSPATH' ) || exit;
14
 
15
  // Script version, used to add version for scripts and styles
16
- define( 'RWMB_VER', '4.4.1' );
17
 
18
  // Define plugin URLs, for fast enqueuing scripts and styles
19
  if ( ! defined( 'RWMB_URL' ) )
@@ -27,24 +27,22 @@ if ( ! defined( 'RWMB_DIR' ) )
27
  define( 'RWMB_INC_DIR', trailingslashit( RWMB_DIR . 'inc' ) );
28
  define( 'RWMB_FIELDS_DIR', trailingslashit( RWMB_INC_DIR . 'fields' ) );
29
 
30
- // Optimize code for loading plugin files ONLY on admin side
31
- // @see http://www.deluxeblogtips.com/?p=345
32
 
33
- // Helper function to retrieve meta value
34
- require_once RWMB_INC_DIR . 'helpers.php';
 
35
 
36
- if ( is_admin() )
 
37
  {
38
- require_once RWMB_INC_DIR . 'common.php';
39
- require_once RWMB_INC_DIR . 'field.php';
40
-
41
- // Field classes
42
- foreach ( glob( RWMB_FIELDS_DIR . '*.php' ) as $file )
43
- {
44
- require_once $file;
45
- }
46
-
47
- // Main file
48
- require_once RWMB_INC_DIR . 'meta-box.php';
49
- require_once RWMB_INC_DIR . 'init.php';
50
  }
 
 
 
 
 
 
 
 
 
1
  <?php
2
  /*
3
  Plugin Name: Meta Box
4
+ Plugin URI: http://metabox.io
5
  Description: Create meta box for editing pages in WordPress. Compatible with custom post types since WP 3.0
6
+ Version: 4.5
7
  Author: Rilwis
8
  Author URI: http://www.deluxeblogtips.com
9
  License: GPL2+
13
  defined( 'ABSPATH' ) || exit;
14
 
15
  // Script version, used to add version for scripts and styles
16
+ define( 'RWMB_VER', '4.5' );
17
 
18
  // Define plugin URLs, for fast enqueuing scripts and styles
19
  if ( ! defined( 'RWMB_URL' ) )
27
  define( 'RWMB_INC_DIR', trailingslashit( RWMB_DIR . 'inc' ) );
28
  define( 'RWMB_FIELDS_DIR', trailingslashit( RWMB_INC_DIR . 'fields' ) );
29
 
 
 
30
 
31
+ require_once RWMB_INC_DIR . 'common.php';
32
+ require_once RWMB_INC_DIR . 'field.php';
33
+ require_once RWMB_INC_DIR . 'field-multiple-values.php';
34
 
35
+ // Field classes
36
+ foreach ( glob( RWMB_FIELDS_DIR . '*.php' ) as $file )
37
  {
38
+ require_once $file;
 
 
 
 
 
 
 
 
 
 
 
39
  }
40
+
41
+ // Meta box class
42
+ require_once RWMB_INC_DIR . 'meta-box.php';
43
+
44
+ // Helper function to retrieve meta value
45
+ require_once RWMB_INC_DIR . 'helpers.php';
46
+
47
+ // Main file
48
+ require_once RWMB_INC_DIR . 'init.php';
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === Meta Box ===
2
- Contributors: rilwis, franz-josef-kaiser, Omnicia, funkedgeek, PerWiklander, ruanmer
3
  Donate link: http://www.deluxeblogtips.com/donate
4
  Tags: meta-box, custom-fields, custom-field, meta, meta-boxes
5
  Requires at least: 3.5
6
- Tested up to: 4.0.1
7
- Stable tag: 4.4.1
8
  License: GPLv2 or later
9
 
10
  Meta Box plugin is a complete tool to create meta box and custom fields in WordPress: lightweight, powerful and easy-to-use.
@@ -31,6 +31,8 @@ See more documentation [here](http://metabox.io/docs/).
31
 
32
  ### Premium Extensions
33
 
 
 
34
  - [Meta Box Template](http://metabox.io/plugins/meta-box-template/): Define custom meta boxes and custom fields easier with templates.
35
  - [Meta Box Tooltip](http://metabox.io/plugins/meta-box-tooltip/): Display help information for fields using beautiful tooltips.
36
  - [Meta Box Show Hide (Javascript)](http://metabox.io/plugins/meta-box-show-hide-javascript/): Toggle meta boxes by page template, post format, taxonomy (including category) via Javascript.
@@ -58,10 +60,42 @@ To getting started with the plugin API, please read [this tutorial](http://metab
58
  == Frequently Asked Questions ==
59
 
60
  == Screenshots ==
61
- 1. Supported fields
 
 
 
 
 
62
 
63
  == Changelog ==
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  = 4.4.1 =
66
  * Fix: wrong text domain
67
  * Fix: `select_advanced` field not cloning
1
  === Meta Box ===
2
+ Contributors: rilwis, fitwp, f-j-kaiser, Omnicia, funkedgeek, PerWiklander, ruanmer
3
  Donate link: http://www.deluxeblogtips.com/donate
4
  Tags: meta-box, custom-fields, custom-field, meta, meta-boxes
5
  Requires at least: 3.5
6
+ Tested up to: 4.2
7
+ Stable tag: 4.5
8
  License: GPLv2 or later
9
 
10
  Meta Box plugin is a complete tool to create meta box and custom fields in WordPress: lightweight, powerful and easy-to-use.
31
 
32
  ### Premium Extensions
33
 
34
+ - [Meta Box Group](http://metabox.io/plugins/meta-box-group/): Organize custom fields in groups for better appearance and structure. Groups can be cloned.
35
+ - [Meta Box Builder](http://metabox.io/plugins/meta-box-builder/): Drag and Drop to create Meta Boxes and Custom Fields has never been easier.
36
  - [Meta Box Template](http://metabox.io/plugins/meta-box-template/): Define custom meta boxes and custom fields easier with templates.
37
  - [Meta Box Tooltip](http://metabox.io/plugins/meta-box-tooltip/): Display help information for fields using beautiful tooltips.
38
  - [Meta Box Show Hide (Javascript)](http://metabox.io/plugins/meta-box-show-hide-javascript/): Toggle meta boxes by page template, post format, taxonomy (including category) via Javascript.
60
  == Frequently Asked Questions ==
61
 
62
  == Screenshots ==
63
+ 1. Text Fields
64
+ 1. Basic Fields
65
+ 1. Advanced Fields
66
+ 1. File Image Upload Fields
67
+ 1. Media Fields
68
+ 1. Post Taxonomy Fields
69
 
70
  == Changelog ==
71
 
72
+
73
+ = 4.5 =
74
+ * Improvement: Separate `esc_meta` method
75
+ * Improvement: Add ability to use URL to retrieve options for autocomplete field
76
+ * Improvement: Add `rwmb_get_field` and `rwmb_the_field` functions to get and display field values in the frontend
77
+ * Improvement: Add field type `custom_html` to display any HTML in the meta box
78
+ * Improvement: Add field type `key_value` which allows users to add any number of key-value pairs
79
+ * Improvement: Use single JS file to display Google Maps in the frontend. No more inline Javascript.
80
+ * Improvement: Code refactor
81
+
82
+ = 4.4.3 =
83
+ * Fix: Incorrect path to loader image for `plupload_image`
84
+ * Fix: Missing placeholder for `post` field when `field_type` = `select`
85
+ * Improvement: No errors showing if invalid value is returned from `rwmb_meta_boxes` filter
86
+ * Improvement: Add filter for add/remove clone buttons text
87
+ * Improvement: Add French translation
88
+
89
+ = 4.4.2 =
90
+ * Fix: Values of text_list field not showing correctly
91
+ * Fix: Time picker field cannot select hour > 22, time > 58
92
+ * Fix: Notice error when showing fields which don't have ID
93
+ * Fix: Don't return non-existing files or images via rwmb_meta function
94
+ * Fix: CSS alignment for taxonomy tree
95
+ * Fix: Placeholder not working for "select" taxonomy
96
+ * Improvement: Update timepicker to latest version
97
+ * Improvement: Improve output markup for checkbox field
98
+
99
  = 4.4.1 =
100
  * Fix: wrong text domain
101
  * Fix: `select_advanced` field not cloning