Timeline Express - Version 1.1.5

Version Description

  • January 10th, 2015 = Enhancement: Added new filter ( timeline_express_custom_fields ) which allows users to define their own custom fields to use on Timeline Announcement posts (see readme for example). Fixed: CMB class file causing conflicts with other plugins, and removed the old version Fixed: Adjusted a few styles on the announcement post page
Download this release

Release Info

Developer eherman24
Plugin Icon 128x128 Timeline Express
Version 1.1.5
Comparing to
See all releases

Code changes from version 1.1.4.1 to 1.1.5

Files changed (38) hide show
  1. classes/class.timeline-express.php +111 -27
  2. lib/{metabox/about-template.php → about-metabox-template.php} +0 -0
  3. lib/cmb_metaboxes/helpers/cmb_Meta_Box_Sanitize.php +346 -0
  4. lib/{metabox/helpers/timeline_express_MetaBox_filters.php → cmb_metaboxes/helpers/cmb_Meta_Box_Show_Filters.php} +105 -65
  5. lib/{metabox/helpers/timeline_express_MetaBox_ajax.php → cmb_metaboxes/helpers/cmb_Meta_Box_ajax.php} +203 -180
  6. lib/cmb_metaboxes/helpers/cmb_Meta_Box_field.php +497 -0
  7. lib/cmb_metaboxes/helpers/cmb_Meta_Box_types.php +794 -0
  8. lib/{metabox → cmb_metaboxes}/images/ico-delete.png +0 -0
  9. lib/{metabox → cmb_metaboxes}/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  10. lib/{metabox → cmb_metaboxes}/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  11. lib/{metabox → cmb_metaboxes}/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  12. lib/{metabox → cmb_metaboxes}/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  13. lib/{metabox → cmb_metaboxes}/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  14. lib/{metabox → cmb_metaboxes}/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  15. lib/{metabox → cmb_metaboxes}/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  16. lib/{metabox → cmb_metaboxes}/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  17. lib/{metabox → cmb_metaboxes}/images/ui-icons_222222_256x240.png +0 -0
  18. lib/{metabox → cmb_metaboxes}/images/ui-icons_2e83ff_256x240.png +0 -0
  19. lib/{metabox → cmb_metaboxes}/images/ui-icons_454545_256x240.png +0 -0
  20. lib/{metabox → cmb_metaboxes}/images/ui-icons_888888_256x240.png +0 -0
  21. lib/{metabox → cmb_metaboxes}/images/ui-icons_cd0a0a_256x240.png +0 -0
  22. lib/cmb_metaboxes/init.php +1185 -0
  23. lib/cmb_metaboxes/js/cmb.js +797 -0
  24. lib/cmb_metaboxes/js/cmb.min.js +1 -0
  25. lib/cmb_metaboxes/js/jquery.datePicker.min.js +2038 -0
  26. lib/{metabox → cmb_metaboxes}/js/jquery.timePicker.min.js +12 -12
  27. lib/cmb_metaboxes/readme.md +296 -0
  28. lib/{metabox → cmb_metaboxes}/style.css +621 -343
  29. lib/cmb_metaboxes/style.min.css +1 -0
  30. lib/metabox/example-functions.php +0 -333
  31. lib/metabox/helpers/timeline_express_MetaBox_types.php +0 -539
  32. lib/metabox/init.php +0 -944
  33. lib/metabox/js/cmb.js +0 -335
  34. lib/metabox/js/cmb.min.js +0 -24
  35. lib/metabox/readme.md +0 -159
  36. lib/metabox/style.min.css +0 -125
  37. readme.txt +54 -2
  38. timeline-express.php +2 -2
classes/class.timeline-express.php CHANGED
@@ -143,8 +143,59 @@ if(!class_exists("timelineExpressBase"))
143
  add_action('admin_init', array( &$this , 'timeline_express_deactivate_license' ) );
144
  // Cross check the validity of our supportl icense , twice a day
145
  add_action('timeline_express_support_license_check', array( &$this , 'crosscheck_support_license' ) );
 
 
 
 
 
 
146
  }
147
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  /*
149
  * schedule_timeline_express_support_cron()
150
  * Setup our twice daily transient, to cross check the API key ( if set )
@@ -293,7 +344,6 @@ if(!class_exists("timelineExpressBase"))
293
  return $new;
294
  }
295
 
296
-
297
  /*
298
  * include_timeline_express_in_auto_updates();
299
  *
@@ -315,11 +365,11 @@ if(!class_exists("timelineExpressBase"))
315
 
316
  // enqueue metabox for the announcement cpt
317
  public function timeline_express_initialize_cmb_meta_boxes() {
318
- if ( !class_exists( 'timeline_express_MetaBoxes' ) ) {
319
- require_once TIMELINE_EXPRESS_PATH.'lib/metabox/init.php';
320
- }
321
- }
322
-
323
  // Register Announcement Custom Post Type
324
  public function timeline_express_generate_announcement_post_type() {
325
 
@@ -388,34 +438,35 @@ if(!class_exists("timelineExpressBase"))
388
  * @return array
389
  */
390
  public function cmb_timeline_announcement_metaboxes( array $meta_boxes ) {
391
-
392
  // Start with an underscore to hide fields from custom fields list
393
  $prefix = 'announcement_';
394
-
395
- $meta_boxes['announcement_info'] = array(
396
- 'id' => 'announcement_info',
397
- 'title' => __( 'Announcement Info.', 'timeline-express' ),
398
- 'pages' => array( 'te_announcements', ), // Post type
399
- 'context' => 'advanced',
400
- 'priority' => 'high',
401
- 'show_names' => true, // Show field names on the left
402
- // 'cmb_styles' => true, // Enqueue the CMB stylesheet on the frontend
403
- 'fields' => array(
404
- array(
 
405
  'name' => __( 'Announcement Color', 'timeline-express' ),
406
  'desc' => __( 'select the color for this announcement.', 'timeline-express' ),
407
  'id' => $prefix . 'color',
408
  'type' => 'colorpicker',
409
- 'std' => $this->timeline_express_optionVal['default-announcement-color'],
410
  // 'repeatable' => true,
411
  // 'on_front' => false, // Optionally designate a field to wp-admin only
412
  ),
413
  array(
414
- 'name' => __( 'Font Awesome Unicode', 'timeline-express' ),
415
  'desc' => __( 'enter the font-awesome class name in the box above. This is used for the icon associated with the announcement. <a href="http://fortawesome.github.io/Font-Awesome/cheatsheet/" target="_blank">cheat sheet</a> Example : "fa-times-circle" ', 'timeline-express' ),
416
  'id' => $prefix . 'icon',
417
  'type' => 'text_medium',
418
- 'std' => trim( $this->timeline_express_optionVal['default-announcement-icon'] ),
419
  // 'repeatable' => true,
420
  // 'on_front' => false, // Optionally designate a field to wp-admin only
421
  ),
@@ -423,8 +474,8 @@ if(!class_exists("timelineExpressBase"))
423
  'name' => __( 'Announcement Date', 'timeline-express' ),
424
  'desc' => __( 'enter the date of the announcement. the announcements will appear in chronological order according to this date. ', 'timeline-express' ),
425
  'id' => $prefix . 'date',
426
- 'type' => 'text_date_timestamp',
427
- 'std' => date( 'm/d/Y' ),
428
  // 'repeatable' => true,
429
  // 'on_front' => false, // Optionally designate a field to wp-admin only
430
  ),
@@ -436,7 +487,28 @@ if(!class_exists("timelineExpressBase"))
436
  // 'repeatable' => true,
437
  // 'on_front' => false, // Optionally designate a field to wp-admin only
438
  ),
439
- ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
440
  );
441
 
442
  $meta_boxes['about_the_author'] = array(
@@ -452,18 +524,30 @@ if(!class_exists("timelineExpressBase"))
452
  'name' => __( '', 'timeline-express' ),
453
  'desc' => __( '', 'timeline-express' ),
454
  'id' => $prefix . 'about',
455
- 'type' => 'custom_about_the_author_callback',
 
456
  ),
457
  ),
458
  );
459
 
460
  // Add other metaboxes as needed
461
  return $meta_boxes;
462
-
463
  }
464
  // End metabox definitions
465
 
466
-
 
 
 
 
 
 
 
 
 
 
 
467
  /* Change Testimonial Title */
468
  public function change_default_announcement_title( $title ){
469
  $screen = get_current_screen();
143
  add_action('admin_init', array( &$this , 'timeline_express_deactivate_license' ) );
144
  // Cross check the validity of our supportl icense , twice a day
145
  add_action('timeline_express_support_license_check', array( &$this , 'crosscheck_support_license' ) );
146
+ // render new custom timeline express date time
147
+ add_action( 'cmb_render_te_date_time_stamp_custom', array($this,'cmb_render_te_date_time_stamp_custom'), 10, 2 );
148
+ // render new custom timeline express about metabox
149
+ add_action( 'cmb_render_te_about_metabox', array($this,'cmb_render_te_about_metabox'), 10, 2 );
150
+ // add custom hook to allow users to add there own fields
151
+ add_action('the_action_hook', array( $this, 'the_action_callback' ) );
152
  }
153
 
154
+ /*
155
+ * cmb_render_te_date_time_stamp_custom()
156
+ * render our custom date time stamp field (allows for a default to be set)
157
+ * since @v1.1.5
158
+ */
159
+ function cmb_render_te_date_time_stamp_custom( $field, $meta ) {
160
+ ?>
161
+ <style>
162
+ #ui-datepicker-div { z-index: 99999 !important; }
163
+ #wpbody-content { overflow: hidden !important; }
164
+ .cmb_id_announcement_image td .cmb_upload_button { height: 32px !important; }
165
+ </style>
166
+ <?php
167
+ if( $meta && isset( $meta['date'] ) ){
168
+ echo '<input class="cmb_text_small cmb_datepicker" type="text" name="', $field['id'], '[date]" id="', $field['id'], '_date" value="', '' !== $meta ? $meta['date'] : $field['default'], '" />';
169
+ echo '<p class="cmb_metabox_description">'.$field['desc'].'</p>';
170
+ } else{
171
+ echo '<input class="cmb_text_small cmb_datepicker" type="text" name="', $field['id'], '[date]" id="', $field['id'], '_date" value="' . date('m/d/Y' ) .'" />';
172
+ echo '<p class="cmb_metabox_description">'.$field['desc'].'</p>';
173
+ }
174
+ }
175
+
176
+ /*
177
+ * cmb_validate_te_date_time_stamp_custom()
178
+ * save our custom date time stamp
179
+ * since @v1.1.5
180
+ */
181
+ function cmb_validate_te_date_time_stamp_custom( $value, $new ) {
182
+ if(isset($new['date']) && $new['date'] != ''){
183
+ return strtotime( $new['date'] );
184
+ }
185
+ return '-1';
186
+ }
187
+
188
+
189
+ /*
190
+ * cmb_validate_te_date_time_stamp_custom()
191
+ * render the data contained in our custom about metabox
192
+ * since @v1.1.5
193
+ */
194
+ function cmb_render_te_about_metabox( $field, $meta ) {
195
+ require_once TIMELINE_EXPRESS_PATH . 'lib/about-metabox-template.php';
196
+ }
197
+
198
+
199
  /*
200
  * schedule_timeline_express_support_cron()
201
  * Setup our twice daily transient, to cross check the API key ( if set )
344
  return $new;
345
  }
346
 
 
347
  /*
348
  * include_timeline_express_in_auto_updates();
349
  *
365
 
366
  // enqueue metabox for the announcement cpt
367
  public function timeline_express_initialize_cmb_meta_boxes() {
368
+ if ( ! class_exists( 'cmb_Meta_Box' ) ){
369
+ require_once( TIMELINE_EXPRESS_PATH . 'lib/cmb_metaboxes/init.php' );
370
+ }
371
+ }
372
+
373
  // Register Announcement Custom Post Type
374
  public function timeline_express_generate_announcement_post_type() {
375
 
438
  * @return array
439
  */
440
  public function cmb_timeline_announcement_metaboxes( array $meta_boxes ) {
441
+
442
  // Start with an underscore to hide fields from custom fields list
443
  $prefix = 'announcement_';
444
+
445
+ // setup an empty field type for users to customize
446
+ $custom_field = array(
447
+ 'name' => __( '', 'timeline-express' ),
448
+ 'desc' => __( '', 'timeline-express' ),
449
+ 'id' => '',
450
+ 'type' => '',
451
+ );
452
+
453
+ // set up our array of fields
454
+ $field_array = array(
455
+ array(
456
  'name' => __( 'Announcement Color', 'timeline-express' ),
457
  'desc' => __( 'select the color for this announcement.', 'timeline-express' ),
458
  'id' => $prefix . 'color',
459
  'type' => 'colorpicker',
460
+ 'default' => $this->timeline_express_optionVal['default-announcement-color'],
461
  // 'repeatable' => true,
462
  // 'on_front' => false, // Optionally designate a field to wp-admin only
463
  ),
464
  array(
465
+ 'name' => __( 'Font Awesome Class', 'timeline-express' ),
466
  'desc' => __( 'enter the font-awesome class name in the box above. This is used for the icon associated with the announcement. <a href="http://fortawesome.github.io/Font-Awesome/cheatsheet/" target="_blank">cheat sheet</a> Example : "fa-times-circle" ', 'timeline-express' ),
467
  'id' => $prefix . 'icon',
468
  'type' => 'text_medium',
469
+ 'default' => trim( $this->timeline_express_optionVal['default-announcement-icon'] ),
470
  // 'repeatable' => true,
471
  // 'on_front' => false, // Optionally designate a field to wp-admin only
472
  ),
474
  'name' => __( 'Announcement Date', 'timeline-express' ),
475
  'desc' => __( 'enter the date of the announcement. the announcements will appear in chronological order according to this date. ', 'timeline-express' ),
476
  'id' => $prefix . 'date',
477
+ 'type' => 'te_date_time_stamp_custom',
478
+ 'default' => date( 'm/d/Y' ),
479
  // 'repeatable' => true,
480
  // 'on_front' => false, // Optionally designate a field to wp-admin only
481
  ),
487
  // 'repeatable' => true,
488
  // 'on_front' => false, // Optionally designate a field to wp-admin only
489
  ),
490
+ );
491
+
492
+ //Filter here is to allow extra fields to be added
493
+ // loop to add fields to our array
494
+ $custom_fields = apply_filters( 'timeline_express_custom_fields', $custom_field );
495
+ $i = 0;
496
+ foreach( $custom_fields as $user_defined_field ) {
497
+ if( $custom_fields[$i]['name'] != '' ) {
498
+ $field_array[] = $custom_fields[$i];
499
+ }
500
+ $i++;
501
+ }
502
+
503
+ $meta_boxes['announcement_info'] = array(
504
+ 'id' => 'announcement_info',
505
+ 'title' => __( 'Announcement Info.', 'timeline-express' ),
506
+ 'pages' => array( 'te_announcements', ), // Post type
507
+ 'context' => 'advanced',
508
+ 'priority' => 'high',
509
+ 'show_names' => true, // Show field names on the left
510
+ // 'cmb_styles' => true, // Enqueue the CMB stylesheet on the frontend
511
+ 'fields' => $field_array
512
  );
513
 
514
  $meta_boxes['about_the_author'] = array(
524
  'name' => __( '', 'timeline-express' ),
525
  'desc' => __( '', 'timeline-express' ),
526
  'id' => $prefix . 'about',
527
+ // 'type' => 'custom_about_the_author_callback',
528
+ 'type' => 'te_about_metabox',
529
  ),
530
  ),
531
  );
532
 
533
  // Add other metaboxes as needed
534
  return $meta_boxes;
535
+
536
  }
537
  // End metabox definitions
538
 
539
+ function the_action_callback() {
540
+ $field = array(
541
+ 'name' => __( 'Announcement Image', 'timeline-express' ),
542
+ 'desc' => __( 'select a banner image for this announcement (optional). (recommended 650px wide or larger) ', 'timeline-express' ),
543
+ 'id' => $prefix . 'image',
544
+ 'type' => 'file',
545
+ // 'repeatable' => true,
546
+ // 'on_front' => false, // Optionally designate a field to wp-admin only
547
+ );
548
+ return $field;
549
+ }
550
+
551
  /* Change Testimonial Title */
552
  public function change_default_announcement_title( $title ){
553
  $screen = get_current_screen();
lib/{metabox/about-template.php → about-metabox-template.php} RENAMED
File without changes
lib/cmb_metaboxes/helpers/cmb_Meta_Box_Sanitize.php ADDED
@@ -0,0 +1,346 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * CMB field validation
5
+ * @since 0.0.4
6
+ */
7
+ class cmb_Meta_Box_Sanitize {
8
+
9
+ /**
10
+ * A CMB field object
11
+ * @var cmb_Meta_Box_field object
12
+ */
13
+ public $field;
14
+
15
+ /**
16
+ * Field's $_POST value
17
+ * @var mixed
18
+ */
19
+ public $value;
20
+
21
+ /**
22
+ * Setup our class vars
23
+ * @since 1.1.0
24
+ * @param object $field A CMB field object
25
+ * @param mixed $value Field value
26
+ */
27
+ public function __construct( $field, $value ) {
28
+ $this->field = $field;
29
+ $this->value = $value;
30
+ $this->object_id = cmb_Meta_Box::get_object_id();
31
+ $this->object_type = cmb_Meta_Box::get_object_type();
32
+ }
33
+
34
+ /**
35
+ * Catchall method if field's 'sanitization_cb' is NOT defined, or field type does not have a corresponding validation method
36
+ * @since 1.0.0
37
+ * @param string $name Non-existent method name
38
+ * @param array $arguments All arguments passed to the method
39
+ */
40
+ public function __call( $name, $arguments ) {
41
+ list( $value ) = $arguments;
42
+ return $this->default_sanitization( $value );
43
+ }
44
+
45
+ /**
46
+ * Default fallback sanitization method. Applies filters.
47
+ * @since 1.0.2
48
+ * @param mixed $value Meta value
49
+ */
50
+ public function default_sanitization( $value ) {
51
+
52
+ // Allow field type validation via filter
53
+ $updated = apply_filters( 'cmb_validate_'. $this->field->type(), null, $value, $this->object_id, $this->field->args(), $this );
54
+
55
+ if ( null !== $updated )
56
+ return $updated;
57
+
58
+ switch ( $this->field->type() ) {
59
+ case 'wysiwyg':
60
+ // $value = wp_kses( $value );
61
+ // break;
62
+ case 'textarea_small':
63
+ return $this->textarea( $value );
64
+ case 'taxonomy_select':
65
+ case 'taxonomy_radio':
66
+ case 'taxonomy_multicheck':
67
+ if ( $this->field->args( 'taxonomy' ) ) {
68
+ return wp_set_object_terms( $this->object_id, $value, $this->field->args( 'taxonomy' ) );
69
+ }
70
+ case 'multicheck':
71
+ case 'file_list':
72
+ case 'oembed':
73
+ // no filtering
74
+ return $value;
75
+ default:
76
+ // Handle repeatable fields array
77
+ // We'll fallback to 'sanitize_text_field'
78
+ return is_array( $value ) ? array_map( 'sanitize_text_field', $value ) : call_user_func( 'sanitize_text_field', $value );
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Simple checkbox validation
84
+ * @since 1.0.1
85
+ * @param mixed $val 'on' or false
86
+ * @return mixed 'on' or false
87
+ */
88
+ public function checkbox( $value ) {
89
+ return $value === 'on' ? 'on' : false;
90
+ }
91
+
92
+ /**
93
+ * Validate url in a meta value
94
+ * @since 1.0.1
95
+ * @param string $value Meta value
96
+ * @return string Empty string or escaped url
97
+ */
98
+ public function text_url( $value ) {
99
+ $protocols = $this->field->args( 'protocols' );
100
+ // for repeatable
101
+ if ( is_array( $value ) ) {
102
+ foreach ( $value as $key => $val ) {
103
+ $value[ $key ] = $val ? esc_url_raw( $val, $protocols ) : $this->field->args( 'default' );
104
+ }
105
+ } else {
106
+ $value = $value ? esc_url_raw( $value, $protocols ) : $this->field->args( 'default' );
107
+ }
108
+
109
+ return $value;
110
+ }
111
+
112
+ public function colorpicker( $value ) {
113
+ // for repeatable
114
+ if ( is_array( $value ) ) {
115
+ $check = $value;
116
+ $value = array();
117
+ foreach ( $check as $key => $val ) {
118
+ if ( $val && '#' != $val ) {
119
+ $value[ $key ] = esc_attr( $val );
120
+ }
121
+ }
122
+ } else {
123
+ $value = ! $value || '#' == $value ? '' : esc_attr( $value );
124
+ }
125
+ return $value;
126
+ }
127
+
128
+ /**
129
+ * Validate email in a meta value
130
+ * @since 1.0.1
131
+ * @param string $value Meta value
132
+ * @return string Empty string or validated email
133
+ */
134
+ public function text_email( $value ) {
135
+ // for repeatable
136
+ if ( is_array( $value ) ) {
137
+ foreach ( $value as $key => $val ) {
138
+ $val = trim( $val );
139
+ $value[ $key ] = is_email( $val ) ? $val : '';
140
+ }
141
+ } else {
142
+ $value = trim( $value );
143
+ $value = is_email( $value ) ? $value : '';
144
+ }
145
+
146
+ return $value;
147
+ }
148
+
149
+ /**
150
+ * Validate money in a meta value
151
+ * @since 1.0.1
152
+ * @param string $value Meta value
153
+ * @return string Empty string or validated money value
154
+ */
155
+ public function text_money( $value ) {
156
+
157
+ global $wp_locale;
158
+
159
+ $search = array( $wp_locale->number_format['thousands_sep'], $wp_locale->number_format['decimal_point'] );
160
+ $replace = array( '', '.' );
161
+
162
+ // for repeatable
163
+ if ( is_array( $value ) ) {
164
+ foreach ( $value as $key => $val ) {
165
+ $value[ $key ] = number_format_i18n( (float) str_ireplace( $search, $replace, $val ), 2 );
166
+ }
167
+ } else {
168
+ $value = number_format_i18n( (float) str_ireplace( $search, $replace, $value ), 2 );
169
+ }
170
+
171
+ return $value;
172
+ }
173
+
174
+ /**
175
+ * Converts text date to timestamp
176
+ * @since 1.0.2
177
+ * @param string $value Meta value
178
+ * @return string Timestring
179
+ */
180
+ public function text_date_timestamp( $value ) {
181
+ return is_array( $value ) ? array_map( 'strtotime', $value ) : strtotime( $value );
182
+ }
183
+
184
+ /**
185
+ * Datetime to timestamp
186
+ * @since 1.0.1
187
+ * @param string $value Meta value
188
+ * @return string Timestring
189
+ */
190
+ public function text_datetime_timestamp( $value, $repeat = false ) {
191
+
192
+ $test = is_array( $value ) ? array_filter( $value ) : '';
193
+ if ( empty( $test ) )
194
+ return '';
195
+
196
+ if ( $repeat_value = $this->_check_repeat( $value, __FUNCTION__, $repeat ) )
197
+ return $repeat_value;
198
+
199
+ $value = strtotime( $value['date'] .' '. $value['time'] );
200
+
201
+ if ( $tz_offset = $this->field->field_timezone_offset() )
202
+ $value += $tz_offset;
203
+
204
+ return $value;
205
+ }
206
+
207
+ /**
208
+ * Datetime to imestamp with timezone
209
+ * @since 1.0.1
210
+ * @param string $value Meta value
211
+ * @return string Timestring
212
+ */
213
+ public function text_datetime_timestamp_timezone( $value, $repeat = false ) {
214
+
215
+ $test = is_array( $value ) ? array_filter( $value ) : '';
216
+ if ( empty( $test ) )
217
+ return '';
218
+
219
+ if ( $repeat_value = $this->_check_repeat( $value, __FUNCTION__, $repeat ) )
220
+ return $repeat_value;
221
+
222
+ $tzstring = null;
223
+
224
+ if ( is_array( $value ) && array_key_exists( 'timezone', $value ) )
225
+ $tzstring = $value['timezone'];
226
+
227
+ if ( empty( $tzstring ) )
228
+ $tzstring = cmb_Meta_Box::timezone_string();
229
+
230
+ $offset = cmb_Meta_Box::timezone_offset( $tzstring, true );
231
+
232
+ if ( substr( $tzstring, 0, 3 ) === 'UTC' )
233
+ $tzstring = timezone_name_from_abbr( '', $offset, 0 );
234
+
235
+ $value = new DateTime( $value['date'] .' '. $value['time'], new DateTimeZone( $tzstring ) );
236
+ $value = serialize( $value );
237
+
238
+ return $value;
239
+ }
240
+
241
+ /**
242
+ * Sanitize textareas and wysiwyg fields
243
+ * @since 1.0.1
244
+ * @param string $value Meta value
245
+ * @return string Sanitized data
246
+ */
247
+ public function textarea( $value ) {
248
+ return is_array( $value ) ? array_map( 'wp_kses_post', $value ) : wp_kses_post( $value );
249
+ }
250
+
251
+ /**
252
+ * Sanitize code textareas
253
+ * @since 1.0.2
254
+ * @param string $value Meta value
255
+ * @return string Sanitized data
256
+ */
257
+ public function textarea_code( $value, $repeat = false ) {
258
+ if ( $repeat_value = $this->_check_repeat( $value, __FUNCTION__, $repeat ) )
259
+ return $repeat_value;
260
+
261
+ return htmlspecialchars_decode( stripslashes( $value ) );
262
+ }
263
+
264
+ /**
265
+ * Peforms saving of `file` attachement's ID
266
+ * @since 1.1.0
267
+ * @param string $value File url
268
+ */
269
+ public function _save_file_id( $value ) {
270
+ $group = $this->field->group;
271
+ $args = $this->field->args();
272
+ $args['id'] = $args['_id'] . '_id';
273
+
274
+ unset( $args['_id'], $args['_name'] );
275
+ // And get new field object
276
+ $field = new cmb_Meta_Box_field( $args, $group );
277
+ $id_key = $field->_id();
278
+ $id_val_old = $field->escaped_value( 'absint' );
279
+
280
+ if ( $group ) {
281
+ // Check group $_POST data
282
+ $i = $group->index;
283
+ $base_id = $group->_id();
284
+ $id_val = isset( $_POST[ $base_id ][ $i ][ $id_key ] ) ? absint( $_POST[ $base_id ][ $i ][ $id_key ] ) : 0;
285
+
286
+ } else {
287
+ // Check standard $_POST data
288
+ $id_val = isset( $_POST[ $field->id() ] ) ? $_POST[ $field->id() ] : null;
289
+
290
+ }
291
+
292
+ // If there is no ID saved yet, try to get it from the url
293
+ if ( $value && ! $id_val ) {
294
+ $id_val = cmb_Meta_Box::image_id_from_url( $value );
295
+ }
296
+
297
+ if ( $group ) {
298
+ return array(
299
+ 'attach_id' => $id_val,
300
+ 'field_id' => $id_key
301
+ );
302
+ }
303
+
304
+ if ( $id_val && $id_val != $id_val_old ) {
305
+ return $field->update_data( $id_val );
306
+ } elseif ( empty( $id_val ) && $id_val_old ) {
307
+ return $field->remove_data( $old );
308
+ }
309
+ }
310
+
311
+ /**
312
+ * Handles saving of attachment post ID and sanitizing file url
313
+ * @since 1.1.0
314
+ * @param string $value File url
315
+ * @return string Sanitized url
316
+ */
317
+ public function file( $value ) {
318
+ // If NOT specified to NOT save the file ID
319
+ if ( $this->field->args( 'save_id' ) ) {
320
+ $id_value = $this->_save_file_id( $value );
321
+ }
322
+ $clean = $this->text_url( $value );
323
+
324
+ // Return an array with url/id if saving a group field
325
+ return $this->field->group ? array_merge( array( 'url' => $clean), $id_value ) : $clean;
326
+ }
327
+
328
+ /**
329
+ * If repeating, loop through and re-apply sanitization method
330
+ * @since 1.1.0
331
+ * @param mixed $value Meta value
332
+ * @param string $method Class method
333
+ * @param bool $repeat Whether repeating or not
334
+ * @return mixed Sanitized value
335
+ */
336
+ public function _check_repeat( $value, $method, $repeat ) {
337
+ if ( $repeat || ! $this->field->args( 'repeatable' ) )
338
+ return;
339
+ $new_value = array();
340
+ foreach ( $value as $iterator => $val ) {
341
+ $new_value[] = $this->$method( $val, true );
342
+ }
343
+ return $new_value;
344
+ }
345
+
346
+ }
lib/{metabox/helpers/timeline_express_MetaBox_filters.php → cmb_metaboxes/helpers/cmb_Meta_Box_Show_Filters.php} RENAMED
@@ -1,65 +1,105 @@
1
- <?php
2
-
3
- /**
4
- * Show On Filters
5
- * Use the 'cmb_show_on' filter to further refine the conditions under which a metabox is displayed.
6
- * Below you can limit it by ID and page template
7
- *
8
- * All methods in this class are automatically filtered
9
- *
10
- * @since 1.0.0
11
- */
12
- class timeline_express_MetaBox_filters {
13
-
14
- /**
15
- * Add metaboxes for an specific ID
16
- * @since 1.0.0
17
- * @param bool $display To display or not
18
- * @param array $meta_box Metabox config array
19
- * @return bool Whether to display this metabox on the current page.
20
- */
21
- public static function check_id( $display, $meta_box ) {
22
-
23
- if ( ! isset( $meta_box['show_on']['key'] ) || 'id' !== $meta_box['show_on']['key'] )
24
- return $display;
25
-
26
- $object_id = cmb_Meta_Box::get_object_id();
27
-
28
- if ( ! $object_id )
29
- return false;
30
-
31
- // If current page id is in the included array, display the metabox
32
- if ( in_array( $object_id, (array) $meta_box['show_on']['value'] ) )
33
- return true;
34
-
35
- return false;
36
- }
37
-
38
- /**
39
- * Add metaboxes for an specific Page Template
40
- * @since 1.0.0
41
- * @param bool $display To display or not
42
- * @param array $meta_box Metabox config array
43
- * @return bool Whether to display this metabox on the current page.
44
- */
45
- public static function check_page_template( $display, $meta_box ) {
46
-
47
- if ( ! isset( $meta_box['show_on']['key'] ) || 'page-template' !== $meta_box['show_on']['key'] )
48
- return $display;
49
-
50
- $object_id = cmb_Meta_Box::get_object_id();
51
-
52
- if ( ! $object_id || cmb_Meta_Box::get_object_type() !== 'post' )
53
- return false;
54
-
55
- // Get current template
56
- $current_template = get_post_meta( $object_id, '_wp_page_template', true );
57
-
58
- // See if there's a match
59
- if ( $current_template && in_array( $current_template, (array) $meta_box['show_on']['value'] ) )
60
- return true;
61
-
62
- return false;
63
- }
64
-
65
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Show On Filters
5
+ * Use the 'cmb_show_on' filter to further refine the conditions under which a metabox is displayed.
6
+ * Below you can limit it by ID and page template
7
+ *
8
+ * All methods in this class are automatically filtered
9
+ *
10
+ * @since 1.0.0
11
+ */
12
+ class cmb_Meta_Box_Show_Filters {
13
+
14
+ /**
15
+ * Add metaboxes for an specific ID
16
+ * @since 1.0.0
17
+ * @param bool $display To display or not
18
+ * @param array $meta_box Metabox config array
19
+ * @return bool Whether to display this metabox on the current page.
20
+ */
21
+ public static function check_id( $display, $meta_box ) {
22
+
23
+ if ( ! isset( $meta_box['show_on']['key'] ) || 'id' !== $meta_box['show_on']['key'] )
24
+ return $display;
25
+
26
+ $object_id = is_admin() ? cmb_Meta_Box::get_object_id() : @get_the_id();
27
+
28
+ if ( ! $object_id )
29
+ return false;
30
+
31
+ // If current page id is in the included array, display the metabox
32
+ return in_array( $object_id, (array) $meta_box['show_on']['value'] );
33
+ }
34
+
35
+ /**
36
+ * Add metaboxes for an specific Page Template
37
+ * @since 1.0.0
38
+ * @param bool $display To display or not
39
+ * @param array $meta_box Metabox config array
40
+ * @return bool Whether to display this metabox on the current page.
41
+ */
42
+ public static function check_page_template( $display, $meta_box ) {
43
+
44
+ if ( ! isset( $meta_box['show_on']['key'] ) || 'page-template' !== $meta_box['show_on']['key'] )
45
+ return $display;
46
+
47
+ $object_id = cmb_Meta_Box::get_object_id();
48
+
49
+ if ( ! $object_id || cmb_Meta_Box::get_object_type() !== 'post' )
50
+ return false;
51
+
52
+ // Get current template
53
+ $current_template = get_post_meta( $object_id, '_wp_page_template', true );
54
+
55
+ // See if there's a match
56
+ if ( $current_template && in_array( $current_template, (array) $meta_box['show_on']['value'] ) )
57
+ return true;
58
+
59
+ return false;
60
+ }
61
+
62
+ /**
63
+ * Only show options-page metaboxes on their options page (but only enforce on the admin side)
64
+ * @since 1.0.0
65
+ * @param bool $display To display or not
66
+ * @param array $meta_box Metabox config array
67
+ * @return bool Whether to display this metabox on the current page.
68
+ */
69
+ public static function check_admin_page( $display, $meta_box ) {
70
+
71
+ // check if this is a 'options-page' metabox
72
+ if ( ! isset( $meta_box['show_on']['key'] ) || 'options-page' !== $meta_box['show_on']['key'] )
73
+ return $display;
74
+
75
+ // Enforce 'show_on' filter in the admin
76
+ if ( is_admin() ) {
77
+
78
+ // If there is no 'page' query var, our filter isn't applicable
79
+ if ( ! isset( $_GET['page'] ) )
80
+ return $display;
81
+
82
+ if ( ! isset( $meta_box['show_on']['value'] ) )
83
+ return false;
84
+
85
+ $pages = $meta_box['show_on']['value'];
86
+
87
+ if ( is_array( $pages ) ) {
88
+ foreach ( $pages as $page ) {
89
+ if ( $_GET['page'] == $page )
90
+ return true;
91
+ }
92
+ } else {
93
+ if ( $_GET['page'] == $pages )
94
+ return true;
95
+ }
96
+
97
+ return false;
98
+
99
+ }
100
+
101
+ // Allow options-page metaboxes to be displayed anywhere on the front-end
102
+ return true;
103
+ }
104
+
105
+ }
lib/{metabox/helpers/timeline_express_MetaBox_ajax.php → cmb_metaboxes/helpers/cmb_Meta_Box_ajax.php} RENAMED
@@ -1,180 +1,203 @@
1
- <?php
2
-
3
- /**
4
- * CMB ajax methods
5
- * (i.e. a lot of work to get oEmbeds to work with non-post objects)
6
- *
7
- * @since 0.9.5
8
- */
9
- class timeline_express_MetaBox_ajax {
10
-
11
- // A single instance of this class.
12
- public static $instance = null;
13
- // Whether to hijack the oembed cache system
14
- public static $hijack = false;
15
- public static $object_id = 0;
16
- public static $embed_args = array();
17
- public static $object_type = 'post';
18
-
19
- /**
20
- * Creates or returns an instance of this class.
21
- * @since 0.1.0
22
- * @return cmb_Meta_Box_types A single instance of this class.
23
- */
24
- public static function get() {
25
- if ( self::$instance === null )
26
- self::$instance = new self();
27
-
28
- return self::$instance;
29
- }
30
-
31
- /**
32
- * Handles our oEmbed ajax request
33
- * @since 0.9.5
34
- * @return object oEmbed embed code | fallback | error message
35
- */
36
- public function oembed_handler() {
37
-
38
- // verify our nonce
39
- if ( ! ( isset( $_REQUEST['cmb_ajax_nonce'], $_REQUEST['oembed_url'] ) && wp_verify_nonce( $_REQUEST['cmb_ajax_nonce'], 'ajax_nonce' ) ) )
40
- die();
41
-
42
- // sanitize our search string
43
- $oembed_string = sanitize_text_field( $_REQUEST['oembed_url'] );
44
-
45
- // send back error if empty
46
- if ( empty( $oembed_string ) )
47
- self::send_result( '<p class="ui-state-error-text">'. __( 'Please Try Again', 'cmb' ) .'</p>', false );
48
-
49
- // Set width of embed
50
- $embed_width = isset( $_REQUEST['oembed_width'] ) && intval( $_REQUEST['oembed_width'] ) < 640 ? intval( $_REQUEST['oembed_width'] ) : '640';
51
-
52
- // set url
53
- $oembed_url = esc_url( $oembed_string );
54
- // set args
55
- $embed_args = array( 'width' => $embed_width );
56
-
57
- // Get embed code (or fallback link)
58
- $html = self::get_oembed( $oembed_url, $_REQUEST['object_id'], array(
59
- 'object_type' => isset( $_REQUEST['object_type'] ) ? $_REQUEST['object_type'] : 'post',
60
- 'oembed_args' => $embed_args,
61
- 'field_id' => $_REQUEST['field_id'],
62
- ) );
63
-
64
- self::send_result( $html );
65
-
66
- }
67
-
68
- /**
69
- * Retrieves oEmbed from url/object ID
70
- * @since 0.9.5
71
- * @param string $url URL to retrieve oEmbed
72
- * @param int $object_id Object ID
73
- * @param array $args Arguments for method
74
- * @return string html markup with embed or fallback
75
- */
76
- public function get_oembed( $url, $object_id, $args = array() ) {
77
- global $wp_embed;
78
-
79
- $oembed_url = esc_url( $url );
80
- self::$object_id = absint( $object_id );
81
-
82
- $args = self::$embed_args = wp_parse_args( $args, array(
83
- 'object_type' => 'post',
84
- 'oembed_args' => self::$embed_args,
85
- 'field_id' => false,
86
- ) );
87
-
88
- // set the post_ID so oEmbed won't fail
89
- $wp_embed->post_ID = self::$object_id;
90
-
91
- // Special scenario if NOT a post object
92
- if ( isset( $args['object_type'] ) && $args['object_type'] != 'post' ) {
93
-
94
- // Ok, we need to hijack the oembed cache system
95
- self::$hijack = true;
96
- self::$object_type = $args['object_type'];
97
-
98
- // Gets ombed cache from our object's meta (vs postmeta)
99
- add_filter( 'get_post_metadata', array( 'cmb_Meta_Box_ajax', 'hijack_oembed_cache_get' ), 10, 3 );
100
- // Sets ombed cache in our object's meta (vs postmeta)
101
- add_filter( 'update_post_metadata', array( 'cmb_Meta_Box_ajax', 'hijack_oembed_cache_set' ), 10, 4 );
102
-
103
- }
104
-
105
- $embed_args = '';
106
- foreach ( $args['oembed_args'] as $key => $val ) {
107
- $embed_args .= " $key=\"$val\"";
108
- }
109
-
110
- // ping WordPress for an embed
111
- $check_embed = $wp_embed->run_shortcode( '[embed'. $embed_args .']'. $oembed_url .'[/embed]' );
112
-
113
- // fallback that WordPress creates when no oEmbed was found
114
- $fallback = $wp_embed->maybe_make_link( $oembed_url );
115
-
116
- // Send back our embed
117
- if ( $check_embed && $check_embed != $fallback )
118
- return '<div class="embed_status">'. $check_embed .'<p><a href="#" class="cmb_remove_file_button" rel="'. $args['field_id'] .'">'. __( 'Remove Embed', 'cmb' ) .'</a></p></div>';
119
-
120
- // Otherwise, send back error info that no oEmbeds were found
121
- return '<p class="ui-state-error-text">'. sprintf( __( 'No oEmbed Results Found for %s. View more info at', 'cmb' ), $fallback ) .' <a href="http://codex.wordpress.org/Embeds" target="_blank">codex.wordpress.org/Embeds</a>.</p>';
122
-
123
- }
124
-
125
- /**
126
- * Hijacks retrieving of cached oEmbed.
127
- * Returns cached data from relevant object metadata (vs postmeta)
128
- *
129
- * @since 0.9.5
130
- * @param boolean $check Whether to retrieve postmeta or override
131
- * @param int $object_id Object ID
132
- * @param string $meta_key Object metakey
133
- * @return mixed Object's oEmbed cached data
134
- */
135
- public function hijack_oembed_cache_get( $check, $object_id, $meta_key ) {
136
-
137
- if ( ! self::$hijack || $object_id != self::$object_id )
138
- return $check;
139
-
140
- // get cached data
141
- return get_metadata( self::$object_type, $object_id, $meta_key, true );
142
-
143
- }
144
-
145
- /**
146
- * Hijacks saving of cached oEmbed.
147
- * Saves cached data to relevant object metadata (vs postmeta)
148
- *
149
- * @since 0.9.5
150
- * @param boolean $check Whether to continue setting postmeta
151
- * @param int $object_id Object ID to get postmeta from
152
- * @param string $meta_key Postmeta's key
153
- * @param mixed $meta_value Value of the postmeta to be saved
154
- * @return boolean Whether to continue setting
155
- */
156
- public function hijack_oembed_cache_set( $check, $object_id, $meta_key, $meta_value ) {
157
- if ( ! self::$hijack || $object_id != self::$object_id )
158
- return $check;
159
-
160
- // Cache the result to our metadata
161
- update_metadata( self::$object_type, $object_id, $meta_key, $meta_value );
162
-
163
- // Anything other than `null` to cancel saving to postmeta
164
- return true;
165
- }
166
-
167
- /**
168
- * Helper to send json encoded response to ajax
169
- * @since 0.9.5
170
- * @param string $data Data to be shown via ajax
171
- * @param boolean $success Success or fail
172
- */
173
- public static function send_result( $data, $success = true ) {
174
- $found = $success ? 'found' : 'not found';
175
- // send back our encoded data
176
- echo json_encode( array( 'result' => $data, 'id' => $found ) );
177
- die();
178
- }
179
-
180
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * CMB ajax methods
5
+ * (i.e. a lot of work to get oEmbeds to work with non-post objects)
6
+ *
7
+ * @since 0.9.5
8
+ */
9
+ class cmb_Meta_Box_ajax {
10
+
11
+ // A single instance of this class.
12
+ public static $instance = null;
13
+ // Whether to hijack the oembed cache system
14
+ public static $hijack = false;
15
+ public static $object_id = 0;
16
+ public static $embed_args = array();
17
+ public static $object_type = 'post';
18
+
19
+ /**
20
+ * Creates or returns an instance of this class.
21
+ * @since 0.1.0
22
+ * @return cmb_Meta_Box_ajax A single instance of this class.
23
+ */
24
+ public static function get() {
25
+ if ( self::$instance === null )
26
+ self::$instance = new self();
27
+
28
+ return self::$instance;
29
+ }
30
+
31
+ /**
32
+ * Handles our oEmbed ajax request
33
+ * @since 0.9.5
34
+ * @return object oEmbed embed code | fallback | error message
35
+ */
36
+ public function oembed_handler() {
37
+
38
+ // verify our nonce
39
+ if ( ! ( isset( $_REQUEST['cmb_ajax_nonce'], $_REQUEST['oembed_url'] ) && wp_verify_nonce( $_REQUEST['cmb_ajax_nonce'], 'ajax_nonce' ) ) )
40
+ die();
41
+
42
+ // sanitize our search string
43
+ $oembed_string = sanitize_text_field( $_REQUEST['oembed_url'] );
44
+
45
+ // send back error if empty
46
+ if ( empty( $oembed_string ) )
47
+ self::send_result( '<p class="ui-state-error-text">'. __( 'Please Try Again', 'cmb' ) .'</p>', false );
48
+
49
+ // Set width of embed
50
+ $embed_width = isset( $_REQUEST['oembed_width'] ) && intval( $_REQUEST['oembed_width'] ) < 640 ? intval( $_REQUEST['oembed_width'] ) : '640';
51
+
52
+ // set url
53
+ $oembed_url = esc_url( $oembed_string );
54
+ // set args
55
+ $embed_args = array( 'width' => $embed_width );
56
+
57
+ // Get embed code (or fallback link)
58
+ $html = self::get_oembed( $oembed_url, $_REQUEST['object_id'], array(
59
+ 'object_type' => isset( $_REQUEST['object_type'] ) ? $_REQUEST['object_type'] : 'post',
60
+ 'oembed_args' => $embed_args,
61
+ 'field_id' => $_REQUEST['field_id'],
62
+ ) );
63
+
64
+ self::send_result( $html );
65
+
66
+ }
67
+
68
+ /**
69
+ * Retrieves oEmbed from url/object ID
70
+ * @since 0.9.5
71
+ * @param string $url URL to retrieve oEmbed
72
+ * @param int $object_id Object ID
73
+ * @param array $args Arguments for method
74
+ * @return string html markup with embed or fallback
75
+ */
76
+ public static function get_oembed( $url, $object_id, $args = array() ) {
77
+ global $wp_embed;
78
+
79
+ $oembed_url = esc_url( $url );
80
+
81
+ // Sanitize object_id
82
+ self::$object_id = is_numeric( $object_id ) ? absint( $object_id ) : sanitize_text_field( $object_id );
83
+
84
+ $args = wp_parse_args( $args, array(
85
+ 'object_type' => 'post',
86
+ 'oembed_args' => self::$embed_args,
87
+ 'field_id' => false,
88
+ 'cache_key' => false,
89
+ ) );
90
+
91
+ self::$embed_args =& $args;
92
+
93
+ // set the post_ID so oEmbed won't fail
94
+ // wp-includes/class-wp-embed.php, WP_Embed::shortcode(), line 162
95
+ $wp_embed->post_ID = self::$object_id;
96
+
97
+ // Special scenario if NOT a post object
98
+ if ( isset( $args['object_type'] ) && $args['object_type'] != 'post' ) {
99
+
100
+ if ( 'options-page' == $args['object_type'] ) {
101
+ // bogus id to pass some numeric checks
102
+ // Issue with a VERY large WP install?
103
+ $wp_embed->post_ID = 1987645321;
104
+ // Use our own cache key to correspond to this field (vs one cache key per url)
105
+ $args['cache_key'] = $args['field_id'] .'_cache';
106
+ }
107
+ // Ok, we need to hijack the oembed cache system
108
+ self::$hijack = true;
109
+ self::$object_type = $args['object_type'];
110
+
111
+ // Gets ombed cache from our object's meta (vs postmeta)
112
+ add_filter( 'get_post_metadata', array( 'cmb_Meta_Box_ajax', 'hijack_oembed_cache_get' ), 10, 3 );
113
+ // Sets ombed cache in our object's meta (vs postmeta)
114
+ add_filter( 'update_post_metadata', array( 'cmb_Meta_Box_ajax', 'hijack_oembed_cache_set' ), 10, 4 );
115
+
116
+ }
117
+
118
+ $embed_args = '';
119
+ foreach ( $args['oembed_args'] as $key => $val ) {
120
+ $embed_args .= " $key=\"$val\"";
121
+ }
122
+
123
+ // ping WordPress for an embed
124
+ $check_embed = $wp_embed->run_shortcode( '[embed'. $embed_args .']'. $oembed_url .'[/embed]' );
125
+
126
+ // fallback that WordPress creates when no oEmbed was found
127
+ $fallback = $wp_embed->maybe_make_link( $oembed_url );
128
+
129
+ // Send back our embed
130
+ if ( $check_embed && $check_embed != $fallback )
131
+ return '<div class="embed_status">'. $check_embed .'<p class="cmb_remove_wrapper"><a href="#" class="cmb_remove_file_button" rel="'. $args['field_id'] .'">'. __( 'Remove Embed', 'cmb' ) .'</a></p></div>';
132
+
133
+ // Otherwise, send back error info that no oEmbeds were found
134
+ return '<p class="ui-state-error-text">'. sprintf( __( 'No oEmbed Results Found for %s. View more info at', 'cmb' ), $fallback ) .' <a href="http://codex.wordpress.org/Embeds" target="_blank">codex.wordpress.org/Embeds</a>.</p>';
135
+
136
+ }
137
+
138
+ /**
139
+ * Hijacks retrieving of cached oEmbed.
140
+ * Returns cached data from relevant object metadata (vs postmeta)
141
+ *
142
+ * @since 0.9.5
143
+ * @param boolean $check Whether to retrieve postmeta or override
144
+ * @param int $object_id Object ID
145
+ * @param string $meta_key Object metakey
146
+ * @return mixed Object's oEmbed cached data
147
+ */
148
+ public static function hijack_oembed_cache_get( $check, $object_id, $meta_key ) {
149
+
150
+ if ( ! self::$hijack || ( self::$object_id != $object_id && 1987645321 !== $object_id ) )
151
+ return $check;
152
+
153
+ // get cached data
154
+ $data = 'options-page' === self::$object_type
155
+ ? cmb_Meta_Box::get_option( self::$object_id, self::$embed_args['cache_key'] )
156
+ : get_metadata( self::$object_type, self::$object_id, $meta_key, true );
157
+
158
+ return $data;
159
+ }
160
+
161
+ /**
162
+ * Hijacks saving of cached oEmbed.
163
+ * Saves cached data to relevant object metadata (vs postmeta)
164
+ *
165
+ * @since 0.9.5
166
+ * @param boolean $check Whether to continue setting postmeta
167
+ * @param int $object_id Object ID to get postmeta from
168
+ * @param string $meta_key Postmeta's key
169
+ * @param mixed $meta_value Value of the postmeta to be saved
170
+ * @return boolean Whether to continue setting
171
+ */
172
+ public static function hijack_oembed_cache_set( $check, $object_id, $meta_key, $meta_value ) {
173
+ if ( ! self::$hijack || ( self::$object_id != $object_id && 1987645321 !== $object_id ) )
174
+ return $check;
175
+
176
+ // Cache the result to our metadata
177
+ if ( 'options-page' === self::$object_type ) {
178
+ // Set the option
179
+ cmb_Meta_Box::update_option( self::$object_id, self::$embed_args['cache_key'], $meta_value, array( 'type' => 'oembed' ) );
180
+ // Save the option
181
+ cmb_Meta_Box::save_option( self::$object_id );
182
+ } else {
183
+ update_metadata( self::$object_type, self::$object_id, $meta_key, $meta_value );
184
+ }
185
+
186
+ // Anything other than `null` to cancel saving to postmeta
187
+ return true;
188
+ }
189
+
190
+ /**
191
+ * Helper to send json encoded response to ajax
192
+ * @since 0.9.5
193
+ * @param string $data Data to be shown via ajax
194
+ * @param boolean $success Success or fail
195
+ */
196
+ public static function send_result( $data, $success = true ) {
197
+ $found = $success ? 'found' : 'not found';
198
+ // send back our encoded data
199
+ echo json_encode( array( 'result' => $data, 'id' => $found ) );
200
+ die();
201
+ }
202
+
203
+ }
lib/cmb_metaboxes/helpers/cmb_Meta_Box_field.php ADDED
@@ -0,0 +1,497 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * CMB field class
5
+ * @since 1.1.0
6
+ */
7
+ class cmb_Meta_Box_field {
8
+
9
+ /**
10
+ * Metabox object id
11
+ * @var mixed
12
+ * @since 1.1.0
13
+ */
14
+ public $object_id;
15
+
16
+ /**
17
+ * Metabox object type
18
+ * @var mixed
19
+ * @since 1.1.0
20
+ */
21
+ public $object_type;
22
+
23
+ /**
24
+ * Field arguments
25
+ * @var mixed
26
+ * @since 1.1.0
27
+ */
28
+ public $args;
29
+
30
+ /**
31
+ * Field group object
32
+ * @var mixed
33
+ * @since 1.1.0
34
+ */
35
+ public $group;
36
+
37
+ /**
38
+ * Field meta value
39
+ * @var mixed
40
+ * @since 1.1.0
41
+ */
42
+ public $value;
43
+
44
+ /**
45
+ * Constructs our field object
46
+ * @since 1.1.0
47
+ * @param array $field_args Field arguments
48
+ * @param array $group_field (optional) Group field object
49
+ */
50
+ public function __construct( $field_args, $group_field = null ) {
51
+ $this->object_id = cmb_Meta_Box::get_object_id();
52
+ $this->object_type = cmb_Meta_Box::get_object_type();
53
+ $this->group = ! empty( $group_field ) ? $group_field : false;
54
+ $this->args = $this->_set_field_defaults( $field_args );
55
+
56
+ // Allow an override for the field's value
57
+ // (assuming no one would want to save 'cmb_no_override_val' as a value)
58
+ $this->value = apply_filters( 'cmb_override_meta_value', 'cmb_no_override_val', $this->object_id, $this->args(), $this->object_type, $this );
59
+
60
+ // If no override, get our meta
61
+ $this->value = 'cmb_no_override_val' === $this->value
62
+ ? $this->get_data()
63
+ : $this->value;
64
+ }
65
+
66
+ /**
67
+ * Non-existent methods fallback to checking for field arguments of the same name
68
+ * @since 1.1.0
69
+ * @param string $name Method name
70
+ * @param array $arguments Array of passed-in arguments
71
+ * @return mixed Value of field argument
72
+ */
73
+ public function __call( $name, $arguments ) {
74
+ $key = isset( $arguments[0] ) ? $arguments[0] : false;
75
+ return $this->args( $name, $key );
76
+ }
77
+
78
+ /**
79
+ * Retrieves the field id
80
+ * @since 1.1.0
81
+ * @param boolean $raw Whether to retrieve pre-modidifed id
82
+ * @return string Field id
83
+ */
84
+ public function id( $raw = false ) {
85
+ $id = $raw ? '_id' : 'id';
86
+ return $this->args( $id );
87
+ }
88
+
89
+ /**
90
+ * Get a field argument
91
+ * @since 1.1.0
92
+ * @param string $key Argument to check
93
+ * @param string $key Sub argument to check
94
+ * @return mixed Argument value or false if non-existent
95
+ */
96
+ public function args( $key = '', $_key = '' ) {
97
+ $vars = $this->_data( 'args', $key );
98
+ if ( $_key ) {
99
+ return isset( $vars[ $_key ] ) ? $vars[ $_key ] : false;
100
+ }
101
+ return $vars;
102
+ }
103
+
104
+ /**
105
+ * Get Field's value
106
+ * @since 1.1.0
107
+ * @param string $key If value is an array, is used to get array key->value
108
+ * @return mixed Field value or false if non-existent
109
+ */
110
+ public function value( $key = '' ) {
111
+ return $this->_data( 'value', $key );
112
+ }
113
+
114
+ /**
115
+ * Retrieve a portion of a field property
116
+ * @since 1.1.0
117
+ * @param string $var Field property to check
118
+ * @param string $key Field property array key to check
119
+ * @return mixed Queried property value or false
120
+ */
121
+ public function _data( $var, $key = '' ) {
122
+ $vars = $this->$var;
123
+ if ( $key ) {
124
+ return isset( $vars[ $key ] ) ? $vars[ $key ] : false;
125
+ }
126
+ return $vars;
127
+ }
128
+
129
+ /**
130
+ * Retrieves metadata/option data
131
+ * @since 1.0.1
132
+ * @param string $field_id Meta key/Option array key
133
+ * @return mixed Meta/Option value
134
+ */
135
+ public function get_data( $field_id = '', $args = array() ) {
136
+ if ( $field_id ) {
137
+ $args['field_id'] = $field_id;
138
+ } else if ( $this->group ) {
139
+ $args['field_id'] = $this->group->id();
140
+ }
141
+ extract( $this->data_args( $args ) );
142
+
143
+ $data = 'options-page' === $type
144
+ ? cmb_Meta_Box::get_option( $id, $field_id )
145
+ : get_metadata( $type, $id, $field_id, ( $single || $repeat ) /* If multicheck this can be multiple values */ );
146
+
147
+ if ( $this->group && $data ) {
148
+ $data = isset( $data[ $this->group->args( 'count' ) ][ $this->args( '_id' ) ] )
149
+ ? $data[ $this->group->args( 'count' ) ][ $this->args( '_id' ) ]
150
+ : false;
151
+ }
152
+ return $data;
153
+ }
154
+
155
+ /**
156
+ * Updates metadata/option data
157
+ * @since 1.0.1
158
+ * @param mixed $value Value to update data with
159
+ * @param bool $single Whether data is an array (add_metadata)
160
+ */
161
+ public function update_data( $new_value, $single = true ) {
162
+ extract( $this->data_args( array( 'new_value' => $new_value, 'single' => $single ) ) );
163
+
164
+ $new_value = $repeat ? array_values( $new_value ) : $new_value;
165
+
166
+ if ( 'options-page' === $type )
167
+ return cmb_Meta_Box::update_option( $id, $field_id, $new_value, $single );
168
+
169
+ if ( ! $single )
170
+ return add_metadata( $type, $id, $field_id, $new_value, false );
171
+
172
+ return update_metadata( $type, $id, $field_id, $new_value );
173
+ }
174
+
175
+ /**
176
+ * Removes/updates metadata/option data
177
+ * @since 1.0.1
178
+ * @param string $old Old value
179
+ */
180
+ public function remove_data( $old = '' ) {
181
+ extract( $this->data_args() );
182
+
183
+ return 'options-page' === $type
184
+ ? cmb_Meta_Box::remove_option( $id, $field_id )
185
+ : delete_metadata( $type, $id, $field_id, $old );
186
+ }
187
+
188
+ /**
189
+ * data variables for get/set data methods
190
+ * @since 1.1.0
191
+ * @param array $args Override arguments
192
+ * @return array Updated arguments
193
+ */
194
+ public function data_args( $args = array() ) {
195
+ $args = wp_parse_args( $args, array(
196
+ 'type' => $this->object_type,
197
+ 'id' => $this->object_id,
198
+ 'field_id' => $this->id( true ),
199
+ 'repeat' => $this->args( 'repeatable' ),
200
+ 'single' => ! $this->args( 'multiple' ),
201
+ ) );
202
+ return $args;
203
+ }
204
+
205
+ /**
206
+ * Checks if field has a registered validation callback
207
+ * @since 1.0.1
208
+ * @param mixed $meta_value Meta value
209
+ * @return mixed Possibly validated meta value
210
+ */
211
+ public function sanitization_cb( $meta_value ) {
212
+ if ( empty( $meta_value ) )
213
+ return $meta_value;
214
+
215
+ // Check if the field has a registered validation callback
216
+ $cb = $this->maybe_callback( 'sanitization_cb' );
217
+ if ( false === $cb ) {
218
+ // If requestion NO validation, return meta value
219
+ return $meta_value;
220
+ } elseif ( $cb ) {
221
+ // Ok, callback is good, let's run it.
222
+ return call_user_func( $cb, $meta_value, $this->args(), $this );
223
+ }
224
+
225
+ $clean = new cmb_Meta_Box_Sanitize( $this, $meta_value );
226
+ // Validation via 'cmb_Meta_Box_Sanitize' (with fallback filter)
227
+ return $clean->{$this->type()}( $meta_value );
228
+ }
229
+
230
+ /**
231
+ * Checks if field has a callback value
232
+ * @since 1.0.1
233
+ * @param string $cb Callback string
234
+ * @return mixed NULL, false for NO validation, or $cb string if it exists.
235
+ */
236
+ public function maybe_callback( $cb ) {
237
+ $field_args = $this->args();
238
+ if ( ! isset( $field_args[ $cb ] ) )
239
+ return;
240
+
241
+ // Check if metabox is requesting NO validation
242
+ $cb = false !== $field_args[ $cb ] && 'false' !== $field_args[ $cb ] ? $field_args[ $cb ] : false;
243
+
244
+ // If requestion NO validation, return false
245
+ if ( ! $cb )
246
+ return false;
247
+
248
+ if ( is_callable( $cb ) )
249
+ return $cb;
250
+ }
251
+
252
+ /**
253
+ * Determine if current type is excempt from escaping
254
+ * @since 1.1.0
255
+ * @return bool True if exempt
256
+ */
257
+ public function escaping_exception() {
258
+ // These types cannot be escaped
259
+ return in_array( $this->type(), array(
260
+ 'file_list',
261
+ 'multicheck',
262
+ 'text_datetime_timestamp_timezone',
263
+ ) );
264
+ }
265
+
266
+ /**
267
+ * Determine if current type cannot be repeatable
268
+ * @since 1.1.0
269
+ * @param string $type Field type to check
270
+ * @return bool True if type cannot be repeatable
271
+ */
272
+ public function repeatable_exception( $type ) {
273
+ // These types cannot be escaped
274
+ return in_array( $type, array(
275
+ 'file', // Use file_list
276
+ 'radio',
277
+ 'title',
278
+ 'group',
279
+ // @todo Ajax load wp_editor: http://wordpress.stackexchange.com/questions/51776/how-to-load-wp-editor-through-ajax-jquery
280
+ 'wysiwyg',
281
+ 'checkbox',
282
+ 'radio_inline',
283
+ 'taxonomy_radio',
284
+ 'taxonomy_select',
285
+ 'taxonomy_multicheck',
286
+ ) );
287
+ }
288
+
289
+ /**
290
+ * Escape the value before output. Defaults to 'esc_attr()'
291
+ * @since 1.0.1
292
+ * @param mixed $meta_value Meta value
293
+ * @param mixed $func Escaping function (if not esc_attr())
294
+ * @return mixed Final value
295
+ */
296
+ public function escaped_value( $func = 'esc_attr', $meta_value = '' ) {
297
+
298
+ if ( isset( $this->escaped_value ) )
299
+ return $this->escaped_value;
300
+
301
+ $meta_value = $meta_value ? $meta_value : $this->value();
302
+ // Check if the field has a registered escaping callback
303
+ $cb = $this->maybe_callback( 'escape_cb' );
304
+ if ( false === $cb || $this->escaping_exception() ) {
305
+ // If requesting NO escaping, return meta value
306
+ return ! empty( $meta_value ) ? $meta_value : $this->args( 'default' );
307
+ } elseif ( $cb ) {
308
+ // Ok, callback is good, let's run it.
309
+ return call_user_func( $cb, $meta_value, $this->args(), $this );
310
+ }
311
+
312
+ // Or custom escaping filter can be used
313
+ $esc = apply_filters( 'cmb_types_esc_'. $this->type(), null, $meta_value, $this->args(), $this );
314
+ if ( null !== $esc ) {
315
+ return $esc;
316
+ }
317
+
318
+ // escaping function passed in?
319
+ $func = $func ? $func : 'esc_attr';
320
+ $meta_value = ! empty( $meta_value ) ? $meta_value : $this->args( 'default' );
321
+
322
+ if ( is_array( $meta_value ) ) {
323
+ foreach ( $meta_value as $key => $value ) {
324
+ $meta_value[ $key ] = call_user_func( $func, $value );
325
+ }
326
+ } else {
327
+ $meta_value = call_user_func( $func, $meta_value );
328
+ }
329
+
330
+ $this->escaped_value = $meta_value;
331
+ return $this->escaped_value;
332
+ }
333
+
334
+ /**
335
+ * Offset a time value based on timezone
336
+ * @since 1.0.0
337
+ * @return string Offset time string
338
+ */
339
+ public function field_timezone_offset() {
340
+ return cmb_Meta_Box::timezone_offset( $this->field_timezone() );
341
+ }
342
+
343
+ /**
344
+ * Return timezone string
345
+ * @since 1.0.0
346
+ * @return string Timezone string
347
+ */
348
+ public function field_timezone() {
349
+
350
+ // Is timezone arg set?
351
+ if ( $this->args( 'timezone' ) ) {
352
+ return $this->args( 'timezone' ) ;
353
+ }
354
+ // Is there another meta key with a timezone stored as its value we should use?
355
+ else if ( $this->args( 'timezone_meta_key' ) ) {
356
+ return $this->get_data( $this->args( 'timezone_meta_key' ) );
357
+ }
358
+
359
+ return false;
360
+ }
361
+
362
+ /**
363
+ * Render a field row
364
+ * @since 1.0.0
365
+ */
366
+ public function render_field() {
367
+
368
+ // If field is requesting to not be shown on the front-end
369
+ if ( ! is_admin() && ! $this->args( 'on_front' ) )
370
+ return;
371
+
372
+ // If field is requesting to be conditionally shown
373
+ if ( is_callable( $this->args( 'show_on_cb' ) ) && ! call_user_func( $this->args( 'show_on_cb' ), $this ) )
374
+ return;
375
+
376
+ $classes = 'cmb-type-'. sanitize_html_class( $this->type() );
377
+ $classes .= ' cmb_id_'. sanitize_html_class( $this->id() );
378
+ $classes .= $this->args( 'repeatable' ) ? ' cmb-repeat' : '';
379
+ // 'inline' flag, or _inline in the field type, set to true
380
+ $classes .= $this->args( 'inline' ) ? ' cmb-inline' : '';
381
+ $is_side = 'side' === $this->args( 'context' );
382
+
383
+ printf( "<tr class=\"%s\">\n", $classes );
384
+
385
+ if ( 'title' == $this->type() || ! $this->args( 'show_names' ) || $is_side ) {
386
+ echo "\t<td colspan=\"2\">\n";
387
+
388
+ if ( ! $this->args( 'show_names' ) || $is_side ) {
389
+ $style = ! $is_side || 'title' == $this->type() ? ' style="display:none;"' : '';
390
+ printf( "\n<label%s for=\"%s\">%s</label>\n", $style, $this->id(), $this->args( 'name' ) );
391
+ }
392
+ } else {
393
+
394
+ $style = 'post' == $this->object_type ? ' style="width:18%"' : '';
395
+ // $tag = 'side' !== $this->args( 'context' ) ? 'th' : 'p';
396
+ $tag = 'th';
397
+ printf( '<%1$s%2$s><label for="%3$s">%4$s</label></%1$s>', $tag, $style, $this->id(), $this->args( 'name' ) );
398
+
399
+ echo "\n\t<td>\n";
400
+ }
401
+
402
+ echo $this->args( 'before' );
403
+
404
+ $this_type = new cmb_Meta_Box_types( $this );
405
+ $this_type->render();
406
+
407
+ echo $this->args( 'after' );
408
+
409
+ echo "\n\t</td>\n</tr>";
410
+ }
411
+
412
+ /**
413
+ * Replaces a hash key - {#} - with the repeatable count
414
+ * @since 1.2.0
415
+ * @param string $value Value to update
416
+ * @return string Updated value
417
+ */
418
+ public function replace_hash( $value ) {
419
+ // Replace hash with 1 based count
420
+ return str_ireplace( '{#}', ( $this->count() + 1 ), $value );
421
+ }
422
+
423
+ /**
424
+ * Fills in empty field parameters with defaults
425
+ * @since 1.1.0
426
+ * @param array $args Metabox field config array
427
+ */
428
+ public function _set_field_defaults( $args ) {
429
+
430
+ // Set up blank or default values for empty ones
431
+ if ( ! isset( $args['name'] ) ) $args['name'] = '';
432
+ if ( ! isset( $args['desc'] ) ) $args['desc'] = '';
433
+ if ( ! isset( $args['before'] ) ) $args['before'] = '';
434
+ if ( ! isset( $args['after'] ) ) $args['after'] = '';
435
+ if ( ! isset( $args['protocols'] ) ) $args['protocols'] = null;
436
+ if ( ! isset( $args['description'] ) ) {
437
+ $args['description'] = isset( $args['desc'] ) ? $args['desc'] : '';
438
+ }
439
+ if ( ! isset( $args['default'] ) ) {
440
+ // Phase out 'std', and use 'default' instead
441
+ $args['default'] = isset( $args['std'] ) ? $args['std'] : '';
442
+ }
443
+ if ( ! isset( $args['preview_size'] ) ) $args['preview_size'] = array( 50, 50 );
444
+ if ( ! isset( $args['date_format'] ) ) $args['date_format'] = 'm\/d\/Y';
445
+ if ( ! isset( $args['time_format'] ) ) $args['time_format'] = 'h:i A';
446
+ // Allow a filter override of the default value
447
+ $args['default'] = apply_filters( 'cmb_default_filter', $args['default'], $args, $this->object_type, $this->object_type );
448
+ $args['allow'] = 'file' == $args['type'] && ! isset( $args['allow'] ) ? array( 'url', 'attachment' ) : array();
449
+ $args['save_id'] = 'file' == $args['type'] && ! ( isset( $args['save_id'] ) && ! $args['save_id'] );
450
+ // $args['multiple'] = isset( $args['multiple'] ) ? $args['multiple'] : ( 'multicheck' == $args['type'] ? true : false );
451
+ $args['multiple'] = isset( $args['multiple'] ) ? $args['multiple'] : false;
452
+ $args['repeatable'] = isset( $args['repeatable'] ) && $args['repeatable'] && ! $this->repeatable_exception( $args['type'] );
453
+ $args['inline'] = isset( $args['inline'] ) && $args['inline'] || false !== stripos( $args['type'], '_inline' );
454
+ $args['on_front'] = ! ( isset( $args['on_front'] ) && ! $args['on_front'] );
455
+ $args['attributes'] = isset( $args['attributes'] ) && is_array( $args['attributes'] ) ? $args['attributes'] : array();
456
+ $args['options'] = isset( $args['options'] ) && is_array( $args['options'] ) ? $args['options'] : array();
457
+
458
+ $args['options'] = 'group' == $args['type'] ? wp_parse_args( $args['options'], array(
459
+ 'add_button' => __( 'Add Group', 'cmb' ),
460
+ 'remove_button' => __( 'Remove Group', 'cmb' ),
461
+ ) ) : $args['options'];
462
+
463
+ $args['_id'] = $args['id'];
464
+ $args['_name'] = $args['id'];
465
+
466
+ if ( $this->group ) {
467
+ $args['id'] = $this->group->args( 'id' ) .'_'. $this->group->args( 'count' ) .'_'. $args['id'];
468
+ $args['_name'] = $this->group->args( 'id' ) .'['. $this->group->args( 'count' ) .']['. $args['_name'] .']';
469
+ }
470
+
471
+ if ( 'wysiwyg' == $args['type'] ) {
472
+ $args['id'] = strtolower( str_ireplace( '-', '_', $args['id'] ) );
473
+ $args['options']['textarea_name'] = $args['_name'];
474
+ }
475
+
476
+ $option_types = array( 'taxonomy_select', 'taxonomy_radio', 'taxonomy_radio_inline' );
477
+ if ( in_array( $args['type'], $option_types, true ) ) {
478
+
479
+ // @todo implemention
480
+ $args['show_option_all'] = isset( $args['show_option_all'] ) && ! $args['show_option_all'] ? false : true;
481
+ $args['show_option_none'] = isset( $args['show_option_none'] ) && ! $args['show_option_none'] ? false : true;
482
+
483
+ }
484
+
485
+ return $args;
486
+ }
487
+
488
+ /**
489
+ * Updates attributes array values unless they exist from the field config array
490
+ * @since 1.1.0
491
+ * @param array $attrs Array of attributes to update
492
+ */
493
+ public function maybe_set_attributes( $attrs = array() ) {
494
+ return wp_parse_args( $this->args['attributes'], $attrs );
495
+ }
496
+
497
+ }
lib/cmb_metaboxes/helpers/cmb_Meta_Box_types.php ADDED
@@ -0,0 +1,794 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * CMB field types
5
+ *
6
+ * @todo test taxonomy methods with non-post objects
7
+ * @todo test all methods with non-post objects
8
+ * @todo Date/Time fields should store date format as data attribute for JS
9
+ *
10
+ * @since 1.0.0
11
+ */
12
+ class cmb_Meta_Box_types {
13
+
14
+ /**
15
+ * An iterator value for repeatable fields
16
+ * @var integer
17
+ * @since 1.0.0
18
+ */
19
+ public $iterator = 0;
20
+
21
+ /**
22
+ * Current field
23
+ * @var array
24
+ * @since 1.0.0
25
+ */
26
+ public $field;
27
+
28
+ public function __construct( $field ) {
29
+ $this->field = $field;
30
+ }
31
+
32
+ /**
33
+ * Default fallback. Allows rendering fields via "cmb_render_$name" hook
34
+ * @since 1.0.0
35
+ * @param string $name Non-existent method name
36
+ * @param array $arguments All arguments passed to the method
37
+ */
38
+ public function __call( $name, $arguments ) {
39
+ // When a non-registered field is called, send it through an action.
40
+ do_action( "cmb_render_$name", $this->field->args(), $this->field->escaped_value(), $this->field->object_id, $this->field->object_type, $this );
41
+ }
42
+
43
+ /**
44
+ * Render a field (and handle repeatable)
45
+ * @since 1.1.0
46
+ */
47
+ public function render() {
48
+ if ( $this->field->args( 'repeatable' ) ) {
49
+ $this->render_repeatable_field();
50
+ } else {
51
+ $this->_render();
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Render a field type
57
+ * @since 1.1.0
58
+ */
59
+ protected function _render() {
60
+ echo $this->{$this->field->type()}();
61
+ }
62
+
63
+ /**
64
+ * Checks if we can get a post object, and if so, uses `get_the_terms` which utilizes caching
65
+ * @since 1.0.2
66
+ * @return mixed Array of terms on success
67
+ */
68
+ public function get_object_terms() {
69
+ $object_id = $this->field->object_id;
70
+ $taxonomy = $this->field->args( 'taxonomy' );
71
+
72
+ if ( ! $post = get_post( $object_id ) ) {
73
+
74
+ $cache_key = 'cmb-cache-'. $taxonomy .'-'. $object_id;
75
+
76
+ // Check cache
77
+ $cached = $test = get_transient( $cache_key );
78
+ if ( $cached )
79
+ return $cached;
80
+
81
+ $cached = wp_get_object_terms( $object_id, $taxonomy );
82
+ // Do our own (minimal) caching. Long enough for a page-load.
83
+ $set = set_transient( $cache_key, $cached, 60 );
84
+ return $cached;
85
+ }
86
+
87
+ // WP caches internally so it's better to use
88
+ return get_the_terms( $post, $taxonomy );
89
+
90
+ }
91
+
92
+ /**
93
+ * Determine a file's extension
94
+ * @since 1.0.0
95
+ * @param string $file File url
96
+ * @return string|false File extension or false
97
+ */
98
+ public function get_file_ext( $file ) {
99
+ $parsed = @parse_url( $file, PHP_URL_PATH );
100
+ return $parsed ? strtolower( pathinfo( $parsed, PATHINFO_EXTENSION ) ) : false;
101
+ }
102
+
103
+ /**
104
+ * Determines if a file has a valid image extension
105
+ * @since 1.0.0
106
+ * @param string $file File url
107
+ * @return bool Whether file has a valid image extension
108
+ */
109
+ public function is_valid_img_ext( $file ) {
110
+ $file_ext = $this->get_file_ext( $file );
111
+
112
+ $this->valid = empty( $this->valid )
113
+ ? (array) apply_filters( 'cmb_valid_img_types', array( 'jpg', 'jpeg', 'png', 'gif', 'ico', 'icon' ) )
114
+ : $this->valid;
115
+
116
+ return ( $file_ext && in_array( $file_ext, $this->valid ) );
117
+ }
118
+
119
+ /**
120
+ * Handles parsing and filtering attributes while preserving any passed in via field config.
121
+ * @since 1.1.0
122
+ * @param array $args Override arguments
123
+ * @param string $element Element for filter
124
+ * @param array $defaults Default arguments
125
+ * @return array Parsed and filtered arguments
126
+ */
127
+ public function parse_args( $args, $element, $defaults ) {
128
+ return wp_parse_args( apply_filters( "cmb_{$element}_attributes", $this->field->maybe_set_attributes( $args ), $this->field, $this ), $defaults );
129
+ }
130
+
131
+ /**
132
+ * Combines attributes into a string for a form element
133
+ * @since 1.1.0
134
+ * @param array $attrs Attributes to concatenate
135
+ * @param array $attr_exclude Attributes that should NOT be concatenated
136
+ * @return string String of attributes for form element
137
+ */
138
+ public function concat_attrs( $attrs, $attr_exclude = array() ) {
139
+ $attributes = '';
140
+ foreach ( $attrs as $attr => $val ) {
141
+ if ( ! in_array( $attr, (array) $attr_exclude, true ) )
142
+ $attributes .= sprintf( ' %s="%s"', $attr, $val );
143
+ }
144
+ return $attributes;
145
+ }
146
+
147
+ /**
148
+ * Generates html for an option element
149
+ * @since 1.1.0
150
+ * @param string $opt_label Option label
151
+ * @param string $opt_value Option value
152
+ * @param mixed $selected Selected attribute if option is selected
153
+ * @return string Generated option element html
154
+ */
155
+ public function option( $opt_label, $opt_value, $selected ) {
156
+ return sprintf( "\t".'<option value="%s" %s>%s</option>', $opt_value, selected( $selected, true, false ), $opt_label )."\n";
157
+ }
158
+
159
+ /**
160
+ * Generates options html
161
+ * @since 1.1.0
162
+ * @param array $args Optional arguments
163
+ * @param string $method Method to generate individual option item
164
+ * @return string Concatenated html options
165
+ */
166
+ public function concat_options( $args = array(), $method = 'list_input' ) {
167
+
168
+ $options = (array) $this->field->args( 'options' );
169
+ $saved_value = $this->field->escaped_value();
170
+ $value = $saved_value ? $saved_value : $this->field->args( 'default' );
171
+
172
+ $_options = ''; $i = 1;
173
+ foreach ( $options as $option_key => $option ) {
174
+
175
+ // Check for the "old" way
176
+ $opt_label = is_array( $option ) && array_key_exists( 'name', $option ) ? $option['name'] : $option;
177
+ $opt_value = is_array( $option ) && array_key_exists( 'value', $option ) ? $option['value'] : $option_key;
178
+ // Check if this option is the value of the input
179
+ $is_current = $value == $opt_value;
180
+
181
+ if ( ! empty( $args ) ) {
182
+ // Clone args & modify for just this item
183
+ $this_args = $args;
184
+ $this_args['value'] = $opt_value;
185
+ $this_args['label'] = $opt_label;
186
+ if ( $is_current )
187
+ $this_args['checked'] = 'checked';
188
+
189
+ $_options .= $this->$method( $this_args, $i );
190
+ } else {
191
+ $_options .= $this->option( $opt_label, $opt_value, $is_current );
192
+ }
193
+ $i++;
194
+ }
195
+ return $_options;
196
+ }
197
+
198
+ /**
199
+ * Generates html for list item with input
200
+ * @since 1.1.0
201
+ * @param array $args Override arguments
202
+ * @param int $i Iterator value
203
+ * @return string Gnerated list item html
204
+ */
205
+ public function list_input( $args = array(), $i ) {
206
+ $args = $this->parse_args( $args, 'list_input', array(
207
+ 'type' => 'radio',
208
+ 'class' => 'cmb_option',
209
+ 'name' => $this->_name(),
210
+ 'id' => $this->_id( $i ),
211
+ 'value' => $this->field->escaped_value(),
212
+ 'label' => '',
213
+ ) );
214
+
215
+ return sprintf( "\t".'<li><input%s/> <label for="%s">%s</label></li>'."\n", $this->concat_attrs( $args, 'label' ), $args['id'], $args['label'] );
216
+ }
217
+
218
+ /**
219
+ * Generates html for list item with checkbox input
220
+ * @since 1.1.0
221
+ * @param array $args Override arguments
222
+ * @param int $i Iterator value
223
+ * @return string Gnerated list item html
224
+ */
225
+ public function list_input_checkbox( $args, $i ) {
226
+ unset( $args['selected'] );
227
+ $saved_value = $this->field->escaped_value();
228
+ if ( is_array( $saved_value ) && in_array( $args['value'], $saved_value ) ) {
229
+ $args['checked'] = 'checked';
230
+ }
231
+ return $this->list_input( $args, $i );
232
+ }
233
+
234
+ /**
235
+ * Generates repeatable field table markup
236
+ * @since 1.0.0
237
+ */
238
+ public function render_repeatable_field() {
239
+ $table_id = $this->field->id() .'_repeat';
240
+
241
+ $this->_desc( true, true );
242
+ ?>
243
+
244
+ <table id="<?php echo $table_id; ?>" class="cmb-repeat-table">
245
+ <tbody>
246
+ <?php $this->repeatable_rows(); ?>
247
+ </tbody>
248
+ </table>
249
+ <p class="add-row">
250
+ <a data-selector="<?php echo $table_id; ?>" class="add-row-button button" href="#"><?php _e( 'Add Row', 'cmb' ); ?></a>
251
+ </p>
252
+
253
+ <?php
254
+ // reset iterator
255
+ $this->iterator = 0;
256
+ }
257
+
258
+ /**
259
+ * Generates repeatable field rows
260
+ * @since 1.1.0
261
+ */
262
+ public function repeatable_rows() {
263
+ $meta_value = $this->field->escaped_value();
264
+ // check for default content
265
+ $default = $this->field->args( 'default' );
266
+
267
+ // check for saved data
268
+ if ( ! empty( $meta_value ) ) {
269
+ $meta_value = is_array( $meta_value ) ? array_filter( $meta_value ) : $meta_value;
270
+ $meta_value = ! empty( $meta_value ) ? $meta_value : $default;
271
+ } else {
272
+ $meta_value = $default;
273
+ }
274
+
275
+ // Loop value array and add a row
276
+ if ( ! empty( $meta_value ) ) {
277
+ foreach ( (array) $meta_value as $val ) {
278
+ $this->field->escaped_value = $val;
279
+ $this->repeat_row();
280
+ $this->iterator++;
281
+ }
282
+ } else {
283
+ // Otherwise add one row
284
+ $this->repeat_row();
285
+ }
286
+
287
+ // Then add an empty row
288
+ $this->field->escaped_value = '';
289
+ $this->iterator = $this->iterator ? $this->iterator : 1;
290
+ $this->repeat_row( 'empty-row' );
291
+ }
292
+
293
+ /**
294
+ * Generates a repeatable row's markup
295
+ * @since 1.1.0
296
+ * @param string $class Repeatable table row's class
297
+ */
298
+ protected function repeat_row( $class = 'repeat-row' ) {
299
+ ?>
300
+
301
+ <tr class="<?php echo $class; ?>">
302
+ <td>
303
+ <?php $this->_render(); ?>
304
+ </td>
305
+ <td class="remove-row">
306
+ <a class="button remove-row-button" href="#"><?php _e( 'Remove', 'cmb' ); ?></a>
307
+ </td>
308
+ </tr>
309
+
310
+ <?php
311
+ }
312
+
313
+ /**
314
+ * Generates description markup
315
+ * @since 1.0.0
316
+ * @param boolean $paragraph Paragraph tag or span
317
+ * @param boolean $echo Whether to echo description or only return it
318
+ * @return string Field's description markup
319
+ */
320
+ public function _desc( $paragraph = false, $echo = false ) {
321
+ // Prevent description from printing multiple times for repeatable fields
322
+ if ( $this->field->args( 'repeatable' ) || $this->iterator > 0 ) {
323
+ return '';
324
+ }
325
+ $tag = $paragraph ? 'p' : 'span';
326
+ $desc = "\n<$tag class=\"cmb_metabox_description\">{$this->field->args( 'description' )}</$tag>\n";
327
+ if ( $echo )
328
+ echo $desc;
329
+ return $desc;
330
+ }
331
+
332
+ /**
333
+ * Generate field name attribute
334
+ * @since 1.1.0
335
+ * @param string $suffix For multi-part fields
336
+ * @return string Name attribute
337
+ */
338
+ public function _name( $suffix = '' ) {
339
+ return $this->field->args( '_name' ) . ( $this->field->args( 'repeatable' ) ? '['. $this->iterator .']' : '' ) . $suffix;
340
+ }
341
+
342
+ /**
343
+ * Generate field id attribute
344
+ * @since 1.1.0
345
+ * @param string $suffix For multi-part fields
346
+ * @return string Id attribute
347
+ */
348
+ public function _id( $suffix = '' ) {
349
+ return $this->field->id() . $suffix . ( $this->field->args( 'repeatable' ) ? '_'. $this->iterator .'" data-iterator="'. $this->iterator : '' );
350
+ }
351
+
352
+ /**
353
+ * Handles outputting an 'input' element
354
+ * @since 1.1.0
355
+ * @param array $args Override arguments
356
+ * @return string Form input element
357
+ */
358
+ public function input( $args = array() ) {
359
+ $args = $this->parse_args( $args, 'input', array(
360
+ 'type' => 'text',
361
+ 'class' => 'regular-text',
362
+ 'name' => $this->_name(),
363
+ 'id' => $this->_id(),
364
+ 'value' => $this->field->escaped_value(),
365
+ 'desc' => $this->_desc( true ),
366
+ ) );
367
+
368
+ return sprintf( '<input%s/>%s', $this->concat_attrs( $args, 'desc' ), $args['desc'] );
369
+ }
370
+
371
+ /**
372
+ * Handles outputting an 'textarea' element
373
+ * @since 1.1.0
374
+ * @param array $args Override arguments
375
+ * @return string Form textarea element
376
+ */
377
+ public function textarea( $args = array() ) {
378
+ $args = $this->parse_args( $args, 'textarea', array(
379
+ 'class' => 'cmb_textarea',
380
+ 'name' => $this->_name(),
381
+ 'id' => $this->_id(),
382
+ 'cols' => 60,
383
+ 'rows' => 10,
384
+ 'value' => $this->field->escaped_value( 'esc_textarea' ),
385
+ 'desc' => $this->_desc( true ),
386
+ ) );
387
+ return sprintf( '<textarea%s>%s</textarea>%s', $this->concat_attrs( $args, array( 'desc', 'value' ) ), $args['value'], $args['desc'] );
388
+ }
389
+
390
+ /**
391
+ * Begin Field Types
392
+ */
393
+
394
+ public function text() {
395
+ return $this->input();
396
+ }
397
+
398
+ public function text_small() {
399
+ return $this->input( array( 'class' => 'cmb_text_small', 'desc' => $this->_desc() ) );
400
+ }
401
+
402
+ public function text_medium() {
403
+ return $this->input( array( 'class' => 'cmb_text_medium', 'desc' => $this->_desc() ) );
404
+ }
405
+
406
+ public function text_email() {
407
+ return $this->input( array( 'class' => 'cmb_text_email cmb_text_medium', 'type' => 'email' ) );
408
+ }
409
+
410
+ public function text_url() {
411
+ return $this->input( array( 'class' => 'cmb_text_url cmb_text_medium regular-text', 'value' => $this->field->escaped_value( 'esc_url' ) ) );
412
+ }
413
+
414
+ public function text_date() {
415
+ return $this->input( array( 'class' => 'cmb_text_small cmb_datepicker', 'desc' => $this->_desc() ) );
416
+ }
417
+
418
+ public function text_time() {
419
+ return $this->input( array( 'class' => 'cmb_timepicker text_time', 'desc' => $this->_desc() ) );
420
+ }
421
+
422
+ public function text_money() {
423
+ return ( ! $this->field->args( 'before' ) ? '$ ' : ' ' ) . $this->input( array( 'class' => 'cmb_text_money', 'desc' => $this->_desc() ) );
424
+ }
425
+
426
+ public function textarea_small() {
427
+ return $this->textarea( array( 'class' => 'cmb_textarea_small', 'rows' => 4 ) );
428
+ }
429
+
430
+ public function textarea_code() {
431
+ return sprintf( '<pre>%s</pre>', $this->textarea( array( 'class' => 'cmb_textarea_code' ) ) );
432
+ }
433
+
434
+ public function wysiwyg( $args = array() ) {
435
+ extract( $this->parse_args( $args, 'input', array(
436
+ 'id' => $this->_id(),
437
+ 'value' => $this->field->escaped_value( 'stripslashes' ),
438
+ 'desc' => $this->_desc( true ),
439
+ 'options' => $this->field->args( 'options' ),
440
+ ) ) );
441
+
442
+ wp_editor( $value, $id, $options );
443
+ echo $desc;
444
+ }
445
+
446
+ public function text_date_timestamp() {
447
+ $meta_value = $this->field->escaped_value();
448
+ $value = ! empty( $meta_value ) ? date( $this->field->args( 'date_format' ), $meta_value ) : '';
449
+ return $this->input( array( 'class' => 'cmb_text_small cmb_datepicker', 'value' => $value ) );
450
+ }
451
+
452
+ public function text_datetime_timestamp( $meta_value = '' ) {
453
+ $desc = '';
454
+ if ( ! $meta_value ) {
455
+ $meta_value = $this->field->escaped_value();
456
+ // This will be used if there is a select_timezone set for this field
457
+ $tz_offset = $this->field->field_timezone_offset();
458
+ if ( ! empty( $tz_offset ) ) {
459
+ $meta_value -= $tz_offset;
460
+ }
461
+ $desc = $this->_desc();
462
+ }
463
+
464
+ $inputs = array(
465
+ $this->input( array(
466
+ 'class' => 'cmb_text_small cmb_datepicker',
467
+ 'name' => $this->_name( '[date]' ),
468
+ 'id' => $this->_id( '_date' ),
469
+ 'value' => ! empty( $meta_value ) ? date( $this->field->args( 'date_format' ), $meta_value ) : '',
470
+ 'desc' => '',
471
+ ) ),
472
+ $this->input( array(
473
+ 'class' => 'cmb_timepicker text_time',
474
+ 'name' => $this->_name( '[time]' ),
475
+ 'id' => $this->_id( '_time' ),
476
+ 'value' => ! empty( $meta_value ) ? date( $this->field->args( 'time_format' ), $meta_value ) : '',
477
+ 'desc' => $desc,
478
+ ) )
479
+ );
480
+
481
+ return implode( "\n", $inputs );
482
+ }
483
+
484
+ public function text_datetime_timestamp_timezone() {
485
+ $meta_value = $this->field->escaped_value();
486
+ $datetime = unserialize( $meta_value );
487
+ $meta_value = $tzstring = false;
488
+
489
+ if ( $datetime && $datetime instanceof DateTime ) {
490
+ $tz = $datetime->getTimezone();
491
+ $tzstring = $tz->getName();
492
+ $meta_value = $datetime->getTimestamp() + $tz->getOffset( new DateTime( 'NOW' ) );
493
+ }
494
+
495
+ $inputs = $this->text_datetime_timestamp( $meta_value );
496
+ $inputs .= '<select name="'. $this->_name( '[timezone]' ) .'" id="'. $this->_id( '_timezone' ) .'">';
497
+ $inputs .= wp_timezone_choice( $tzstring );
498
+ $inputs .= '</select>'. $this->_desc();
499
+
500
+ return $inputs;
501
+ }
502
+
503
+ public function select_timezone() {
504
+ $this->field->args['default'] = $this->field->args( 'default' )
505
+ ? $this->field->args( 'default' )
506
+ : cmb_Meta_Box::timezone_string();
507
+
508
+ $meta_value = $this->field->escaped_value();
509
+
510
+ return '<select name="'. $this->_name() .'" id="'. $this->_id() .'">'. wp_timezone_choice( $meta_value ) .'</select>';
511
+ }
512
+
513
+ public function colorpicker() {
514
+ $meta_value = $this->field->escaped_value();
515
+ $hex_color = '(([a-fA-F0-9]){3}){1,2}$';
516
+ if ( preg_match( '/^' . $hex_color . '/i', $meta_value ) ) // Value is just 123abc, so prepend #.
517
+ $meta_value = '#' . $meta_value;
518
+ elseif ( ! preg_match( '/^#' . $hex_color . '/i', $meta_value ) ) // Value doesn't match #123abc, so sanitize to just #.
519
+ $meta_value = "#";
520
+
521
+ return $this->input( array( 'class' => 'cmb_colorpicker cmb_text_small', 'value' => $meta_value ) );
522
+ }
523
+
524
+ public function title() {
525
+ extract( $this->parse_args( array(), 'title', array(
526
+ 'tag' => $this->field->object_type == 'post' ? 'h5' : 'h3',
527
+ 'class' => 'cmb_metabox_title',
528
+ 'name' => $this->field->args( 'name' ),
529
+ 'desc' => $this->_desc( true ),
530
+ ) ) );
531
+
532
+ return sprintf( '<%1$s class="%2$s">%3$s</%1$s>%4$s', $tag, $class, $name, $desc );
533
+ }
534
+
535
+ public function select( $args = array() ) {
536
+ $args = $this->parse_args( $args, 'select', array(
537
+ 'class' => 'cmb_select',
538
+ 'name' => $this->_name(),
539
+ 'id' => $this->_id(),
540
+ 'desc' => $this->_desc( true ),
541
+ 'options' => $this->concat_options(),
542
+ ) );
543
+
544
+ $attrs = $this->concat_attrs( $args, array( 'desc', 'options' ) );
545
+ return sprintf( '<select%s>%s</select>%s', $attrs, $args['options'], $args['desc'] );
546
+ }
547
+
548
+ public function taxonomy_select() {
549
+
550
+ $names = $this->get_object_terms();
551
+ $saved_term = is_wp_error( $names ) || empty( $names ) ? $this->field->args( 'default' ) : $names[0]->slug;
552
+ $terms = get_terms( $this->field->args( 'taxonomy' ), 'hide_empty=0' );
553
+ $options = '';
554
+
555
+ foreach ( $terms as $term ) {
556
+ $selected = $saved_term == $term->slug;
557
+ $options .= $this->option( $term->name, $term->slug, $selected );
558
+ }
559
+
560
+ return $this->select( array( 'options' => $options ) );
561
+ }
562
+
563
+ public function radio( $args = array(), $type = 'radio' ) {
564
+ extract( $this->parse_args( $args, $type, array(
565
+ 'class' => 'cmb_radio_list cmb_list',
566
+ 'options' => $this->concat_options( array( 'label' => 'test' ) ),
567
+ 'desc' => $this->_desc( true ),
568
+ ) ) );
569
+
570
+ return sprintf( '<ul class="%s">%s</ul>%s', $class, $options, $desc );
571
+ }
572
+
573
+ public function radio_inline() {
574
+ return $this->radio( array(), 'radio_inline' );
575
+ }
576
+
577
+ public function multicheck( $type = 'checkbox' ) {
578
+ return $this->radio( array( 'class' => 'cmb_checkbox_list cmb_list', 'options' => $this->concat_options( array( 'type' => 'checkbox', 'name' => $this->_name() .'[]' ), 'list_input_checkbox' ) ), $type );
579
+ }
580
+
581
+ public function multicheck_inline() {
582
+ $this->multicheck( 'multicheck_inline' );
583
+ }
584
+
585
+ public function checkbox() {
586
+ $meta_value = $this->field->escaped_value();
587
+ $args = array( 'type' => 'checkbox', 'class' => 'cmb_option cmb_list', 'value' => 'on', 'desc' => '' );
588
+ if ( ! empty( $meta_value ) ) {
589
+ $args['checked'] = 'checked';
590
+ }
591
+ return sprintf( '%s <label for="%s">%s</label>', $this->input( $args ), $this->_id(), $this->_desc() );
592
+ }
593
+
594
+ public function taxonomy_radio() {
595
+ $names = $this->get_object_terms();
596
+ $saved_term = is_wp_error( $names ) || empty( $names ) ? $this->field->args( 'default' ) : $names[0]->slug;
597
+ $terms = get_terms( $this->field->args( 'taxonomy' ), 'hide_empty=0' );
598
+ $options = ''; $i = 1;
599
+
600
+ if ( ! $terms ) {
601
+ $options .= '<li><label>'. __( 'No terms', 'cmb' ) .'</label></li>';
602
+ } else {
603
+ foreach ( $terms as $term ) {
604
+ $args = array(
605
+ 'value' => $term->slug,
606
+ 'label' => $term->name,
607
+ );
608
+
609
+ if ( $saved_term == $term->slug ) {
610
+ $args['checked'] = 'checked';
611
+ }
612
+ $options .= $this->list_input( $args, $i );
613
+ $i++;
614
+ }
615
+ }
616
+
617
+ return $this->radio( array( 'options' => $options ), 'taxonomy_radio' );
618
+ }
619
+
620
+ public function taxonomy_radio_inline() {
621
+ $this->taxonomy_radio();
622
+ }
623
+
624
+ public function taxonomy_multicheck() {
625
+
626
+ $names = $this->get_object_terms();
627
+ $saved_terms = is_wp_error( $names ) || empty( $names )
628
+ ? $this->field->args( 'default' )
629
+ : wp_list_pluck( $names, 'slug' );
630
+ $terms = get_terms( $this->field->args( 'taxonomy' ), 'hide_empty=0' );
631
+ $name = $this->_name() .'[]';
632
+ $options = ''; $i = 1;
633
+
634
+ if ( ! $terms ) {
635
+ $options .= '<li><label>'. __( 'No terms', 'cmb' ) .'</label></li>';
636
+ } else {
637
+
638
+ foreach ( $terms as $term ) {
639
+ $args = array(
640
+ 'value' => $term->slug,
641
+ 'label' => $term->name,
642
+ 'type' => 'checkbox',
643
+ 'name' => $name,
644
+ );
645
+
646
+ if ( is_array( $saved_terms ) && in_array( $term->slug, $saved_terms ) ) {
647
+ $args['checked'] = 'checked';
648
+ }
649
+ $options .= $this->list_input( $args, $i );
650
+ $i++;
651
+ }
652
+ }
653
+
654
+ return $this->radio( array( 'class' => 'cmb_checkbox_list cmb_list', 'options' => $options ), 'taxonomy_multicheck' );
655
+ }
656
+
657
+ public function taxonomy_multicheck_inline() {
658
+ $this->taxonomy_multicheck();
659
+ }
660
+
661
+ public function file_list() {
662
+ $meta_value = $this->field->escaped_value();
663
+
664
+ $name = $this->_name();
665
+
666
+ echo $this->input( array(
667
+ 'type' => 'hidden',
668
+ 'class' => 'cmb_upload_file cmb_upload_list',
669
+ 'size' => 45, 'desc' => '', 'value' => '',
670
+ ) ),
671
+ $this->input( array(
672
+ 'type' => 'button',
673
+ 'class' => 'cmb_upload_button button cmb_upload_list',
674
+ 'value' => __( 'Add or Upload File', 'cmb' ),
675
+ 'name' => '', 'id' => '',
676
+ ) );
677
+
678
+ echo '<ul id="', $this->_id( '_status' ) ,'" class="cmb_media_status attach_list">';
679
+
680
+ if ( $meta_value && is_array( $meta_value ) ) {
681
+
682
+ foreach ( $meta_value as $id => $fullurl ) {
683
+ $id_input = $this->input( array(
684
+ 'type' => 'hidden',
685
+ 'value' => $fullurl,
686
+ 'name' => $name .'['. $id .']',
687
+ 'id' => 'filelist-'. $id,
688
+ 'desc' => '', 'class' => '',
689
+ ) );
690
+
691
+ if ( $this->is_valid_img_ext( $fullurl ) ) {
692
+ echo
693
+ '<li class="img_status">',
694
+ wp_get_attachment_image( $id, $this->field->args( 'preview_size' ) ),
695
+ '<p class="cmb_remove_wrapper"><a href="#" class="cmb_remove_file_button">'. __( 'Remove Image', 'cmb' ) .'</a></p>
696
+ '. $id_input .'
697
+ </li>';
698
+
699
+ } else {
700
+ $parts = explode( '/', $fullurl );
701
+ for ( $i = 0; $i < count( $parts ); ++$i ) {
702
+ $title = $parts[$i];
703
+ }
704
+ echo
705
+ '<li>',
706
+ __( 'File:', 'cmb' ), ' <strong>', $title, '</strong>&nbsp;&nbsp;&nbsp; (<a href="', $fullurl, '" target="_blank" rel="external">'. __( 'Download', 'cmb' ) .'</a> / <a href="#" class="cmb_remove_file_button">'. __( 'Remove', 'cmb' ) .'</a>)
707
+ '. $id_input .'
708
+ </li>';
709
+ }
710
+ }
711
+ }
712
+
713
+ echo '</ul>';
714
+ }
715
+
716
+ public function file() {
717
+ $meta_value = $this->field->escaped_value();
718
+ $allow = $this->field->args( 'allow' );
719
+ $input_type = ( 'url' == $allow || ( is_array( $allow ) && in_array( 'url', $allow ) ) )
720
+ ? 'text' : 'hidden';
721
+
722
+ echo $this->input( array(
723
+ 'type' => $input_type,
724
+ 'class' => 'cmb_upload_file',
725
+ 'size' => 45,
726
+ 'desc' => '',
727
+ ) ),
728
+ '<input class="cmb_upload_button button" type="button" value="'. __( 'Add or Upload File', 'cmb' ) .'" />',
729
+ $this->_desc( true );
730
+
731
+ $cached_id = $this->_id();
732
+ // Reset field args for attachment ID
733
+ $args = $this->field->args();
734
+ $args['id'] = $args['_id'] . '_id';
735
+ unset( $args['_id'], $args['_name'] );
736
+
737
+ // And get new field object
738
+ $this->field = new cmb_Meta_Box_field( $args, $this->field->group );
739
+
740
+ // Get ID value
741
+ $_id_value = $this->field->escaped_value( 'absint' );
742
+
743
+ // If there is no ID saved yet, try to get it from the url
744
+ if ( $meta_value && ! $_id_value ) {
745
+ $_id_value = cmb_Meta_Box::image_id_from_url( esc_url_raw( $meta_value ) );
746
+ }
747
+
748
+ echo $this->input( array(
749
+ 'type' => 'hidden',
750
+ 'class' => 'cmb_upload_file_id',
751
+ 'value' => $_id_value,
752
+ 'desc' => '',
753
+ ) ),
754
+ '<div id="', $this->_id( '_status' ) ,'" class="cmb_media_status">';
755
+ if ( ! empty( $meta_value ) ) {
756
+
757
+ if ( $this->is_valid_img_ext( $meta_value ) ) {
758
+ echo '<div class="img_status">';
759
+ echo '<img style="max-width: 350px; width: 100%; height: auto;" src="', $meta_value, '" alt="" />';
760
+ echo '<p class="cmb_remove_wrapper"><a href="#" class="cmb_remove_file_button" rel="', $cached_id, '">'. __( 'Remove Image', 'cmb' ) .'</a></p>';
761
+ echo '</div>';
762
+ } else {
763
+ // $file_ext = $this->get_file_ext( $meta_value );
764
+ $parts = explode( '/', $meta_value );
765
+ for ( $i = 0; $i < count( $parts ); ++$i ) {
766
+ $title = $parts[$i];
767
+ }
768
+ echo __( 'File:', 'cmb' ), ' <strong>', $title, '</strong>&nbsp;&nbsp;&nbsp; (<a href="', $meta_value, '" target="_blank" rel="external">'. __( 'Download', 'cmb' ) .'</a> / <a href="#" class="cmb_remove_file_button" rel="', $cached_id, '">'. __( 'Remove', 'cmb' ) .'</a>)';
769
+ }
770
+ }
771
+ echo '</div>';
772
+ }
773
+
774
+ public function oembed() {
775
+ echo $this->input( array(
776
+ 'class' => 'cmb_oembed regular-text',
777
+ 'data-objectid' => $this->field->object_id,
778
+ 'data-objecttype' => $this->field->object_type
779
+ ) ),
780
+ '<p class="cmb-spinner spinner" style="display:none;"><img src="'. admin_url( '/images/wpspin_light.gif' ) .'" alt="spinner"/></p>',
781
+ '<div id="',$this->_id( '_status' ) ,'" class="cmb_media_status ui-helper-clearfix embed_wrap">';
782
+
783
+ if ( $meta_value = $this->field->escaped_value() ) {
784
+ echo cmb_Meta_Box_ajax::get_oembed( $meta_value, $this->field->object_id, array(
785
+ 'object_type' => $this->field->object_type,
786
+ 'oembed_args' => array( 'width' => '640' ),
787
+ 'field_id' => $this->_id(),
788
+ ) );
789
+ }
790
+
791
+ echo '</div>';
792
+ }
793
+
794
+ }
lib/{metabox → cmb_metaboxes}/images/ico-delete.png RENAMED
File without changes
lib/{metabox → cmb_metaboxes}/images/ui-bg_flat_0_aaaaaa_40x100.png RENAMED
File without changes
lib/{metabox → cmb_metaboxes}/images/ui-bg_flat_75_ffffff_40x100.png RENAMED
File without changes
lib/{metabox → cmb_metaboxes}/images/ui-bg_glass_55_fbf9ee_1x400.png RENAMED
File without changes
lib/{metabox → cmb_metaboxes}/images/ui-bg_glass_65_ffffff_1x400.png RENAMED
File without changes
lib/{metabox → cmb_metaboxes}/images/ui-bg_glass_75_dadada_1x400.png RENAMED
File without changes
lib/{metabox → cmb_metaboxes}/images/ui-bg_glass_75_e6e6e6_1x400.png RENAMED
File without changes
lib/{metabox → cmb_metaboxes}/images/ui-bg_glass_95_fef1ec_1x400.png RENAMED
File without changes
lib/{metabox → cmb_metaboxes}/images/ui-bg_highlight-soft_75_cccccc_1x100.png RENAMED
File without changes
lib/{metabox → cmb_metaboxes}/images/ui-icons_222222_256x240.png RENAMED
File without changes
lib/{metabox → cmb_metaboxes}/images/ui-icons_2e83ff_256x240.png RENAMED
File without changes
lib/{metabox → cmb_metaboxes}/images/ui-icons_454545_256x240.png RENAMED
File without changes
lib/{metabox → cmb_metaboxes}/images/ui-icons_888888_256x240.png RENAMED
File without changes
lib/{metabox → cmb_metaboxes}/images/ui-icons_cd0a0a_256x240.png RENAMED
File without changes
lib/cmb_metaboxes/init.php ADDED
@@ -0,0 +1,1185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Script Name: Custom Metaboxes and Fields
4
+ Contributors: WebDevStudios (@webdevstudios / webdevstudios.com)
5
+ Justin Sternberg (@jtsternberg / dsgnwrks.pro)
6
+ Jared Atchison (@jaredatch / jaredatchison.com)
7
+ Bill Erickson (@billerickson / billerickson.net)
8
+ Andrew Norcross (@norcross / andrewnorcross.com)
9
+ Description: This will create metaboxes with custom fields that will blow your mind.
10
+ Version: 1.2.0
11
+ */
12
+
13
+ /**
14
+ * Released under the GPL license
15
+ * http://www.opensource.org/licenses/gpl-license.php
16
+ *
17
+ * This is an add-on for WordPress
18
+ * http://wordpress.org/
19
+ *
20
+ * **********************************************************************
21
+ * This program is free software; you can redistribute it and/or modify
22
+ * it under the terms of the GNU General Public License as published by
23
+ * the Free Software Foundation; either version 2 of the License, or
24
+ * (at your option) any later version.
25
+ *
26
+ * This program is distributed in the hope that it will be useful,
27
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29
+ * GNU General Public License for more details.
30
+ * **********************************************************************
31
+ */
32
+
33
+ /************************************************************************
34
+ You should not edit the code below or things might explode!
35
+ *************************************************************************/
36
+
37
+ // Autoload helper classes
38
+ spl_autoload_register('cmb_Meta_Box::autoload_helpers');
39
+
40
+ $meta_boxes = array();
41
+ $meta_boxes = apply_filters( 'cmb_meta_boxes', $meta_boxes );
42
+ foreach ( $meta_boxes as $meta_box ) {
43
+ $my_box = new cmb_Meta_Box( $meta_box );
44
+ }
45
+
46
+ define( 'CMB_META_BOX_URL', cmb_Meta_Box::get_meta_box_url() );
47
+
48
+ /**
49
+ * Create meta boxes
50
+ */
51
+ class cmb_Meta_Box {
52
+
53
+ /**
54
+ * Current version number
55
+ * @var string
56
+ * @since 1.0.0
57
+ */
58
+ const CMB_VERSION = '1.2.0';
59
+
60
+ /**
61
+ * Metabox Config array
62
+ * @var array
63
+ * @since 0.9.0
64
+ */
65
+ protected $_meta_box;
66
+
67
+ /**
68
+ * Metabox Defaults
69
+ * @var array
70
+ * @since 1.0.1
71
+ */
72
+ protected static $mb_defaults = array(
73
+ 'id' => '',
74
+ 'title' => '',
75
+ 'type' => '',
76
+ 'pages' => array(), // Post type
77
+ 'context' => 'normal',
78
+ 'priority' => 'high',
79
+ 'show_names' => true, // Show field names on the left
80
+ 'show_on' => array( 'key' => false, 'value' => false ), // Specific post IDs or page templates to display this metabox
81
+ 'cmb_styles' => true, // Include cmb bundled stylesheet
82
+ 'fields' => array(),
83
+ );
84
+
85
+ /**
86
+ * Metabox Form ID
87
+ * @var string
88
+ * @since 0.9.4
89
+ */
90
+ protected $form_id = 'post';
91
+
92
+ /**
93
+ * Current field config array
94
+ * @var array
95
+ * @since 1.0.0
96
+ */
97
+ public static $field = array();
98
+
99
+ /**
100
+ * Object ID for metabox meta retrieving/saving
101
+ * @var int
102
+ * @since 1.0.0
103
+ */
104
+ protected static $object_id = 0;
105
+
106
+ /**
107
+ * Type of object being saved. (e.g., post, user, or comment)
108
+ * @var string
109
+ * @since 1.0.0
110
+ */
111
+ protected static $object_type = '';
112
+
113
+ /**
114
+ * Whether scripts/styles have been enqueued yet
115
+ * @var bool
116
+ * @since 1.0.0
117
+ */
118
+ protected static $is_enqueued = false;
119
+
120
+ /**
121
+ * Whether CMB nonce has been added to the page. (oly add once)
122
+ * @var bool
123
+ * @since 1.2.0
124
+ */
125
+ protected static $nonce_added = false;
126
+
127
+ /**
128
+ * Type of object specified by the metabox Config
129
+ * @var string
130
+ * @since 1.0.0
131
+ */
132
+ protected static $mb_object_type = 'post';
133
+
134
+ /**
135
+ * Array of all options from manage-options metaboxes
136
+ * @var array
137
+ * @since 1.0.0
138
+ */
139
+ protected static $options = array();
140
+
141
+ /**
142
+ * List of fields that are changed/updated on save
143
+ * @var array
144
+ * @since 1.1.0
145
+ */
146
+ protected static $updated = array();
147
+
148
+ /**
149
+ * Get started
150
+ */
151
+ function __construct( $meta_box ) {
152
+
153
+ $meta_box = self::set_mb_defaults( $meta_box );
154
+
155
+ $allow_frontend = apply_filters( 'cmb_allow_frontend', true, $meta_box );
156
+
157
+ if ( ! is_admin() && ! $allow_frontend )
158
+ return;
159
+
160
+ $this->_meta_box = $meta_box;
161
+
162
+ self::set_mb_type( $meta_box );
163
+
164
+ $types = wp_list_pluck( $meta_box['fields'], 'type' );
165
+ $upload = in_array( 'file', $types ) || in_array( 'file_list', $types );
166
+
167
+ global $pagenow;
168
+
169
+ $show_filters = 'cmb_Meta_Box_Show_Filters';
170
+ foreach ( get_class_methods( $show_filters ) as $filter ) {
171
+ add_filter( 'cmb_show_on', array( $show_filters, $filter ), 10, 2 );
172
+ }
173
+
174
+ // register our scripts and styles for cmb
175
+ add_action( 'admin_enqueue_scripts', array( $this, 'register_scripts' ), 8 );
176
+
177
+ if ( self::get_object_type() == 'post' ) {
178
+ add_action( 'admin_menu', array( $this, 'add_metaboxes' ) );
179
+ add_action( 'add_attachment', array( $this, 'save_post' ) );
180
+ add_action( 'edit_attachment', array( $this, 'save_post' ) );
181
+ add_action( 'save_post', array( $this, 'save_post' ), 10, 2 );
182
+ add_action( 'admin_enqueue_scripts', array( $this, 'do_scripts' ) );
183
+
184
+ if ( $upload && in_array( $pagenow, array( 'page.php', 'page-new.php', 'post.php', 'post-new.php' ) ) ) {
185
+ add_action( 'admin_head', array( $this, 'add_post_enctype' ) );
186
+ }
187
+
188
+ }
189
+ if ( self::get_object_type() == 'user' ) {
190
+
191
+ $priority = 10;
192
+ if ( isset( $meta_box['priority'] ) ) {
193
+ if ( is_numeric( $meta_box['priority'] ) )
194
+ $priority = $meta_box['priority'];
195
+ elseif ( $meta_box['priority'] == 'high' )
196
+ $priority = 5;
197
+ elseif ( $meta_box['priority'] == 'low' )
198
+ $priority = 20;
199
+ }
200
+ add_action( 'show_user_profile', array( $this, 'user_metabox' ), $priority );
201
+ add_action( 'edit_user_profile', array( $this, 'user_metabox' ), $priority );
202
+
203
+ add_action( 'personal_options_update', array( $this, 'save_user' ) );
204
+ add_action( 'edit_user_profile_update', array( $this, 'save_user' ) );
205
+ if ( $upload && in_array( $pagenow, array( 'profile.php', 'user-edit.php' ) ) ) {
206
+ $this->form_id = 'your-profile';
207
+ add_action( 'admin_head', array( $this, 'add_post_enctype' ) );
208
+ }
209
+ }
210
+
211
+ }
212
+
213
+ /**
214
+ * Autoloads files with classes when needed
215
+ * @since 1.0.0
216
+ * @param string $class_name Name of the class being requested
217
+ */
218
+ public static function autoload_helpers( $class_name ) {
219
+ if ( class_exists( $class_name, false ) )
220
+ return;
221
+
222
+ // for PHP versions < 5.3
223
+ $dir = dirname( __FILE__ );
224
+
225
+ $file = "$dir/helpers/$class_name.php";
226
+ if ( file_exists( $file ) )
227
+ @include( $file );
228
+ }
229
+
230
+ /**
231
+ * Registers scripts and styles for CMB
232
+ * @since 1.0.0
233
+ */
234
+ public function register_scripts() {
235
+
236
+ // Should only be run once
237
+ if ( self::$is_enqueued )
238
+ return;
239
+
240
+ global $wp_version;
241
+ // Only use minified files if SCRIPT_DEBUG is off
242
+ $min = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min';
243
+
244
+ // scripts required for cmb
245
+ $scripts = array( 'jquery', 'jquery-ui-core', 'cmb-datepicker', /*'media-upload', */'cmb-timepicker' );
246
+ // styles required for cmb
247
+ $styles = array();
248
+
249
+ // if we're 3.5 or later, user wp-color-picker
250
+ if ( 3.5 <= $wp_version ) {
251
+ $scripts[] = 'wp-color-picker';
252
+ $styles[] = 'wp-color-picker';
253
+ if ( ! is_admin() ) {
254
+ // we need to register colorpicker on the front-end
255
+ wp_register_script( 'iris', admin_url( 'js/iris.min.js' ), array( 'jquery-ui-draggable', 'jquery-ui-slider', 'jquery-touch-punch' ), self::CMB_VERSION );
256
+ wp_register_script( 'wp-color-picker', admin_url( 'js/color-picker.min.js' ), array( 'iris' ), self::CMB_VERSION );
257
+ wp_localize_script( 'wp-color-picker', 'wpColorPickerL10n', array(
258
+ 'clear' => __( 'Clear' ),
259
+ 'defaultString' => __( 'Default' ),
260
+ 'pick' => __( 'Select Color' ),
261
+ 'current' => __( 'Current Color' ),
262
+ ) );
263
+ }
264
+ } else {
265
+ // otherwise use the older 'farbtastic'
266
+ $scripts[] = 'farbtastic';
267
+ $styles[] = 'farbtastic';
268
+ }
269
+ wp_register_script( 'cmb-datepicker', CMB_META_BOX_URL . 'js/jquery.datePicker.min.js' );
270
+ wp_register_script( 'cmb-timepicker', CMB_META_BOX_URL . 'js/jquery.timePicker.min.js' );
271
+ wp_register_script( 'cmb-scripts', CMB_META_BOX_URL .'js/cmb'. $min .'.js', $scripts, self::CMB_VERSION );
272
+
273
+ wp_enqueue_media();
274
+
275
+ wp_localize_script( 'cmb-scripts', 'cmb_l10', apply_filters( 'cmb_localized_data', array(
276
+ 'ajax_nonce' => wp_create_nonce( 'ajax_nonce' ),
277
+ 'script_debug' => defined('SCRIPT_DEBUG') && SCRIPT_DEBUG,
278
+ 'new_admin_style' => version_compare( $wp_version, '3.7', '>' ),
279
+ 'object_type' => self::get_object_type(),
280
+ 'upload_file' => 'Use this file',
281
+ 'remove_image' => 'Remove Image',
282
+ 'remove_file' => 'Remove',
283
+ 'file' => 'File:',
284
+ 'download' => 'Download',
285
+ 'ajaxurl' => admin_url( '/admin-ajax.php' ),
286
+ 'up_arrow' => '[ ↑ ]&nbsp;',
287
+ 'down_arrow' => '&nbsp;[ ↓ ]',
288
+ 'check_toggle' => __( 'Select / Deselect All', 'cmb' ),
289
+ ) ) );
290
+
291
+ wp_register_style( 'cmb-styles', CMB_META_BOX_URL . 'style'. $min .'.css', $styles );
292
+
293
+ // Ok, we've enqueued our scripts/styles
294
+ self::$is_enqueued = true;
295
+ }
296
+
297
+ /**
298
+ * Enqueues scripts and styles for CMB
299
+ * @since 1.0.0
300
+ */
301
+ public function do_scripts( $hook ) {
302
+ // only enqueue our scripts/styles on the proper pages
303
+ if ( $hook == 'post.php' || $hook == 'post-new.php' || $hook == 'page-new.php' || $hook == 'page.php' ) {
304
+ wp_enqueue_script( 'cmb-scripts' );
305
+
306
+ // default is to show cmb styles on post pages
307
+ if ( $this->_meta_box['cmb_styles'] )
308
+ wp_enqueue_style( 'cmb-styles' );
309
+ }
310
+ }
311
+
312
+ /**
313
+ * Add encoding attribute
314
+ */
315
+ public function add_post_enctype() {
316
+ echo '
317
+ <script type="text/javascript">
318
+ jQuery(document).ready(function(){
319
+ jQuery("#'. $this->form_id .'").attr("enctype", "multipart/form-data");
320
+ jQuery("#'. $this->form_id .'").attr("encoding", "multipart/form-data");
321
+ });
322
+ </script>';
323
+ }
324
+
325
+ /**
326
+ * Add metaboxes (to 'post' object type)
327
+ */
328
+ public function add_metaboxes() {
329
+
330
+ foreach ( $this->_meta_box['pages'] as $page ) {
331
+ if ( apply_filters( 'cmb_show_on', true, $this->_meta_box ) )
332
+ add_meta_box( $this->_meta_box['id'], $this->_meta_box['title'], array( $this, 'post_metabox' ), $page, $this->_meta_box['context'], $this->_meta_box['priority']) ;
333
+ }
334
+ }
335
+
336
+ /**
337
+ * Display metaboxes for a post object
338
+ * @since 1.0.0
339
+ */
340
+ public function post_metabox() {
341
+ if ( ! $this->_meta_box )
342
+ return;
343
+
344
+ self::show_form( $this->_meta_box, get_the_ID(), 'post' );
345
+
346
+ }
347
+
348
+ /**
349
+ * Display metaboxes for a user object
350
+ * @since 1.0.0
351
+ */
352
+ public function user_metabox() {
353
+ if ( ! $this->_meta_box )
354
+ return;
355
+
356
+ if ( 'user' != self::set_mb_type( $this->_meta_box ) )
357
+ return;
358
+
359
+ if ( ! apply_filters( 'cmb_show_on', true, $this->_meta_box ) )
360
+ return;
361
+
362
+ wp_enqueue_script( 'cmb-scripts' );
363
+
364
+ // default is to NOT show cmb styles on user profile page
365
+ if ( $this->_meta_box['cmb_styles'] != false )
366
+ wp_enqueue_style( 'cmb-styles' );
367
+
368
+ self::show_form( $this->_meta_box );
369
+
370
+ }
371
+
372
+ /**
373
+ * Loops through and displays fields
374
+ * @since 1.0.0
375
+ * @param array $meta_box Metabox config array
376
+ * @param int $object_id Object ID
377
+ * @param string $object_type Type of object being saved. (e.g., post, user, or comment)
378
+ */
379
+ public static function show_form( $meta_box, $object_id = 0, $object_type = '' ) {
380
+ $meta_box = self::set_mb_defaults( $meta_box );
381
+ // Set/get type
382
+ $object_type = self::set_object_type( $object_type ? $object_type : self::set_mb_type( $meta_box ) );
383
+ // Set/get ID
384
+ $object_id = self::set_object_id( $object_id ? $object_id : self::get_object_id() );
385
+
386
+ // Add nonce only once per page.
387
+ if ( ! self::$nonce_added ) {
388
+ wp_nonce_field( self::nonce(), 'wp_meta_box_nonce', false, true );
389
+ self::$nonce_added = true;
390
+ }
391
+
392
+ // Use nonce for verification
393
+ echo "\n<!-- Begin CMB Fields -->\n";
394
+ do_action( 'cmb_before_table', $meta_box, $object_id, $object_type );
395
+ echo '<table class="form-table cmb_metabox">';
396
+
397
+ foreach ( $meta_box['fields'] as $field_args ) {
398
+
399
+ $field_args['context'] = $meta_box['context'];
400
+
401
+ if ( 'group' == $field_args['type'] ) {
402
+
403
+ if ( ! isset( $field_args['show_names'] ) ) {
404
+ $field_args['show_names'] = $meta_box['show_names'];
405
+ }
406
+ self::render_group( $field_args );
407
+ } else {
408
+
409
+ $field_args['show_names'] = $meta_box['show_names'];
410
+ // Render default fields
411
+ $field = new cmb_Meta_Box_field( $field_args );
412
+ $field->render_field();
413
+ }
414
+ }
415
+ echo '</table>';
416
+ do_action( 'cmb_after_table', $meta_box, $object_id, $object_type );
417
+ echo "\n<!-- End CMB Fields -->\n";
418
+
419
+ }
420
+
421
+ /**
422
+ * Render a repeatable group
423
+ */
424
+ public static function render_group( $args ) {
425
+ if ( ! isset( $args['id'], $args['fields'] ) || ! is_array( $args['fields'] ) )
426
+ return;
427
+
428
+ $args['count'] = 0;
429
+ $field_group = new cmb_Meta_Box_field( $args );
430
+ $desc = $field_group->args( 'description' );
431
+ $label = $field_group->args( 'name' );
432
+ $sortable = $field_group->options( 'sortable' ) ? ' sortable' : '';
433
+ $group_val = (array) $field_group->value();
434
+ $nrows = count( $group_val );
435
+ $remove_disabled = $nrows <= 1 ? 'disabled="disabled" ' : '';
436
+
437
+ echo '<tr><td colspan="2"><table id="', $field_group->id(), '_repeat" class="repeatable-group'. $sortable .'" style="width:100%;">';
438
+ if ( $desc || $label ) {
439
+ echo '<tr><th>';
440
+ if ( $label )
441
+ echo '<h2 class="cmb-group-name">'. $label .'</h2>';
442
+ if ( $desc )
443
+ echo '<p class="cmb_metabox_description">'. $desc .'</p>';
444
+ echo '</th></tr>';
445
+ }
446
+
447
+ if ( ! empty( $group_val ) ) {
448
+
449
+ foreach ( $group_val as $iterator => $field_id ) {
450
+ self::render_group_row( $field_group, $remove_disabled );
451
+ }
452
+ } else {
453
+ self::render_group_row( $field_group, $remove_disabled );
454
+ }
455
+
456
+ echo '<tr><td><p class="add-row"><button data-selector="', $field_group->id() ,'_repeat" data-grouptitle="', $field_group->options( 'group_title' ) ,'" class="add-group-row button">'. $field_group->options( 'add_button' ) .'</button></p></td></tr>';
457
+
458
+ echo '</table></td></tr>';
459
+
460
+ }
461
+
462
+ public static function render_group_row( $field_group, $remove_disabled ) {
463
+
464
+ echo '
465
+ <tr class="repeatable-grouping" data-iterator="'. $field_group->count() .'">
466
+ <td>
467
+ <table class="cmb-nested-table" style="width: 100%;">';
468
+ if ( $field_group->options( 'group_title' ) ) {
469
+ echo '
470
+ <tr class="cmb-group-title">
471
+ <th colspan="2">
472
+ ', sprintf( '<h4>%1$s</h4>', $field_group->replace_hash( $field_group->options( 'group_title' ) ) ), '
473
+ <th>
474
+ </tr>
475
+ ';
476
+ }
477
+ // Render repeatable group fields
478
+ foreach ( array_values( $field_group->args( 'fields' ) ) as $field_args ) {
479
+ $field_args['show_names'] = $field_group->args( 'show_names' );
480
+ $field_args['context'] = $field_group->args( 'context' );
481
+ $field = new cmb_Meta_Box_field( $field_args, $field_group );
482
+ $field->render_field();
483
+ }
484
+ echo '
485
+ <tr>
486
+ <td class="remove-row" colspan="2">
487
+ <button '. $remove_disabled .'data-selector="'. $field_group->id() .'_repeat" class="button remove-group-row alignright">'. $field_group->options( 'remove_button' ) .'</button>
488
+ </td>
489
+ </tr>
490
+ </table>
491
+ </td>
492
+ </tr>
493
+ ';
494
+
495
+ $field_group->args['count']++;
496
+ }
497
+
498
+ /**
499
+ * Save data from metabox
500
+ */
501
+ public function save_post( $post_id, $post = false ) {
502
+
503
+ $post_type = $post ? $post->post_type : get_post_type( $post_id );
504
+
505
+ // check permissions
506
+ if (
507
+ // check nonce
508
+ ! isset( $_POST['wp_meta_box_nonce'] )
509
+ || ! wp_verify_nonce( $_POST['wp_meta_box_nonce'], self::nonce() )
510
+ // check if autosave
511
+ || defined('DOING_AUTOSAVE' ) && DOING_AUTOSAVE
512
+ // check user editing permissions
513
+ || ( 'page' == $_POST['post_type'] && ! current_user_can( 'edit_page', $post_id ) )
514
+ || ! current_user_can( 'edit_post', $post_id )
515
+ // get the metabox post_types & compare it to this post_type
516
+ || ! in_array( $post_type, $this->_meta_box['pages'] )
517
+ )
518
+ return $post_id;
519
+
520
+ self::save_fields( $this->_meta_box, $post_id, 'post' );
521
+ }
522
+
523
+ /**
524
+ * Save data from metabox
525
+ */
526
+ public function save_user( $user_id ) {
527
+
528
+ // check permissions
529
+ // @todo more hardening?
530
+ if (
531
+ // check nonce
532
+ ! isset( $_POST['wp_meta_box_nonce'] )
533
+ || ! wp_verify_nonce( $_POST['wp_meta_box_nonce'], self::nonce() )
534
+ )
535
+ return $user_id;
536
+
537
+ self::save_fields( $this->_meta_box, $user_id, 'user' );
538
+ }
539
+
540
+ /**
541
+ * Loops through and saves field data
542
+ * @since 1.0.0
543
+ * @param array $meta_box Metabox config array
544
+ * @param int $object_id Object ID
545
+ * @param string $object_type Type of object being saved. (e.g., post, user, or comment)
546
+ */
547
+ public static function save_fields( $meta_box, $object_id, $object_type = '' ) {
548
+ $meta_box = self::set_mb_defaults( $meta_box );
549
+
550
+ $meta_box['show_on'] = empty( $meta_box['show_on'] ) ? array( 'key' => false, 'value' => false ) : $meta_box['show_on'];
551
+
552
+ self::set_object_id( $object_id );
553
+ // Set/get type
554
+ $object_type = self::set_object_type( $object_type ? $object_type : self::set_mb_type( $meta_box ) );
555
+
556
+ if ( ! apply_filters( 'cmb_show_on', true, $meta_box ) )
557
+ return;
558
+
559
+ // save field ids of those that are updated
560
+ self::$updated = array();
561
+
562
+ foreach ( $meta_box['fields'] as $field_args ) {
563
+
564
+ if ( 'group' == $field_args['type'] ) {
565
+ self::save_group( $field_args );
566
+ } else {
567
+ // Save default fields
568
+ $field = new cmb_Meta_Box_field( $field_args );
569
+ self::save_field( self::sanitize_field( $field ), $field );
570
+ }
571
+
572
+ }
573
+
574
+ // If options page, save the updated options
575
+ if ( $object_type == 'options-page' )
576
+ self::save_option( $object_id );
577
+
578
+ do_action( "cmb_save_{$object_type}_fields", $object_id, $meta_box['id'], self::$updated, $meta_box );
579
+
580
+ }
581
+
582
+ /**
583
+ * Save a repeatable group
584
+ */
585
+ public static function save_group( $args ) {
586
+ if ( ! isset( $args['id'], $args['fields'], $_POST[ $args['id'] ] ) || ! is_array( $args['fields'] ) )
587
+ return;
588
+
589
+ $field_group = new cmb_Meta_Box_field( $args );
590
+ $base_id = $field_group->id();
591
+ $old = $field_group->get_data();
592
+ $group_vals = $_POST[ $base_id ];
593
+ $saved = array();
594
+ $is_updated = false;
595
+ $field_group->index = 0;
596
+
597
+ // $group_vals[0]['color'] = '333';
598
+ foreach ( array_values( $field_group->fields() ) as $field_args ) {
599
+ $field = new cmb_Meta_Box_field( $field_args, $field_group );
600
+ $sub_id = $field->id( true );
601
+
602
+ foreach ( (array) $group_vals as $field_group->index => $post_vals ) {
603
+
604
+ // Get value
605
+ $new_val = isset( $group_vals[ $field_group->index ][ $sub_id ] )
606
+ ? $group_vals[ $field_group->index ][ $sub_id ]
607
+ : false;
608
+
609
+ // Sanitize
610
+ $new_val = self::sanitize_field( $field, $new_val, $field_group->index );
611
+
612
+ if ( 'file' == $field->type() && is_array( $new_val ) ) {
613
+ // Add image ID to the array stack
614
+ $saved[ $field_group->index ][ $new_val['field_id'] ] = $new_val['attach_id'];
615
+ // Reset var to url string
616
+ $new_val = $new_val['url'];
617
+ }
618
+
619
+ // Get old value
620
+ $old_val = is_array( $old ) && isset( $old[ $field_group->index ][ $sub_id ] )
621
+ ? $old[ $field_group->index ][ $sub_id ]
622
+ : false;
623
+
624
+ $is_updated = ( ! empty( $new_val ) && $new_val != $old_val );
625
+ $is_removed = ( empty( $new_val ) && ! empty( $old_val ) );
626
+ // Compare values and add to `$updated` array
627
+ if ( $is_updated || $is_removed )
628
+ self::$updated[] = $base_id .'::'. $field_group->index .'::'. $sub_id;
629
+
630
+ // Add to `$saved` array
631
+ $saved[ $field_group->index ][ $sub_id ] = $new_val;
632
+
633
+ }
634
+ $saved[ $field_group->index ] = array_filter( $saved[ $field_group->index ] );
635
+ }
636
+ $saved = array_filter( $saved );
637
+
638
+ $field_group->update_data( $saved, true );
639
+ }
640
+
641
+ public static function sanitize_field( $field, $new_value = null ) {
642
+
643
+ $new_value = null !== $new_value
644
+ ? $new_value
645
+ : ( isset( $_POST[ $field->id( true ) ] ) ? $_POST[ $field->id( true ) ] : null );
646
+
647
+ if ( $field->args( 'repeatable' ) && is_array( $new_value ) ) {
648
+ // Remove empties
649
+ $new_value = array_filter( $new_value );
650
+ }
651
+
652
+ // Check if this metabox field has a registered validation callback, or perform default sanitization
653
+ return $field->sanitization_cb( $new_value );
654
+ }
655
+
656
+ public static function save_field( $new_value, $field ) {
657
+ $name = $field->id();
658
+ $old = $field->get_data();
659
+
660
+ // if ( $field->args( 'multiple' ) && ! $field->args( 'repeatable' ) && ! $field->group ) {
661
+ // $field->remove_data();
662
+ // if ( ! empty( $new_value ) ) {
663
+ // foreach ( $new_value as $add_new ) {
664
+ // self::$updated[] = $name;
665
+ // $field->update_data( $add_new, $name, false );
666
+ // }
667
+ // }
668
+ // } else
669
+ if ( ! empty( $new_value ) && $new_value != $old ) {
670
+ self::$updated[] = $name;
671
+ return $field->update_data( $new_value );
672
+ } elseif ( empty( $new_value ) ) {
673
+ if ( ! empty( $old ) )
674
+ self::$updated[] = $name;
675
+ return $field->remove_data();
676
+ }
677
+ }
678
+
679
+ /**
680
+ * Get object id from global space if no id is provided
681
+ * @since 1.0.0
682
+ * @param integer $object_id Object ID
683
+ * @return integer $object_id Object ID
684
+ */
685
+ public static function get_object_id( $object_id = 0 ) {
686
+
687
+ if ( $object_id )
688
+ return $object_id;
689
+
690
+ if ( self::$object_id )
691
+ return self::$object_id;
692
+
693
+ // Try to get our object ID from the global space
694
+ switch ( self::get_object_type() ) {
695
+ case 'user':
696
+ $object_id = isset( $GLOBALS['user_ID'] ) ? $GLOBALS['user_ID'] : $object_id;
697
+ $object_id = isset( $_REQUEST['user_id'] ) ? $_REQUEST['user_id'] : $object_id;
698
+ break;
699
+
700
+ default:
701
+ $object_id = isset( $GLOBALS['post']->ID ) ? $GLOBALS['post']->ID : $object_id;
702
+ $object_id = isset( $_REQUEST['post'] ) ? $_REQUEST['post'] : $object_id;
703
+ break;
704
+ }
705
+
706
+ // reset to id or 0
707
+ self::set_object_id( $object_id ? $object_id : 0 );
708
+
709
+ return self::$object_id;
710
+ }
711
+
712
+ /**
713
+ * Explicitly Set object id
714
+ * @since 1.0.0
715
+ * @param integer $object_id Object ID
716
+ * @return integer $object_id Object ID
717
+ */
718
+ public static function set_object_id( $object_id ) {
719
+ return self::$object_id = $object_id;
720
+ }
721
+
722
+ /**
723
+ * Sets the $object_type based on metabox settings
724
+ * @since 1.0.0
725
+ * @param array|string $meta_box Metabox config array or explicit setting
726
+ * @return string Object type
727
+ */
728
+ public static function set_mb_type( $meta_box ) {
729
+
730
+ if ( is_string( $meta_box ) ) {
731
+ self::$mb_object_type = $meta_box;
732
+ return self::get_mb_type();
733
+ }
734
+
735
+ if ( ! isset( $meta_box['pages'] ) )
736
+ return self::get_mb_type();
737
+
738
+ $type = false;
739
+ // check if 'pages' is a string
740
+ if ( self::is_options_page_mb( $meta_box ) )
741
+ $type = 'options-page';
742
+ // check if 'pages' is a string
743
+ elseif ( is_string( $meta_box['pages'] ) )
744
+ $type = $meta_box['pages'];
745
+ // if it's an array of one, extract it
746
+ elseif ( is_array( $meta_box['pages'] ) && count( $meta_box['pages'] === 1 ) )
747
+ $type = is_string( end( $meta_box['pages'] ) ) ? end( $meta_box['pages'] ) : false;
748
+
749
+ if ( !$type )
750
+ return self::get_mb_type();
751
+
752
+ // Get our object type
753
+ if ( 'user' == $type )
754
+ self::$mb_object_type = 'user';
755
+ elseif ( 'comment' == $type )
756
+ self::$mb_object_type = 'comment';
757
+ elseif ( 'options-page' == $type )
758
+ self::$mb_object_type = 'options-page';
759
+ else
760
+ self::$mb_object_type = 'post';
761
+
762
+ return self::get_mb_type();
763
+ }
764
+
765
+ /**
766
+ * Determines if metabox is for an options page
767
+ * @since 1.0.1
768
+ * @param array $meta_box Metabox config array
769
+ * @return boolean True/False
770
+ */
771
+ public static function is_options_page_mb( $meta_box ) {
772
+ return ( isset( $meta_box['show_on']['key'] ) && 'options-page' === $meta_box['show_on']['key'] );
773
+ }
774
+
775
+ /**
776
+ * Returns the object type
777
+ * @since 1.0.0
778
+ * @return string Object type
779
+ */
780
+ public static function get_object_type() {
781
+ if ( self::$object_type )
782
+ return self::$object_type;
783
+
784
+ global $pagenow;
785
+
786
+ if (
787
+ $pagenow == 'user-edit.php'
788
+ || $pagenow == 'profile.php'
789
+ )
790
+ self::set_object_type( 'user' );
791
+
792
+ elseif (
793
+ $pagenow == 'edit-comments.php'
794
+ || $pagenow == 'comment.php'
795
+ )
796
+ self::set_object_type( 'comment' );
797
+ else
798
+ self::set_object_type( 'post' );
799
+
800
+ return self::$object_type;
801
+ }
802
+
803
+ /**
804
+ * Sets the object type
805
+ * @since 1.0.0
806
+ * @return string Object type
807
+ */
808
+ public static function set_object_type( $object_type ) {
809
+ return self::$object_type = $object_type;
810
+ }
811
+
812
+ /**
813
+ * Returns the object type
814
+ * @since 1.0.0
815
+ * @return string Object type
816
+ */
817
+ public static function get_mb_type() {
818
+ return self::$mb_object_type;
819
+ }
820
+
821
+ /**
822
+ * Returns the nonce value for wp_meta_box_nonce
823
+ * @since 1.0.0
824
+ * @return string Nonce value
825
+ */
826
+ public static function nonce() {
827
+ return basename( __FILE__ );
828
+ }
829
+
830
+ /**
831
+ * Defines the url which is used to load local resources.
832
+ * This may need to be filtered for local Window installations.
833
+ * If resources do not load, please check the wiki for details.
834
+ * @since 1.0.1
835
+ * @return string URL to CMB resources
836
+ */
837
+ public static function get_meta_box_url() {
838
+
839
+ if ( strtoupper( substr( PHP_OS, 0, 3 ) ) === 'WIN' ) {
840
+ // Windows
841
+ $content_dir = str_replace( '/', DIRECTORY_SEPARATOR, WP_CONTENT_DIR );
842
+ $content_url = str_replace( $content_dir, WP_CONTENT_URL, dirname(__FILE__) );
843
+ $cmb_url = str_replace( DIRECTORY_SEPARATOR, '/', $content_url );
844
+
845
+ } else {
846
+ $cmb_url = str_replace(
847
+ array(WP_CONTENT_DIR, WP_PLUGIN_DIR),
848
+ array(WP_CONTENT_URL, WP_PLUGIN_URL),
849
+ dirname( __FILE__ )
850
+ );
851
+ }
852
+
853
+ return trailingslashit( apply_filters('cmb_meta_box_url', $cmb_url ) );
854
+ }
855
+
856
+ /**
857
+ * Fills in empty metabox parameters with defaults
858
+ * @since 1.0.1
859
+ * @param array $meta_box Metabox config array
860
+ * @return array Modified Metabox config array
861
+ */
862
+ public static function set_mb_defaults( $meta_box ) {
863
+ return wp_parse_args( $meta_box, self::$mb_defaults );
864
+ }
865
+
866
+ /**
867
+ * Removes an option from an option array
868
+ * @since 1.0.1
869
+ * @param string $option_key Option key
870
+ * @param string $field_id Option array field key
871
+ * @return array Modified options
872
+ */
873
+ public static function remove_option( $option_key, $field_id ) {
874
+
875
+ self::$options[ $option_key ] = ! isset( self::$options[ $option_key ] ) || empty( self::$options[ $option_key ] ) ? self::_get_option( $option_key ) : self::$options[ $option_key ];
876
+
877
+ if ( isset( self::$options[ $option_key ][ $field_id ] ) )
878
+ unset( self::$options[ $option_key ][ $field_id ] );
879
+
880
+ return self::$options[ $option_key ];
881
+ }
882
+
883
+ /**
884
+ * Retrieves an option from an option array
885
+ * @since 1.0.1
886
+ * @param string $option_key Option key
887
+ * @param string $field_id Option array field key
888
+ * @return array Options array or specific field
889
+ */
890
+ public static function get_option( $option_key, $field_id = '' ) {
891
+
892
+ self::$options[ $option_key ] = ! isset( self::$options[ $option_key ] ) || empty( self::$options[ $option_key ] ) ? self::_get_option( $option_key ) : self::$options[ $option_key ];
893
+
894
+ if ( $field_id ) {
895
+ return isset( self::$options[ $option_key ][ $field_id ] ) ? self::$options[ $option_key ][ $field_id ] : false;
896
+ }
897
+
898
+ return self::$options[ $option_key ];
899
+ }
900
+
901
+ /**
902
+ * Updates Option data
903
+ * @since 1.0.1
904
+ * @param string $option_key Option key
905
+ * @param string $field_id Option array field key
906
+ * @param mixed $value Value to update data with
907
+ * @param bool $single Whether data should be an array
908
+ * @return array Modified options
909
+ */
910
+ public static function update_option( $option_key, $field_id, $value, $single = true ) {
911
+
912
+ if ( ! $single ) {
913
+ // If multiple, add to array
914
+ self::$options[ $option_key ][ $field_id ][] = $value;
915
+ } else {
916
+ self::$options[ $option_key ][ $field_id ] = $value;
917
+ }
918
+
919
+ return self::$options[ $option_key ];
920
+ }
921
+
922
+ /**
923
+ * Retrieve option value based on name of option.
924
+ * @uses apply_filters() Calls 'cmb_override_option_get_$option_key' hook to allow
925
+ * overwriting the option value to be retrieved.
926
+ *
927
+ * @since 1.0.1
928
+ * @param string $option Name of option to retrieve. Expected to not be SQL-escaped.
929
+ * @param mixed $default Optional. Default value to return if the option does not exist.
930
+ * @return mixed Value set for the option.
931
+ */
932
+ public static function _get_option( $option_key, $default = false ) {
933
+
934
+ $test_get = apply_filters( "cmb_override_option_get_$option_key", 'cmb_no_override_option_get', $default );
935
+
936
+ if ( $test_get !== 'cmb_no_override_option_get' )
937
+ return $test_get;
938
+
939
+ // If no override, get the option
940
+ return get_option( $option_key, $default );
941
+ }
942
+
943
+ /**
944
+ * Saves the option array
945
+ * Needs to be run after finished using remove/update_option
946
+ * @uses apply_filters() Calls 'cmb_override_option_save_$option_key' hook to allow
947
+ * overwriting the option value to be stored.
948
+ *
949
+ * @since 1.0.1
950
+ * @param string $option_key Option key
951
+ * @return boolean Success/Failure
952
+ */
953
+ public static function save_option( $option_key ) {
954
+
955
+ $to_save = self::get_option( $option_key );
956
+
957
+ $test_save = apply_filters( "cmb_override_option_save_$option_key", 'cmb_no_override_option_save', $to_save );
958
+
959
+ if ( $test_save !== 'cmb_no_override_option_save' )
960
+ return $test_save;
961
+
962
+ // If no override, update the option
963
+ return update_option( $option_key, $to_save );
964
+ }
965
+
966
+ /**
967
+ * Utility method that returns a timezone string representing the default timezone for the site.
968
+ *
969
+ * Roughly copied from WordPress, as get_option('timezone_string') will return
970
+ * and empty string if no value has beens set on the options page.
971
+ * A timezone string is required by the wp_timezone_choice() used by the
972
+ * select_timezone field.
973
+ *
974
+ * @since 1.0.0
975
+ * @return string Timezone string
976
+ */
977
+ public static function timezone_string() {
978
+ $current_offset = get_option( 'gmt_offset' );
979
+ $tzstring = get_option( 'timezone_string' );
980
+
981
+ if ( empty( $tzstring ) ) { // Create a UTC+- zone if no timezone string exists
982
+ if ( 0 == $current_offset )
983
+ $tzstring = 'UTC+0';
984
+ elseif ( $current_offset < 0 )
985
+ $tzstring = 'UTC' . $current_offset;
986
+ else
987
+ $tzstring = 'UTC+' . $current_offset;
988
+ }
989
+
990
+ return $tzstring;
991
+ }
992
+
993
+ /**
994
+ * Utility method that returns time string offset by timezone
995
+ * @since 1.0.0
996
+ * @param string $tzstring Time string
997
+ * @return string Offset time string
998
+ */
999
+ public static function timezone_offset( $tzstring ) {
1000
+ if ( ! empty( $tzstring ) && is_string( $tzstring ) ) {
1001
+ if ( substr( $tzstring, 0, 3 ) === 'UTC' ) {
1002
+ $tzstring = str_replace( array( ':15',':30',':45' ), array( '.25','.5','.75' ), $tzstring );
1003
+ return intval( floatval( substr( $tzstring, 3 ) ) * HOUR_IN_SECONDS );
1004
+ }
1005
+
1006
+ $date_time_zone_selected = new DateTimeZone( $tzstring );
1007
+ $tz_offset = timezone_offset_get( $date_time_zone_selected, date_create() );
1008
+
1009
+ return $tz_offset;
1010
+ }
1011
+
1012
+ return 0;
1013
+ }
1014
+
1015
+ /**
1016
+ * Utility method that attempts to get an attachment's ID by it's url
1017
+ * @since 1.0.0
1018
+ * @param string $img_url Attachment url
1019
+ * @return mixed Attachment ID or false
1020
+ */
1021
+ public static function image_id_from_url( $img_url ) {
1022
+ global $wpdb;
1023
+
1024
+ $img_url = esc_url_raw( $img_url );
1025
+ // Get just the file name
1026
+ if ( false !== strpos( $img_url, '/' ) ) {
1027
+ $explode = explode( '/', $img_url );
1028
+ $img_url = end( $explode );
1029
+ }
1030
+
1031
+ // And search for a fuzzy match of the file name
1032
+ $attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid LIKE '%%%s%%' LIMIT 1;", $img_url ) );
1033
+
1034
+ // If we found an attachement ID, return it
1035
+ if ( !empty( $attachment ) && is_array( $attachment ) )
1036
+ return $attachment[0];
1037
+
1038
+ // No luck
1039
+ return false;
1040
+ }
1041
+
1042
+ }
1043
+
1044
+ // Handle oembed Ajax
1045
+ add_action( 'wp_ajax_cmb_oembed_handler', array( 'cmb_Meta_Box_ajax', 'oembed_handler' ) );
1046
+ add_action( 'wp_ajax_nopriv_cmb_oembed_handler', array( 'cmb_Meta_Box_ajax', 'oembed_handler' ) );
1047
+
1048
+ /**
1049
+ * A helper function to get an option from a CMB options array
1050
+ * @since 1.0.1
1051
+ * @param string $option_key Option key
1052
+ * @param string $field_id Option array field key
1053
+ * @return array Options array or specific field
1054
+ */
1055
+ function cmb_get_option( $option_key, $field_id = '' ) {
1056
+ return cmb_Meta_Box::get_option( $option_key, $field_id );
1057
+ }
1058
+
1059
+ /**
1060
+ * Get a CMB field object.
1061
+ * @since 1.1.0
1062
+ * @param array $field_args Field arguments
1063
+ * @param int $object_id Object ID
1064
+ * @param string $object_type Type of object being saved. (e.g., post, user, or comment)
1065
+ * @return object cmb_Meta_Box_field object
1066
+ */
1067
+ function cmb_get_field( $field_args, $object_id = 0, $object_type = 'post' ) {
1068
+ // Default to the loop post ID
1069
+ $object_id = $object_id ? $object_id : get_the_ID();
1070
+ cmb_Meta_Box::set_object_id( $object_id );
1071
+ cmb_Meta_Box::set_object_type( $object_type );
1072
+ // Send back field object
1073
+ return new cmb_Meta_Box_field( $field_args );
1074
+ }
1075
+
1076
+ /**
1077
+ * Get a field's value.
1078
+ * @since 1.1.0
1079
+ * @param array $field_args Field arguments
1080
+ * @param int $object_id Object ID
1081
+ * @param string $object_type Type of object being saved. (e.g., post, user, comment, or options-page)
1082
+ * @return mixed Maybe escaped value
1083
+ */
1084
+ function cmb_get_field_value( $field_args, $object_id = 0, $object_type = 'post' ) {
1085
+ $field = cmb_get_field( $field_args, $object_id, $object_type );
1086
+ return $field->escaped_value();
1087
+ }
1088
+
1089
+ /**
1090
+ * Loop and output multiple metaboxes
1091
+ * @since 1.0.0
1092
+ * @param array $meta_boxes Metaboxes config array
1093
+ * @param int $object_id Object ID
1094
+ */
1095
+ function cmb_print_metaboxes( $meta_boxes, $object_id ) {
1096
+ foreach ( (array) $meta_boxes as $meta_box ) {
1097
+ cmb_print_metabox( $meta_box, $object_id );
1098
+ }
1099
+ }
1100
+
1101
+ /**
1102
+ * Output a metabox
1103
+ * @since 1.0.0
1104
+ * @param array $meta_box Metabox config array
1105
+ * @param int $object_id Object ID
1106
+ */
1107
+ function cmb_print_metabox( $meta_box, $object_id ) {
1108
+ $cmb = new cmb_Meta_Box( $meta_box );
1109
+ if ( $cmb ) {
1110
+
1111
+ cmb_Meta_Box::set_object_id( $object_id );
1112
+
1113
+ if ( ! wp_script_is( 'cmb-scripts', 'registered' ) )
1114
+ $cmb->register_scripts();
1115
+
1116
+ wp_enqueue_script( 'cmb-scripts' );
1117
+
1118
+ // default is to show cmb styles
1119
+ if ( $meta_box['cmb_styles'] != false )
1120
+ wp_enqueue_style( 'cmb-styles' );
1121
+
1122
+ cmb_Meta_Box::show_form( $meta_box );
1123
+ }
1124
+
1125
+ }
1126
+
1127
+ /**
1128
+ * Saves a particular metabox's fields
1129
+ * @since 1.0.0
1130
+ * @param array $meta_box Metabox config array
1131
+ * @param int $object_id Object ID
1132
+ */
1133
+ function cmb_save_metabox_fields( $meta_box, $object_id ) {
1134
+ cmb_Meta_Box::save_fields( $meta_box, $object_id );
1135
+ }
1136
+
1137
+ /**
1138
+ * Display a metabox form & save it on submission
1139
+ * @since 1.0.0
1140
+ * @param array $meta_box Metabox config array
1141
+ * @param int $object_id Object ID
1142
+ * @param boolean $return Whether to return or echo form
1143
+ * @return string CMB html form markup
1144
+ */
1145
+ function cmb_metabox_form( $meta_box, $object_id, $echo = true ) {
1146
+
1147
+ $meta_box = cmb_Meta_Box::set_mb_defaults( $meta_box );
1148
+
1149
+ // Make sure form should be shown
1150
+ if ( ! apply_filters( 'cmb_show_on', true, $meta_box ) )
1151
+ return '';
1152
+
1153
+ // Make sure that our object type is explicitly set by the metabox config
1154
+ cmb_Meta_Box::set_object_type( cmb_Meta_Box::set_mb_type( $meta_box ) );
1155
+
1156
+ // Save the metabox if it's been submitted
1157
+ // check permissions
1158
+ // @todo more hardening?
1159
+ if (
1160
+ // check nonce
1161
+ isset( $_POST['submit-cmb'], $_POST['object_id'], $_POST['wp_meta_box_nonce'] )
1162
+ && wp_verify_nonce( $_POST['wp_meta_box_nonce'], cmb_Meta_Box::nonce() )
1163
+ && $_POST['object_id'] == $object_id
1164
+ )
1165
+ cmb_save_metabox_fields( $meta_box, $object_id );
1166
+
1167
+ // Show specific metabox form
1168
+
1169
+ // Get cmb form
1170
+ ob_start();
1171
+ cmb_print_metabox( $meta_box, $object_id );
1172
+ $form = ob_get_contents();
1173
+ ob_end_clean();
1174
+
1175
+ $form_format = apply_filters( 'cmb_frontend_form_format', '<form class="cmb-form" method="post" id="%s" enctype="multipart/form-data" encoding="multipart/form-data"><input type="hidden" name="object_id" value="%s">%s<input type="submit" name="submit-cmb" value="%s" class="button-primary"></form>', $object_id, $meta_box, $form );
1176
+
1177
+ $form = sprintf( $form_format, $meta_box['id'], $object_id, $form, __( 'Save' ) );
1178
+
1179
+ if ( $echo )
1180
+ echo $form;
1181
+
1182
+ return $form;
1183
+ }
1184
+
1185
+ // End. That's it, folks! //
lib/cmb_metaboxes/js/cmb.js ADDED
@@ -0,0 +1,797 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Controls the behaviours of custom metabox fields.
3
+ *
4
+ * @author Andrew Norcross
5
+ * @author Jared Atchison
6
+ * @author Bill Erickson
7
+ * @author Justin Sternberg
8
+ * @see https://github.com/webdevstudios/Custom-Metaboxes-and-Fields-for-WordPress
9
+ */
10
+
11
+ /**
12
+ * Custom jQuery for Custom Metaboxes and Fields
13
+ */
14
+ window.CMB = (function(window, document, $, undefined){
15
+ 'use strict';
16
+
17
+ // localization strings
18
+ var l10n = window.cmb_l10;
19
+ var setTimeout = window.setTimeout;
20
+
21
+ // CMB functionality object
22
+ var cmb = {
23
+ formfield : '',
24
+ idNumber : false,
25
+ file_frames : {},
26
+ repeatEls : 'input:not([type="button"]),select,textarea,.cmb_media_status'
27
+ };
28
+
29
+ cmb.metabox = function() {
30
+ if ( cmb.$metabox ) {
31
+ return cmb.$metabox;
32
+ }
33
+ cmb.$metabox = $('table.cmb_metabox');
34
+ return cmb.$metabox;
35
+ };
36
+
37
+ cmb.init = function() {
38
+
39
+ var $metabox = cmb.metabox();
40
+ var $repeatGroup = $metabox.find('.repeatable-group');
41
+
42
+ // hide our spinner gif if we're on a MP6 dashboard
43
+ if ( l10n.new_admin_style ) {
44
+ $metabox.find('.cmb-spinner img').hide();
45
+ }
46
+
47
+ /**
48
+ * Initialize time/date/color pickers
49
+ */
50
+ cmb.initPickers( $metabox.find('input:text.cmb_timepicker'), $metabox.find('input:text.cmb_datepicker'), $metabox.find('input:text.cmb_colorpicker') );
51
+
52
+ // Wrap date picker in class to narrow the scope of jQuery UI CSS and prevent conflicts
53
+ $("#ui-datepicker-div").wrap('<div class="cmb_element" />');
54
+
55
+ // Insert toggle button into DOM wherever there is multicheck. credit: Genesis Framework
56
+ $( '<p><span class="button cmb-multicheck-toggle">' + l10n.check_toggle + '</span></p>' ).insertBefore( 'ul.cmb_checkbox_list' );
57
+
58
+ $metabox
59
+ .on( 'change', '.cmb_upload_file', function() {
60
+ cmb.formfield = $(this).attr('id');
61
+ $('#' + cmb.formfield + '_id').val('');
62
+ })
63
+ // Media/file management
64
+ .on( 'click', '.cmb-multicheck-toggle', cmb.toggleCheckBoxes )
65
+ .on( 'click', '.cmb_upload_button', cmb.handleMedia )
66
+ .on( 'click', '.cmb_remove_file_button', cmb.handleRemoveMedia )
67
+ // Repeatable content
68
+ .on( 'click', '.add-group-row', cmb.addGroupRow )
69
+ .on( 'click', '.add-row-button', cmb.addAjaxRow )
70
+ .on( 'click', '.remove-group-row', cmb.removeGroupRow )
71
+ .on( 'click', '.remove-row-button', cmb.removeAjaxRow )
72
+ // Ajax oEmbed display
73
+ .on( 'keyup paste focusout', '.cmb_oembed', cmb.maybeOembed )
74
+ // Reset titles when removing a row
75
+ .on( 'cmb_remove_row', '.repeatable-group', cmb.resetTitlesAndIterator );
76
+
77
+ if ( $repeatGroup.length ) {
78
+ $repeatGroup
79
+ .filter('.sortable').each( function() {
80
+ // Add sorting arrows
81
+ $(this).find( '.remove-group-row' ).before( '<a class="shift-rows move-up alignleft" href="#">'+ l10n.up_arrow +'</a> <a class="shift-rows move-down alignleft" href="#">'+ l10n.down_arrow +'</a>' );
82
+ })
83
+ .on( 'click', '.shift-rows', cmb.shiftRows )
84
+ .on( 'cmb_add_row', cmb.emptyValue );
85
+ }
86
+
87
+ // on pageload
88
+ setTimeout( cmb.resizeoEmbeds, 500);
89
+ // and on window resize
90
+ $(window).on( 'resize', cmb.resizeoEmbeds );
91
+
92
+ };
93
+
94
+ cmb.resetTitlesAndIterator = function() {
95
+ // Loop repeatable group tables
96
+ $( '.repeatable-group' ).each( function() {
97
+ var $table = $(this);
98
+ // Loop repeatable group table rows
99
+ $table.find( '.repeatable-grouping' ).each( function( rowindex ) {
100
+ var $row = $(this);
101
+ // Reset rows iterator
102
+ $row.data( 'iterator', rowindex );
103
+ // Reset rows title
104
+ $row.find( '.cmb-group-title h4' ).text( $table.find( '.add-group-row' ).data( 'grouptitle' ).replace( '{#}', ( rowindex + 1 ) ) );
105
+ });
106
+ });
107
+ };
108
+
109
+ cmb.toggleCheckBoxes = function( event ) {
110
+ event.preventDefault();
111
+ var $self = $(this);
112
+ var $multicheck = $self.parents( 'td' ).find( 'input[type=checkbox]' );
113
+
114
+ // If the button has already been clicked once...
115
+ if ( $self.data( 'checked' ) ) {
116
+ // clear the checkboxes and remove the flag
117
+ $multicheck.prop( 'checked', false );
118
+ $self.data( 'checked', false );
119
+ }
120
+ // Otherwise mark the checkboxes and add a flag
121
+ else {
122
+ $multicheck.prop( 'checked', true );
123
+ $self.data( 'checked', true );
124
+ }
125
+ };
126
+
127
+ cmb.handleMedia = function(event) {
128
+
129
+ if ( ! wp ) {
130
+ return;
131
+ }
132
+
133
+ event.preventDefault();
134
+
135
+ var $metabox = cmb.metabox();
136
+ var $self = $(this);
137
+ cmb.formfield = $self.prev('input').attr('id');
138
+ var $formfield = $('#'+cmb.formfield);
139
+ var formName = $formfield.attr('name');
140
+ var uploadStatus = true;
141
+ var attachment = true;
142
+ var isList = $self.hasClass( 'cmb_upload_list' );
143
+
144
+ // If this field's media frame already exists, reopen it.
145
+ if ( cmb.formfield in cmb.file_frames ) {
146
+ cmb.file_frames[cmb.formfield].open();
147
+ return;
148
+ }
149
+
150
+ // Create the media frame.
151
+ cmb.file_frames[cmb.formfield] = wp.media.frames.file_frame = wp.media({
152
+ title: $metabox.find('label[for=' + cmb.formfield + ']').text(),
153
+ button: {
154
+ text: l10n.upload_file
155
+ },
156
+ multiple: isList ? true : false
157
+ });
158
+
159
+ var handlers = {
160
+ list : function( selection ) {
161
+ // Get all of our selected files
162
+ attachment = selection.toJSON();
163
+
164
+ $formfield.val(attachment.url);
165
+ $('#'+ cmb.formfield +'_id').val(attachment.id);
166
+
167
+ // Setup our fileGroup array
168
+ var fileGroup = [];
169
+
170
+ // Loop through each attachment
171
+ $( attachment ).each( function() {
172
+ if ( this.type && this.type === 'image' ) {
173
+ // image preview
174
+ uploadStatus = '<li class="img_status">'+
175
+ '<img width="50" height="50" src="' + this.url + '" class="attachment-50x50" alt="'+ this.filename +'">'+
176
+ '<p><a href="#" class="cmb_remove_file_button" rel="'+ cmb.formfield +'['+ this.id +']">'+ l10n.remove_image +'</a></p>'+
177
+ '<input type="hidden" id="filelist-'+ this.id +'" name="'+ formName +'['+ this.id +']" value="' + this.url + '">'+
178
+ '</li>';
179
+
180
+ } else {
181
+ // Standard generic output if it's not an image.
182
+ uploadStatus = '<li>'+ l10n.file +' <strong>'+ this.filename +'</strong>&nbsp;&nbsp;&nbsp; (<a href="' + this.url + '" target="_blank" rel="external">'+ l10n.download +'</a> / <a href="#" class="cmb_remove_file_button" rel="'+ cmb.formfield +'['+ this.id +']">'+ l10n.remove_file +'</a>)'+
183
+ '<input type="hidden" id="filelist-'+ this.id +'" name="'+ formName +'['+ this.id +']" value="' + this.url + '">'+
184
+ '</li>';
185
+
186
+ }
187
+
188
+ // Add our file to our fileGroup array
189
+ fileGroup.push( uploadStatus );
190
+ });
191
+
192
+ // Append each item from our fileGroup array to .cmb_media_status
193
+ $( fileGroup ).each( function() {
194
+ $formfield.siblings('.cmb_media_status').slideDown().append(this);
195
+ });
196
+ },
197
+ single : function( selection ) {
198
+ // Only get one file from the uploader
199
+ attachment = selection.first().toJSON();
200
+
201
+ $formfield.val(attachment.url);
202
+ $('#'+ cmb.formfield +'_id').val(attachment.id);
203
+
204
+ if ( attachment.type && attachment.type === 'image' ) {
205
+ // image preview
206
+ uploadStatus = '<div class="img_status"><img style="max-width: 350px; width: 100%; height: auto;" src="' + attachment.url + '" alt="'+ attachment.filename +'" title="'+ attachment.filename +'" /><p><a href="#" class="cmb_remove_file_button" rel="' + cmb.formfield + '">'+ l10n.remove_image +'</a></p></div>';
207
+ } else {
208
+ // Standard generic output if it's not an image.
209
+ uploadStatus = l10n.file +' <strong>'+ attachment.filename +'</strong>&nbsp;&nbsp;&nbsp; (<a href="'+ attachment.url +'" target="_blank" rel="external">'+ l10n.download +'</a> / <a href="#" class="cmb_remove_file_button" rel="'+ cmb.formfield +'">'+ l10n.remove_file +'</a>)';
210
+ }
211
+
212
+ // add/display our output
213
+ $formfield.siblings('.cmb_media_status').slideDown().html(uploadStatus);
214
+ }
215
+ };
216
+
217
+ // When an file is selected, run a callback.
218
+ cmb.file_frames[cmb.formfield].on( 'select', function() {
219
+ var selection = cmb.file_frames[cmb.formfield].state().get('selection');
220
+ var type = isList ? 'list' : 'single';
221
+ handlers[type]( selection );
222
+ });
223
+
224
+ // Finally, open the modal
225
+ cmb.file_frames[cmb.formfield].open();
226
+ };
227
+
228
+ cmb.handleRemoveMedia = function( event ) {
229
+ event.preventDefault();
230
+ var $self = $(this);
231
+ if ( $self.is( '.attach_list .cmb_remove_file_button' ) ){
232
+ $self.parents('li').remove();
233
+ return false;
234
+ }
235
+ cmb.formfield = $self.attr('rel');
236
+ var $container = $self.parents('.img_status');
237
+
238
+ cmb.metabox().find('input#' + cmb.formfield).val('');
239
+ cmb.metabox().find('input#' + cmb.formfield + '_id').val('');
240
+ if ( ! $container.length ) {
241
+ $self.parents('.cmb_media_status').html('');
242
+ } else {
243
+ $container.html('');
244
+ }
245
+ return false;
246
+ };
247
+
248
+ // src: http://www.benalman.com/projects/jquery-replacetext-plugin/
249
+ $.fn.replaceText = function(b, a, c) {
250
+ return this.each(function() {
251
+ var f = this.firstChild, g, e, d = [];
252
+ if (f) {
253
+ do {
254
+ if (f.nodeType === 3) {
255
+ g = f.nodeValue;
256
+ e = g.replace(b, a);
257
+ if (e !== g) {
258
+ if (!c && /</.test(e)) {
259
+ $(f).before(e);
260
+ d.push(f);
261
+ } else {
262
+ f.nodeValue = e;
263
+ }
264
+ }
265
+ }
266
+ } while (f = f.nextSibling);
267
+ }
268
+ if ( d.length ) { $(d).remove(); }
269
+ });
270
+ };
271
+
272
+ $.fn.cleanRow = function( prevNum, group ) {
273
+ var $self = $(this);
274
+ var $inputs = $self.find('input:not([type="button"]), select, textarea, label');
275
+ if ( group ) {
276
+ // Remove extra ajaxed rows
277
+ $self.find('.cmb-repeat-table .repeat-row:not(:first-child)').remove();
278
+ }
279
+ cmb.$focus = false;
280
+ cmb.neweditor_id = [];
281
+
282
+ $inputs.filter(':checked').removeAttr( 'checked' );
283
+ $inputs.filter(':selected').removeAttr( 'selected' );
284
+
285
+ if ( $self.find('.cmb-group-title') ) {
286
+ $self.find( '.cmb-group-title h4' ).text( $self.data( 'title' ).replace( '{#}', ( cmb.idNumber + 1 ) ) );
287
+ }
288
+
289
+ $inputs.each( function(){
290
+ var $newInput = $(this);
291
+ var isEditor = $newInput.hasClass( 'wp-editor-area' );
292
+ var oldFor = $newInput.attr( 'for' );
293
+ // var $next = $newInput.next();
294
+ var attrs = {};
295
+ var newID, oldID;
296
+ if ( oldFor ) {
297
+ attrs = { 'for' : oldFor.replace( '_'+ prevNum, '_'+ cmb.idNumber ) };
298
+ } else {
299
+ var oldName = $newInput.attr( 'name' );
300
+ // Replace 'name' attribute key
301
+ var newName = oldName ? oldName.replace( '['+ prevNum +']', '['+ cmb.idNumber +']' ) : '';
302
+ oldID = $newInput.attr( 'id' );
303
+ newID = oldID ? oldID.replace( '_'+ prevNum, '_'+ cmb.idNumber ) : '';
304
+ attrs = {
305
+ id: newID,
306
+ name: newName,
307
+ // value: '',
308
+ 'data-iterator': cmb.idNumber,
309
+ };
310
+ }
311
+
312
+ $newInput
313
+ .removeClass( 'hasDatepicker' )
314
+ .attr( attrs ).val('');
315
+
316
+ // wysiwyg field
317
+ if ( isEditor ) {
318
+ // Get new wysiwyg ID
319
+ newID = newID ? oldID.replace( 'zx'+ prevNum, 'zx'+ cmb.idNumber ) : '';
320
+ // Empty the contents
321
+ $newInput.html('');
322
+ // Get wysiwyg field
323
+ var $wysiwyg = $newInput.parents( '.cmb-type-wysiwyg' );
324
+ // Remove extra mce divs
325
+ $wysiwyg.find('.mce-tinymce:not(:first-child)').remove();
326
+ // Replace id instances
327
+ var html = $wysiwyg.html().replace( new RegExp( oldID, 'g' ), newID );
328
+ // Update field html
329
+ $wysiwyg.html( html );
330
+ // Save ids for later to re-init tinymce
331
+ cmb.neweditor_id.push( { 'id': newID, 'old': oldID } );
332
+ }
333
+
334
+ cmb.$focus = cmb.$focus ? cmb.$focus : $newInput;
335
+ });
336
+
337
+ return this;
338
+ };
339
+
340
+ $.fn.newRowHousekeeping = function() {
341
+ var $row = $(this);
342
+ var $colorPicker = $row.find( '.wp-picker-container' );
343
+ var $list = $row.find( '.cmb_media_status' );
344
+
345
+ if ( $colorPicker.length ) {
346
+ // Need to clean-up colorpicker before appending
347
+ $colorPicker.each( function() {
348
+ var $td = $(this).parent();
349
+ $td.html( $td.find( 'input:text.cmb_colorpicker' ).attr('style', '') );
350
+ });
351
+ }
352
+
353
+ // Need to clean-up colorpicker before appending
354
+ if ( $list.length ) {
355
+ $list.empty();
356
+ }
357
+
358
+ return this;
359
+ };
360
+
361
+ cmb.afterRowInsert = function( $row ) {
362
+ if ( cmb.$focus ) {
363
+ cmb.$focus.focus();
364
+ }
365
+
366
+ var _prop;
367
+
368
+ // Need to re-init wp_editor instances
369
+ if ( cmb.neweditor_id.length ) {
370
+ var i;
371
+ for ( i = cmb.neweditor_id.length - 1; i >= 0; i-- ) {
372
+ var id = cmb.neweditor_id[i].id;
373
+ var old = cmb.neweditor_id[i].old;
374
+
375
+ if ( typeof( tinyMCEPreInit.mceInit[ id ] ) === 'undefined' ) {
376
+ var newSettings = jQuery.extend( {}, tinyMCEPreInit.mceInit[ old ] );
377
+
378
+ for ( _prop in newSettings ) {
379
+ if ( 'string' === typeof( newSettings[_prop] ) ) {
380
+ newSettings[_prop] = newSettings[_prop].replace( new RegExp( old, 'g' ), id );
381
+ }
382
+ }
383
+ tinyMCEPreInit.mceInit[ id ] = newSettings;
384
+ }
385
+ if ( typeof( tinyMCEPreInit.qtInit[ id ] ) === 'undefined' ) {
386
+ var newQTS = jQuery.extend( {}, tinyMCEPreInit.qtInit[ old ] );
387
+ for ( _prop in newQTS ) {
388
+ if ( 'string' === typeof( newQTS[_prop] ) ) {
389
+ newQTS[_prop] = newQTS[_prop].replace( new RegExp( old, 'g' ), id );
390
+ }
391
+ }
392
+ tinyMCEPreInit.qtInit[ id ] = newQTS;
393
+ }
394
+ tinyMCE.init({
395
+ id : tinyMCEPreInit.mceInit[ id ],
396
+ });
397
+
398
+ }
399
+ }
400
+
401
+ // Init pickers from new row
402
+ cmb.initPickers( $row.find('input:text.cmb_timepicker'), $row.find('input:text.cmb_datepicker'), $row.find('input:text.cmb_colorpicker') );
403
+ };
404
+
405
+ cmb.updateNameAttr = function () {
406
+
407
+ var $this = $(this);
408
+ var name = $this.attr( 'name' ); // get current name
409
+
410
+ // No name? bail
411
+ if ( typeof name === 'undefined' ) {
412
+ return false;
413
+ }
414
+
415
+ var prevNum = parseInt( $this.parents( '.repeatable-grouping' ).data( 'iterator' ) );
416
+ var newNum = prevNum - 1; // Subtract 1 to get new iterator number
417
+
418
+ // Update field name attributes so data is not orphaned when a row is removed and post is saved
419
+ var $newName = name.replace( '[' + prevNum + ']', '[' + newNum + ']' );
420
+
421
+ // New name with replaced iterator
422
+ $this.attr( 'name', $newName );
423
+
424
+ };
425
+
426
+ cmb.emptyValue = function( event, row ) {
427
+ $('input:not([type="button"]), textarea', row).val('');
428
+ };
429
+
430
+ cmb.addGroupRow = function( event ) {
431
+
432
+ event.preventDefault();
433
+
434
+ var $self = $(this);
435
+ var $table = $('#'+ $self.data('selector'));
436
+ var $oldRow = $table.find('.repeatable-grouping').last();
437
+ var prevNum = parseInt( $oldRow.data('iterator') );
438
+ cmb.idNumber = prevNum + 1;
439
+ var $row = $oldRow.clone();
440
+
441
+ $row.data( 'title', $self.data( 'grouptitle' ) ).newRowHousekeeping().cleanRow( prevNum, true );
442
+
443
+ // console.log( '$row.html()', $row.html() );
444
+ var $newRow = $( '<tr class="repeatable-grouping" data-iterator="'+ cmb.idNumber +'">'+ $row.html() +'</tr>' );
445
+ $oldRow.after( $newRow );
446
+ // console.log( '$newRow.html()', $row.html() );
447
+
448
+ cmb.afterRowInsert( $newRow );
449
+
450
+ if ( $table.find('.repeatable-grouping').length <= 1 ) {
451
+ $table.find('.remove-group-row').prop('disabled', true);
452
+ } else {
453
+ $table.find('.remove-group-row').removeAttr( 'disabled' );
454
+ }
455
+
456
+ $table.trigger( 'cmb_add_row', $newRow );
457
+ };
458
+
459
+ cmb.addAjaxRow = function( event ) {
460
+
461
+ event.preventDefault();
462
+
463
+ var $self = $(this);
464
+ var tableselector = '#'+ $self.data('selector');
465
+ var $table = $(tableselector);
466
+ var $emptyrow = $table.find('.empty-row');
467
+ var prevNum = parseInt( $emptyrow.find('[data-iterator]').data('iterator') );
468
+ cmb.idNumber = prevNum + 1;
469
+ var $row = $emptyrow.clone();
470
+
471
+ $row.newRowHousekeeping().cleanRow( prevNum );
472
+
473
+ $emptyrow.removeClass('empty-row').addClass('repeat-row');
474
+ $emptyrow.after( $row );
475
+
476
+ cmb.afterRowInsert( $row );
477
+ $table.trigger( 'cmb_add_row', $row );
478
+ };
479
+
480
+ cmb.removeGroupRow = function( event ) {
481
+ event.preventDefault();
482
+ var $self = $(this);
483
+ var $table = $('#'+ $self.data('selector'));
484
+ var $parent = $self.parents('.repeatable-grouping');
485
+ var noRows = $table.find('.repeatable-grouping').length;
486
+
487
+ // when a group is removed loop through all next groups and update fields names
488
+ $parent.nextAll( '.repeatable-grouping' ).find( cmb.repeatEls ).each( cmb.updateNameAttr );
489
+
490
+ if ( noRows > 1 ) {
491
+ $parent.remove();
492
+ if ( noRows < 3 ) {
493
+ $table.find('.remove-group-row').prop('disabled', true);
494
+ } else {
495
+ $table.find('.remove-group-row').prop('disabled', false);
496
+ }
497
+ $table.trigger( 'cmb_remove_row' );
498
+ }
499
+ };
500
+
501
+ cmb.removeAjaxRow = function( event ) {
502
+ event.preventDefault();
503
+ var $self = $(this);
504
+ var $parent = $self.parents('tr');
505
+ var $table = $self.parents('.cmb-repeat-table');
506
+
507
+ // cmb.log( 'number of tbodys', $table.length );
508
+ // cmb.log( 'number of trs', $('tr', $table).length );
509
+ if ( $table.find('tr').length > 1 ) {
510
+ if ( $parent.hasClass('empty-row') ) {
511
+ $parent.prev().addClass( 'empty-row' ).removeClass('repeat-row');
512
+ }
513
+ $self.parents('.cmb-repeat-table tr').remove();
514
+ $table.trigger( 'cmb_remove_row' );
515
+ }
516
+ };
517
+
518
+ cmb.shiftRows = function( event ) {
519
+
520
+ event.preventDefault();
521
+
522
+ var $self = $(this);
523
+ var $parent = $self.parents( '.repeatable-grouping' );
524
+ var $goto = $self.hasClass( 'move-up' ) ? $parent.prev( '.repeatable-grouping' ) : $parent.next( '.repeatable-grouping' );
525
+
526
+ if ( ! $goto.length ) {
527
+ return;
528
+ }
529
+
530
+ var inputVals = [];
531
+ // Loop this items fields
532
+ $parent.find( cmb.repeatEls ).each( function() {
533
+ var $element = $(this);
534
+ var val;
535
+ if ( $element.hasClass('cmb_media_status') ) {
536
+ // special case for image previews
537
+ val = $element.html();
538
+ } else if ( 'checkbox' === $element.attr('type') ) {
539
+ val = $element.is(':checked');
540
+ cmb.log( 'checked', val );
541
+ } else if ( 'select' === $element.prop('tagName') ) {
542
+ val = $element.is(':selected');
543
+ cmb.log( 'checked', val );
544
+ } else {
545
+ val = $element.val();
546
+ }
547
+ // Get all the current values per element
548
+ inputVals.push( { val: val, $: $element } );
549
+ });
550
+ // And swap them all
551
+ $goto.find( cmb.repeatEls ).each( function( index ) {
552
+ var $element = $(this);
553
+ var val;
554
+
555
+ if ( $element.hasClass('cmb_media_status') ) {
556
+ // special case for image previews
557
+ val = $element.html();
558
+ $element.html( inputVals[ index ]['val'] );
559
+ inputVals[ index ]['$'].html( val );
560
+
561
+ }
562
+ // handle checkbox swapping
563
+ else if ( 'checkbox' === $element.attr('type') ) {
564
+ inputVals[ index ]['$'].prop( 'checked', $element.is(':checked') );
565
+ $element.prop( 'checked', inputVals[ index ]['val'] );
566
+ }
567
+ // handle select swapping
568
+ else if ( 'select' === $element.prop('tagName') ) {
569
+ inputVals[ index ]['$'].prop( 'selected', $element.is(':selected') );
570
+ $element.prop( 'selected', inputVals[ index ]['val'] );
571
+ }
572
+ // handle normal input swapping
573
+ else {
574
+ inputVals[ index ]['$'].val( $element.val() );
575
+ $element.val( inputVals[ index ]['val'] );
576
+ }
577
+ });
578
+ };
579
+
580
+ /**
581
+ * @todo make work, always
582
+ */
583
+ cmb.initPickers = function( $timePickers, $datePickers, $colorPickers ) {
584
+ // Initialize timepicker
585
+ cmb.initTimePickers( $timePickers );
586
+
587
+ // Initialize jQuery UI datepicker
588
+ cmb.initDatePickers( $datePickers );
589
+
590
+ // Initialize color picker
591
+ cmb.initColorPickers( $colorPickers );
592
+ };
593
+
594
+ cmb.initTimePickers = function( $selector ) {
595
+ if ( ! $selector.length ) {
596
+ return;
597
+ }
598
+
599
+ $selector.timePicker({
600
+ startTime: "00:00",
601
+ endTime: "23:59",
602
+ show24Hours: false,
603
+ separator: ':',
604
+ step: 30
605
+ });
606
+ };
607
+
608
+ cmb.initDatePickers = function( $selector ) {
609
+ if ( ! $selector.length ) {
610
+ return;
611
+ }
612
+
613
+ $selector.datepicker( "destroy" );
614
+ $selector.datepicker();
615
+ };
616
+
617
+ cmb.initColorPickers = function( $selector ) {
618
+ if ( ! $selector.length ) {
619
+ return;
620
+ }
621
+ if (typeof jQuery.wp === 'object' && typeof jQuery.wp.wpColorPicker === 'function') {
622
+
623
+ $selector.wpColorPicker();
624
+
625
+ } else {
626
+ $selector.each( function(i) {
627
+ $(this).after('<div id="picker-' + i + '" style="z-index: 1000; background: #EEE; border: 1px solid #CCC; position: absolute; display: block;"></div>');
628
+ $('#picker-' + i).hide().farbtastic($(this));
629
+ })
630
+ .focus( function() {
631
+ $(this).next().show();
632
+ })
633
+ .blur( function() {
634
+ $(this).next().hide();
635
+ });
636
+ }
637
+ };
638
+
639
+ cmb.maybeOembed = function( evt ) {
640
+ var $self = $(this);
641
+ var type = evt.type;
642
+
643
+ var m = {
644
+ focusout : function() {
645
+ setTimeout( function() {
646
+ // if it's been 2 seconds, hide our spinner
647
+ cmb.spinner( '.postbox table.cmb_metabox', true );
648
+ }, 2000);
649
+ },
650
+ keyup : function() {
651
+ var betw = function( min, max ) {
652
+ return ( evt.which <= max && evt.which >= min );
653
+ };
654
+ // Only Ajax on normal keystrokes
655
+ if ( betw( 48, 90 ) || betw( 96, 111 ) || betw( 8, 9 ) || evt.which === 187 || evt.which === 190 ) {
656
+ // fire our ajax function
657
+ cmb.doAjax( $self, evt);
658
+ }
659
+ },
660
+ paste : function() {
661
+ // paste event is fired before the value is filled, so wait a bit
662
+ setTimeout( function() { cmb.doAjax( $self ); }, 100);
663
+ }
664
+ };
665
+ m[type]();
666
+
667
+ };
668
+
669
+ /**
670
+ * Resize oEmbed videos to fit in their respective metaboxes
671
+ */
672
+ cmb.resizeoEmbeds = function() {
673
+ cmb.metabox().each( function() {
674
+ var $self = $(this);
675
+ var $tableWrap = $self.parents('.inside');
676
+ if ( ! $tableWrap.length ) {
677
+ return true; // continue
678
+ }
679
+
680
+ // Calculate new width
681
+ var newWidth = Math.round(($tableWrap.width() * 0.82)*0.97) - 30;
682
+ if ( newWidth > 639 ) {
683
+ return true; // continue
684
+ }
685
+
686
+ var $embeds = $self.find('.cmb-type-oembed .embed_status');
687
+ var $children = $embeds.children().not('.cmb_remove_wrapper');
688
+ if ( ! $children.length ) {
689
+ return true; // continue
690
+ }
691
+
692
+ $children.each( function() {
693
+ var $self = $(this);
694
+ var iwidth = $self.width();
695
+ var iheight = $self.height();
696
+ var _newWidth = newWidth;
697
+ if ( $self.parents( '.repeat-row' ).length ) {
698
+ // Make room for our repeatable "remove" button column
699
+ _newWidth = newWidth - 91;
700
+ }
701
+ // Calc new height
702
+ var newHeight = Math.round((_newWidth * iheight)/iwidth);
703
+ $self.width(_newWidth).height(newHeight);
704
+ });
705
+
706
+ });
707
+ };
708
+
709
+ /**
710
+ * Safely log things if query var is set
711
+ * @since 1.0.0
712
+ */
713
+ cmb.log = function() {
714
+ if ( l10n.script_debug && console && typeof console.log === 'function' ) {
715
+ console.log.apply(console, arguments);
716
+ }
717
+ };
718
+
719
+ cmb.spinner = function( $context, hide ) {
720
+ if ( hide ) {
721
+ $('.cmb-spinner', $context ).hide();
722
+ }
723
+ else {
724
+ $('.cmb-spinner', $context ).show();
725
+ }
726
+ };
727
+
728
+ // function for running our ajax
729
+ cmb.doAjax = function($obj) {
730
+ // get typed value
731
+ var oembed_url = $obj.val();
732
+ // only proceed if the field contains more than 6 characters
733
+ if ( oembed_url.length < 6 ) {
734
+ return;
735
+ }
736
+
737
+ // only proceed if the user has pasted, pressed a number, letter, or whitelisted characters
738
+
739
+ // get field id
740
+ var field_id = $obj.attr('id');
741
+ // get our inputs $context for pinpointing
742
+ var $context = $obj.parents('.cmb-repeat-table tr td');
743
+ $context = $context.length ? $context : $obj.parents('.cmb_metabox tr td');
744
+
745
+ var embed_container = $('.embed_status', $context);
746
+ var oembed_width = $obj.width();
747
+ var child_el = $(':first-child', embed_container);
748
+
749
+ // http://www.youtube.com/watch?v=dGG7aru2S6U
750
+ cmb.log( 'oembed_url', oembed_url, field_id );
751
+ oembed_width = ( embed_container.length && child_el.length ) ? child_el.width() : $obj.width();
752
+
753
+ // show our spinner
754
+ cmb.spinner( $context );
755
+ // clear out previous results
756
+ $('.embed_wrap', $context).html('');
757
+ // and run our ajax function
758
+ setTimeout( function() {
759
+ // if they haven't typed in 500 ms
760
+ if ( $('.cmb_oembed:focus').val() !== oembed_url ) {
761
+ return;
762
+ }
763
+ $.ajax({
764
+ type : 'post',
765
+ dataType : 'json',
766
+ url : l10n.ajaxurl,
767
+ data : {
768
+ 'action': 'cmb_oembed_handler',
769
+ 'oembed_url': oembed_url,
770
+ 'oembed_width': oembed_width > 300 ? oembed_width : 300,
771
+ 'field_id': field_id,
772
+ 'object_id': $obj.data('objectid'),
773
+ 'object_type': $obj.data('objecttype'),
774
+ 'cmb_ajax_nonce': l10n.ajax_nonce
775
+ },
776
+ success: function(response) {
777
+ cmb.log( response );
778
+ // Make sure we have a response id
779
+ if ( typeof response.id === 'undefined' ) {
780
+ return;
781
+ }
782
+
783
+ // hide our spinner
784
+ cmb.spinner( $context, true );
785
+ // and populate our results from ajax response
786
+ $('.embed_wrap', $context).html(response.result);
787
+ }
788
+ });
789
+
790
+ }, 500);
791
+ };
792
+
793
+ $(document).ready(cmb.init);
794
+
795
+ return cmb;
796
+
797
+ })(window, document, jQuery);
lib/cmb_metaboxes/js/cmb.min.js ADDED
@@ -0,0 +1 @@
 
1
+ window.CMB=function(window,document,$){"use strict";var l10n=window.cmb_l10,setTimeout=window.setTimeout,cmb={formfield:"",idNumber:!1,file_frames:{},repeatEls:'input:not([type="button"]),select,textarea,.cmb_media_status'};return cmb.metabox=function(){return cmb.$metabox?cmb.$metabox:(cmb.$metabox=$("table.cmb_metabox"),cmb.$metabox)},cmb.init=function(){var $metabox=cmb.metabox(),$repeatGroup=$metabox.find(".repeatable-group");l10n.new_admin_style&&$metabox.find(".cmb-spinner img").hide(),cmb.initPickers($metabox.find("input:text.cmb_timepicker"),$metabox.find("input:text.cmb_datepicker"),$metabox.find("input:text.cmb_colorpicker")),$("#ui-datepicker-div").wrap('<div class="cmb_element" />'),$('<p><span class="button cmb-multicheck-toggle">'+l10n.check_toggle+"</span></p>").insertBefore("ul.cmb_checkbox_list"),$metabox.on("change",".cmb_upload_file",function(){cmb.formfield=$(this).attr("id"),$("#"+cmb.formfield+"_id").val("")}).on("click",".cmb-multicheck-toggle",cmb.toggleCheckBoxes).on("click",".cmb_upload_button",cmb.handleMedia).on("click",".cmb_remove_file_button",cmb.handleRemoveMedia).on("click",".add-group-row",cmb.addGroupRow).on("click",".add-row-button",cmb.addAjaxRow).on("click",".remove-group-row",cmb.removeGroupRow).on("click",".remove-row-button",cmb.removeAjaxRow).on("keyup paste focusout",".cmb_oembed",cmb.maybeOembed).on("cmb_remove_row",".repeatable-group",cmb.resetTitlesAndIterator),$repeatGroup.length&&$repeatGroup.filter(".sortable").each(function(){$(this).find(".remove-group-row").before('<a class="shift-rows move-up alignleft" href="#">'+l10n.up_arrow+'</a> <a class="shift-rows move-down alignleft" href="#">'+l10n.down_arrow+"</a>")}).on("click",".shift-rows",cmb.shiftRows).on("cmb_add_row",cmb.emptyValue),setTimeout(cmb.resizeoEmbeds,500),$(window).on("resize",cmb.resizeoEmbeds)},cmb.resetTitlesAndIterator=function(){$(".repeatable-group").each(function(){var $table=$(this);$table.find(".repeatable-grouping").each(function(rowindex){var $row=$(this);$row.data("iterator",rowindex),$row.find(".cmb-group-title h4").text($table.find(".add-group-row").data("grouptitle").replace("{#}",rowindex+1))})})},cmb.toggleCheckBoxes=function(event){event.preventDefault();var $self=$(this),$multicheck=$self.parents("td").find("input[type=checkbox]");$self.data("checked")?($multicheck.prop("checked",!1),$self.data("checked",!1)):($multicheck.prop("checked",!0),$self.data("checked",!0))},cmb.handleMedia=function(event){if(wp){event.preventDefault();var $metabox=cmb.metabox(),$self=$(this);cmb.formfield=$self.prev("input").attr("id");var $formfield=$("#"+cmb.formfield),formName=$formfield.attr("name"),uploadStatus=!0,attachment=!0,isList=$self.hasClass("cmb_upload_list");if(cmb.formfield in cmb.file_frames)return void cmb.file_frames[cmb.formfield].open();cmb.file_frames[cmb.formfield]=wp.media.frames.file_frame=wp.media({title:$metabox.find("label[for="+cmb.formfield+"]").text(),button:{text:l10n.upload_file},multiple:isList?!0:!1});var handlers={list:function(selection){attachment=selection.toJSON(),$formfield.val(attachment.url),$("#"+cmb.formfield+"_id").val(attachment.id);var fileGroup=[];$(attachment).each(function(){uploadStatus=this.type&&"image"===this.type?'<li class="img_status"><img width="50" height="50" src="'+this.url+'" class="attachment-50x50" alt="'+this.filename+'"><p><a href="#" class="cmb_remove_file_button" rel="'+cmb.formfield+"["+this.id+']">'+l10n.remove_image+'</a></p><input type="hidden" id="filelist-'+this.id+'" name="'+formName+"["+this.id+']" value="'+this.url+'"></li>':"<li>"+l10n.file+" <strong>"+this.filename+'</strong>&nbsp;&nbsp;&nbsp; (<a href="'+this.url+'" target="_blank" rel="external">'+l10n.download+'</a> / <a href="#" class="cmb_remove_file_button" rel="'+cmb.formfield+"["+this.id+']">'+l10n.remove_file+'</a>)<input type="hidden" id="filelist-'+this.id+'" name="'+formName+"["+this.id+']" value="'+this.url+'"></li>',fileGroup.push(uploadStatus)}),$(fileGroup).each(function(){$formfield.siblings(".cmb_media_status").slideDown().append(this)})},single:function(selection){attachment=selection.first().toJSON(),$formfield.val(attachment.url),$("#"+cmb.formfield+"_id").val(attachment.id),uploadStatus=attachment.type&&"image"===attachment.type?'<div class="img_status"><img style="max-width: 350px; width: 100%; height: auto;" src="'+attachment.url+'" alt="'+attachment.filename+'" title="'+attachment.filename+'" /><p><a href="#" class="cmb_remove_file_button" rel="'+cmb.formfield+'">'+l10n.remove_image+"</a></p></div>":l10n.file+" <strong>"+attachment.filename+'</strong>&nbsp;&nbsp;&nbsp; (<a href="'+attachment.url+'" target="_blank" rel="external">'+l10n.download+'</a> / <a href="#" class="cmb_remove_file_button" rel="'+cmb.formfield+'">'+l10n.remove_file+"</a>)",$formfield.siblings(".cmb_media_status").slideDown().html(uploadStatus)}};cmb.file_frames[cmb.formfield].on("select",function(){var selection=cmb.file_frames[cmb.formfield].state().get("selection"),type=isList?"list":"single";handlers[type](selection)}),cmb.file_frames[cmb.formfield].open()}},cmb.handleRemoveMedia=function(event){event.preventDefault();var $self=$(this);if($self.is(".attach_list .cmb_remove_file_button"))return $self.parents("li").remove(),!1;cmb.formfield=$self.attr("rel");var $container=$self.parents(".img_status");return cmb.metabox().find("input#"+cmb.formfield).val(""),cmb.metabox().find("input#"+cmb.formfield+"_id").val(""),$container.length?$container.html(""):$self.parents(".cmb_media_status").html(""),!1},$.fn.replaceText=function(b,a,c){return this.each(function(){var g,e,f=this.firstChild,d=[];if(f)do 3===f.nodeType&&(g=f.nodeValue,e=g.replace(b,a),e!==g&&(!c&&/</.test(e)?($(f).before(e),d.push(f)):f.nodeValue=e));while(f=f.nextSibling);d.length&&$(d).remove()})},$.fn.cleanRow=function(prevNum,group){var $self=$(this),$inputs=$self.find('input:not([type="button"]), select, textarea, label');return group&&$self.find(".cmb-repeat-table .repeat-row:not(:first-child)").remove(),cmb.$focus=!1,cmb.neweditor_id=[],$inputs.filter(":checked").removeAttr("checked"),$inputs.filter(":selected").removeAttr("selected"),$self.find(".cmb-group-title")&&$self.find(".cmb-group-title h4").text($self.data("title").replace("{#}",cmb.idNumber+1)),$inputs.each(function(){var newID,oldID,$newInput=$(this),isEditor=$newInput.hasClass("wp-editor-area"),oldFor=$newInput.attr("for"),attrs={};if(oldFor)attrs={"for":oldFor.replace("_"+prevNum,"_"+cmb.idNumber)};else{var oldName=$newInput.attr("name"),newName=oldName?oldName.replace("["+prevNum+"]","["+cmb.idNumber+"]"):"";oldID=$newInput.attr("id"),newID=oldID?oldID.replace("_"+prevNum,"_"+cmb.idNumber):"",attrs={id:newID,name:newName,"data-iterator":cmb.idNumber}}if($newInput.removeClass("hasDatepicker").attr(attrs).val(""),isEditor){newID=newID?oldID.replace("zx"+prevNum,"zx"+cmb.idNumber):"",$newInput.html("");var $wysiwyg=$newInput.parents(".cmb-type-wysiwyg");$wysiwyg.find(".mce-tinymce:not(:first-child)").remove();var html=$wysiwyg.html().replace(new RegExp(oldID,"g"),newID);$wysiwyg.html(html),cmb.neweditor_id.push({id:newID,old:oldID})}cmb.$focus=cmb.$focus?cmb.$focus:$newInput}),this},$.fn.newRowHousekeeping=function(){var $row=$(this),$colorPicker=$row.find(".wp-picker-container"),$list=$row.find(".cmb_media_status");return $colorPicker.length&&$colorPicker.each(function(){var $td=$(this).parent();$td.html($td.find("input:text.cmb_colorpicker").attr("style",""))}),$list.length&&$list.empty(),this},cmb.afterRowInsert=function($row){cmb.$focus&&cmb.$focus.focus();var _prop;if(cmb.neweditor_id.length){var i;for(i=cmb.neweditor_id.length-1;i>=0;i--){var id=cmb.neweditor_id[i].id,old=cmb.neweditor_id[i].old;if("undefined"==typeof tinyMCEPreInit.mceInit[id]){var newSettings=jQuery.extend({},tinyMCEPreInit.mceInit[old]);for(_prop in newSettings)"string"==typeof newSettings[_prop]&&(newSettings[_prop]=newSettings[_prop].replace(new RegExp(old,"g"),id));tinyMCEPreInit.mceInit[id]=newSettings}if("undefined"==typeof tinyMCEPreInit.qtInit[id]){var newQTS=jQuery.extend({},tinyMCEPreInit.qtInit[old]);for(_prop in newQTS)"string"==typeof newQTS[_prop]&&(newQTS[_prop]=newQTS[_prop].replace(new RegExp(old,"g"),id));tinyMCEPreInit.qtInit[id]=newQTS}tinyMCE.init({id:tinyMCEPreInit.mceInit[id]})}}cmb.initPickers($row.find("input:text.cmb_timepicker"),$row.find("input:text.cmb_datepicker"),$row.find("input:text.cmb_colorpicker"))},cmb.updateNameAttr=function(){var $this=$(this),name=$this.attr("name");if("undefined"==typeof name)return!1;var prevNum=parseInt($this.parents(".repeatable-grouping").data("iterator")),newNum=prevNum-1,$newName=name.replace("["+prevNum+"]","["+newNum+"]");$this.attr("name",$newName)},cmb.emptyValue=function(event,row){$('input:not([type="button"]), textarea',row).val("")},cmb.addGroupRow=function(event){event.preventDefault();var $self=$(this),$table=$("#"+$self.data("selector")),$oldRow=$table.find(".repeatable-grouping").last(),prevNum=parseInt($oldRow.data("iterator"));cmb.idNumber=prevNum+1;var $row=$oldRow.clone();$row.data("title",$self.data("grouptitle")).newRowHousekeeping().cleanRow(prevNum,!0);var $newRow=$('<tr class="repeatable-grouping" data-iterator="'+cmb.idNumber+'">'+$row.html()+"</tr>");$oldRow.after($newRow),cmb.afterRowInsert($newRow),$table.find(".repeatable-grouping").length<=1?$table.find(".remove-group-row").prop("disabled",!0):$table.find(".remove-group-row").removeAttr("disabled"),$table.trigger("cmb_add_row",$newRow)},cmb.addAjaxRow=function(event){event.preventDefault();var $self=$(this),tableselector="#"+$self.data("selector"),$table=$(tableselector),$emptyrow=$table.find(".empty-row"),prevNum=parseInt($emptyrow.find("[data-iterator]").data("iterator"));cmb.idNumber=prevNum+1;var $row=$emptyrow.clone();$row.newRowHousekeeping().cleanRow(prevNum),$emptyrow.removeClass("empty-row").addClass("repeat-row"),$emptyrow.after($row),cmb.afterRowInsert($row),$table.trigger("cmb_add_row",$row)},cmb.removeGroupRow=function(event){event.preventDefault();var $self=$(this),$table=$("#"+$self.data("selector")),$parent=$self.parents(".repeatable-grouping"),noRows=$table.find(".repeatable-grouping").length;$parent.nextAll(".repeatable-grouping").find(cmb.repeatEls).each(cmb.updateNameAttr),noRows>1&&($parent.remove(),3>noRows?$table.find(".remove-group-row").prop("disabled",!0):$table.find(".remove-group-row").prop("disabled",!1),$table.trigger("cmb_remove_row"))},cmb.removeAjaxRow=function(event){event.preventDefault();var $self=$(this),$parent=$self.parents("tr"),$table=$self.parents(".cmb-repeat-table");$table.find("tr").length>1&&($parent.hasClass("empty-row")&&$parent.prev().addClass("empty-row").removeClass("repeat-row"),$self.parents(".cmb-repeat-table tr").remove(),$table.trigger("cmb_remove_row"))},cmb.shiftRows=function(event){event.preventDefault();var $self=$(this),$parent=$self.parents(".repeatable-grouping"),$goto=$self.hasClass("move-up")?$parent.prev(".repeatable-grouping"):$parent.next(".repeatable-grouping");if($goto.length){var inputVals=[];$parent.find(cmb.repeatEls).each(function(){var val,$element=$(this);$element.hasClass("cmb_media_status")?val=$element.html():"checkbox"===$element.attr("type")?(val=$element.is(":checked"),cmb.log("checked",val)):"select"===$element.prop("tagName")?(val=$element.is(":selected"),cmb.log("checked",val)):val=$element.val(),inputVals.push({val:val,$:$element})}),$goto.find(cmb.repeatEls).each(function(index){var val,$element=$(this);$element.hasClass("cmb_media_status")?(val=$element.html(),$element.html(inputVals[index].val),inputVals[index].$.html(val)):"checkbox"===$element.attr("type")?(inputVals[index].$.prop("checked",$element.is(":checked")),$element.prop("checked",inputVals[index].val)):"select"===$element.prop("tagName")?(inputVals[index].$.prop("selected",$element.is(":selected")),$element.prop("selected",inputVals[index].val)):(inputVals[index].$.val($element.val()),$element.val(inputVals[index].val))})}},cmb.initPickers=function($timePickers,$datePickers,$colorPickers){cmb.initTimePickers($timePickers),cmb.initDatePickers($datePickers),cmb.initColorPickers($colorPickers)},cmb.initTimePickers=function($selector){$selector.length&&$selector.timePicker({startTime:"00:00",endTime:"23:59",show24Hours:!1,separator:":",step:30})},cmb.initDatePickers=function($selector){$selector.length&&($selector.datepicker("destroy"),$selector.datepicker())},cmb.initColorPickers=function($selector){$selector.length&&("object"==typeof jQuery.wp&&"function"==typeof jQuery.wp.wpColorPicker?$selector.wpColorPicker():$selector.each(function(i){$(this).after('<div id="picker-'+i+'" style="z-index: 1000; background: #EEE; border: 1px solid #CCC; position: absolute; display: block;"></div>'),$("#picker-"+i).hide().farbtastic($(this))}).focus(function(){$(this).next().show()}).blur(function(){$(this).next().hide()}))},cmb.maybeOembed=function(evt){var $self=$(this),type=evt.type,m={focusout:function(){setTimeout(function(){cmb.spinner(".postbox table.cmb_metabox",!0)},2e3)},keyup:function(){var betw=function(min,max){return evt.which<=max&&evt.which>=min};(betw(48,90)||betw(96,111)||betw(8,9)||187===evt.which||190===evt.which)&&cmb.doAjax($self,evt)},paste:function(){setTimeout(function(){cmb.doAjax($self)},100)}};m[type]()},cmb.resizeoEmbeds=function(){cmb.metabox().each(function(){var $self=$(this),$tableWrap=$self.parents(".inside");if(!$tableWrap.length)return!0;var newWidth=Math.round(.82*$tableWrap.width()*.97)-30;if(newWidth>639)return!0;var $embeds=$self.find(".cmb-type-oembed .embed_status"),$children=$embeds.children().not(".cmb_remove_wrapper");return $children.length?void $children.each(function(){var $self=$(this),iwidth=$self.width(),iheight=$self.height(),_newWidth=newWidth;$self.parents(".repeat-row").length&&(_newWidth=newWidth-91);var newHeight=Math.round(_newWidth*iheight/iwidth);$self.width(_newWidth).height(newHeight)}):!0})},cmb.log=function(){l10n.script_debug&&console&&"function"==typeof console.log&&console.log.apply(console,arguments)},cmb.spinner=function($context,hide){hide?$(".cmb-spinner",$context).hide():$(".cmb-spinner",$context).show()},cmb.doAjax=function($obj){var oembed_url=$obj.val();if(!(oembed_url.length<6)){var field_id=$obj.attr("id"),$context=$obj.parents(".cmb-repeat-table tr td");$context=$context.length?$context:$obj.parents(".cmb_metabox tr td");var embed_container=$(".embed_status",$context),oembed_width=$obj.width(),child_el=$(":first-child",embed_container);cmb.log("oembed_url",oembed_url,field_id),oembed_width=embed_container.length&&child_el.length?child_el.width():$obj.width(),cmb.spinner($context),$(".embed_wrap",$context).html(""),setTimeout(function(){$(".cmb_oembed:focus").val()===oembed_url&&$.ajax({type:"post",dataType:"json",url:l10n.ajaxurl,data:{action:"cmb_oembed_handler",oembed_url:oembed_url,oembed_width:oembed_width>300?oembed_width:300,field_id:field_id,object_id:$obj.data("objectid"),object_type:$obj.data("objecttype"),cmb_ajax_nonce:l10n.ajax_nonce},success:function(response){cmb.log(response),"undefined"!=typeof response.id&&(cmb.spinner($context,!0),$(".embed_wrap",$context).html(response.result))}})},500)}},$(document).ready(cmb.init),cmb}(window,document,jQuery);
lib/cmb_metaboxes/js/jquery.datePicker.min.js ADDED
@@ -0,0 +1,2038 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * jQuery UI Datepicker 1.10.4
3
+ * http://jqueryui.com
4
+ *
5
+ * Copyright 2014 jQuery Foundation and other contributors
6
+ * Released under the MIT license.
7
+ * http://jquery.org/license
8
+ *
9
+ * http://api.jqueryui.com/datepicker/
10
+ *
11
+ * Depends:
12
+ * jquery.ui.core.js
13
+ */
14
+ (function( $, undefined ) {
15
+
16
+ $.extend($.ui, { datepicker: { version: "1.10.4" } });
17
+
18
+ var PROP_NAME = "datepicker",
19
+ instActive;
20
+
21
+ /* Date picker manager.
22
+ Use the singleton instance of this class, $.datepicker, to interact with the date picker.
23
+ Settings for (groups of) date pickers are maintained in an instance object,
24
+ allowing multiple different settings on the same page. */
25
+
26
+ function Datepicker() {
27
+ this._curInst = null; // The current instance in use
28
+ this._keyEvent = false; // If the last event was a key event
29
+ this._disabledInputs = []; // List of date picker inputs that have been disabled
30
+ this._datepickerShowing = false; // True if the popup picker is showing , false if not
31
+ this._inDialog = false; // True if showing within a "dialog", false if not
32
+ this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
33
+ this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
34
+ this._appendClass = "ui-datepicker-append"; // The name of the append marker class
35
+ this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
36
+ this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
37
+ this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
38
+ this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
39
+ this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
40
+ this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
41
+ this.regional = []; // Available regional settings, indexed by language code
42
+ this.regional[""] = { // Default regional settings
43
+ closeText: "Done", // Display text for close link
44
+ prevText: "Prev", // Display text for previous month link
45
+ nextText: "Next", // Display text for next month link
46
+ currentText: "Today", // Display text for current month link
47
+ monthNames: ["January","February","March","April","May","June",
48
+ "July","August","September","October","November","December"], // Names of months for drop-down and formatting
49
+ monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
50
+ dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
51
+ dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
52
+ dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
53
+ weekHeader: "Wk", // Column header for week of the year
54
+ dateFormat: "mm/dd/yy", // See format options on parseDate
55
+ firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
56
+ isRTL: false, // True if right-to-left language, false if left-to-right
57
+ showMonthAfterYear: false, // True if the year select precedes month, false for month then year
58
+ yearSuffix: "" // Additional text to append to the year in the month headers
59
+ };
60
+ this._defaults = { // Global defaults for all the date picker instances
61
+ showOn: "focus", // "focus" for popup on focus,
62
+ // "button" for trigger button, or "both" for either
63
+ showAnim: "fadeIn", // Name of jQuery animation for popup
64
+ showOptions: {}, // Options for enhanced animations
65
+ defaultDate: null, // Used when field is blank: actual date,
66
+ // +/-number for offset from today, null for today
67
+ appendText: "", // Display text following the input box, e.g. showing the format
68
+ buttonText: "...", // Text for trigger button
69
+ buttonImage: "", // URL for trigger button image
70
+ buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
71
+ hideIfNoPrevNext: false, // True to hide next/previous month links
72
+ // if not applicable, false to just disable them
73
+ navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
74
+ gotoCurrent: false, // True if today link goes back to current selection instead
75
+ changeMonth: false, // True if month can be selected directly, false if only prev/next
76
+ changeYear: false, // True if year can be selected directly, false if only prev/next
77
+ yearRange: "c-10:c+10", // Range of years to display in drop-down,
78
+ // either relative to today's year (-nn:+nn), relative to currently displayed year
79
+ // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
80
+ showOtherMonths: false, // True to show dates in other months, false to leave blank
81
+ selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
82
+ showWeek: false, // True to show week of the year, false to not show it
83
+ calculateWeek: this.iso8601Week, // How to calculate the week of the year,
84
+ // takes a Date and returns the number of the week for it
85
+ shortYearCutoff: "+10", // Short year values < this are in the current century,
86
+ // > this are in the previous century,
87
+ // string value starting with "+" for current year + value
88
+ minDate: null, // The earliest selectable date, or null for no limit
89
+ maxDate: null, // The latest selectable date, or null for no limit
90
+ duration: "fast", // Duration of display/closure
91
+ beforeShowDay: null, // Function that takes a date and returns an array with
92
+ // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
93
+ // [2] = cell title (optional), e.g. $.datepicker.noWeekends
94
+ beforeShow: null, // Function that takes an input field and
95
+ // returns a set of custom settings for the date picker
96
+ onSelect: null, // Define a callback function when a date is selected
97
+ onChangeMonthYear: null, // Define a callback function when the month or year is changed
98
+ onClose: null, // Define a callback function when the datepicker is closed
99
+ numberOfMonths: 1, // Number of months to show at a time
100
+ showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
101
+ stepMonths: 1, // Number of months to step back/forward
102
+ stepBigMonths: 12, // Number of months to step back/forward for the big links
103
+ altField: "", // Selector for an alternate field to store selected dates into
104
+ altFormat: "", // The date format to use for the alternate field
105
+ constrainInput: true, // The input is constrained by the current date format
106
+ showButtonPanel: false, // True to show button panel, false to not show it
107
+ autoSize: false, // True to size the input for the date format, false to leave as is
108
+ disabled: false // The initial disabled state
109
+ };
110
+ $.extend(this._defaults, this.regional[""]);
111
+ this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
112
+ }
113
+
114
+ $.extend(Datepicker.prototype, {
115
+ /* Class name added to elements to indicate already configured with a date picker. */
116
+ markerClassName: "hasDatepicker",
117
+
118
+ //Keep track of the maximum number of rows displayed (see #7043)
119
+ maxRows: 4,
120
+
121
+ // TODO rename to "widget" when switching to widget factory
122
+ _widgetDatepicker: function() {
123
+ return this.dpDiv;
124
+ },
125
+
126
+ /* Override the default settings for all instances of the date picker.
127
+ * @param settings object - the new settings to use as defaults (anonymous object)
128
+ * @return the manager object
129
+ */
130
+ setDefaults: function(settings) {
131
+ extendRemove(this._defaults, settings || {});
132
+ return this;
133
+ },
134
+
135
+ /* Attach the date picker to a jQuery selection.
136
+ * @param target element - the target input field or division or span
137
+ * @param settings object - the new settings to use for this date picker instance (anonymous)
138
+ */
139
+ _attachDatepicker: function(target, settings) {
140
+ var nodeName, inline, inst;
141
+ nodeName = target.nodeName.toLowerCase();
142
+ inline = (nodeName === "div" || nodeName === "span");
143
+ if (!target.id) {
144
+ this.uuid += 1;
145
+ target.id = "dp" + this.uuid;
146
+ }
147
+ inst = this._newInst($(target), inline);
148
+ inst.settings = $.extend({}, settings || {});
149
+ if (nodeName === "input") {
150
+ this._connectDatepicker(target, inst);
151
+ } else if (inline) {
152
+ this._inlineDatepicker(target, inst);
153
+ }
154
+ },
155
+
156
+ /* Create a new instance object. */
157
+ _newInst: function(target, inline) {
158
+ var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
159
+ return {id: id, input: target, // associated target
160
+ selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
161
+ drawMonth: 0, drawYear: 0, // month being drawn
162
+ inline: inline, // is datepicker inline or not
163
+ dpDiv: (!inline ? this.dpDiv : // presentation div
164
+ bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
165
+ },
166
+
167
+ /* Attach the date picker to an input field. */
168
+ _connectDatepicker: function(target, inst) {
169
+ var input = $(target);
170
+ inst.append = $([]);
171
+ inst.trigger = $([]);
172
+ if (input.hasClass(this.markerClassName)) {
173
+ return;
174
+ }
175
+ this._attachments(input, inst);
176
+ input.addClass(this.markerClassName).keydown(this._doKeyDown).
177
+ keypress(this._doKeyPress).keyup(this._doKeyUp);
178
+ this._autoSize(inst);
179
+ $.data(target, PROP_NAME, inst);
180
+ //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
181
+ if( inst.settings.disabled ) {
182
+ this._disableDatepicker( target );
183
+ }
184
+ },
185
+
186
+ /* Make attachments based on settings. */
187
+ _attachments: function(input, inst) {
188
+ var showOn, buttonText, buttonImage,
189
+ appendText = this._get(inst, "appendText"),
190
+ isRTL = this._get(inst, "isRTL");
191
+
192
+ if (inst.append) {
193
+ inst.append.remove();
194
+ }
195
+ if (appendText) {
196
+ inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
197
+ input[isRTL ? "before" : "after"](inst.append);
198
+ }
199
+
200
+ input.unbind("focus", this._showDatepicker);
201
+
202
+ if (inst.trigger) {
203
+ inst.trigger.remove();
204
+ }
205
+
206
+ showOn = this._get(inst, "showOn");
207
+ if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
208
+ input.focus(this._showDatepicker);
209
+ }
210
+ if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
211
+ buttonText = this._get(inst, "buttonText");
212
+ buttonImage = this._get(inst, "buttonImage");
213
+ inst.trigger = $(this._get(inst, "buttonImageOnly") ?
214
+ $("<img/>").addClass(this._triggerClass).
215
+ attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
216
+ $("<button type='button'></button>").addClass(this._triggerClass).
217
+ html(!buttonImage ? buttonText : $("<img/>").attr(
218
+ { src:buttonImage, alt:buttonText, title:buttonText })));
219
+ input[isRTL ? "before" : "after"](inst.trigger);
220
+ inst.trigger.click(function() {
221
+ if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
222
+ $.datepicker._hideDatepicker();
223
+ } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
224
+ $.datepicker._hideDatepicker();
225
+ $.datepicker._showDatepicker(input[0]);
226
+ } else {
227
+ $.datepicker._showDatepicker(input[0]);
228
+ }
229
+ return false;
230
+ });
231
+ }
232
+ },
233
+
234
+ /* Apply the maximum length for the date format. */
235
+ _autoSize: function(inst) {
236
+ if (this._get(inst, "autoSize") && !inst.inline) {
237
+ var findMax, max, maxI, i,
238
+ date = new Date(2009, 12 - 1, 20), // Ensure double digits
239
+ dateFormat = this._get(inst, "dateFormat");
240
+
241
+ if (dateFormat.match(/[DM]/)) {
242
+ findMax = function(names) {
243
+ max = 0;
244
+ maxI = 0;
245
+ for (i = 0; i < names.length; i++) {
246
+ if (names[i].length > max) {
247
+ max = names[i].length;
248
+ maxI = i;
249
+ }
250
+ }
251
+ return maxI;
252
+ };
253
+ date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
254
+ "monthNames" : "monthNamesShort"))));
255
+ date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
256
+ "dayNames" : "dayNamesShort"))) + 20 - date.getDay());
257
+ }
258
+ inst.input.attr("size", this._formatDate(inst, date).length);
259
+ }
260
+ },
261
+
262
+ /* Attach an inline date picker to a div. */
263
+ _inlineDatepicker: function(target, inst) {
264
+ var divSpan = $(target);
265
+ if (divSpan.hasClass(this.markerClassName)) {
266
+ return;
267
+ }
268
+ divSpan.addClass(this.markerClassName).append(inst.dpDiv);
269
+ $.data(target, PROP_NAME, inst);
270
+ this._setDate(inst, this._getDefaultDate(inst), true);
271
+ this._updateDatepicker(inst);
272
+ this._updateAlternate(inst);
273
+ //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
274
+ if( inst.settings.disabled ) {
275
+ this._disableDatepicker( target );
276
+ }
277
+ // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
278
+ // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
279
+ inst.dpDiv.css( "display", "block" );
280
+ },
281
+
282
+ /* Pop-up the date picker in a "dialog" box.
283
+ * @param input element - ignored
284
+ * @param date string or Date - the initial date to display
285
+ * @param onSelect function - the function to call when a date is selected
286
+ * @param settings object - update the dialog date picker instance's settings (anonymous object)
287
+ * @param pos int[2] - coordinates for the dialog's position within the screen or
288
+ * event - with x/y coordinates or
289
+ * leave empty for default (screen centre)
290
+ * @return the manager object
291
+ */
292
+ _dialogDatepicker: function(input, date, onSelect, settings, pos) {
293
+ var id, browserWidth, browserHeight, scrollX, scrollY,
294
+ inst = this._dialogInst; // internal instance
295
+
296
+ if (!inst) {
297
+ this.uuid += 1;
298
+ id = "dp" + this.uuid;
299
+ this._dialogInput = $("<input type='text' id='" + id +
300
+ "' style='position: absolute; top: -100px; width: 0px;'/>");
301
+ this._dialogInput.keydown(this._doKeyDown);
302
+ $("body").append(this._dialogInput);
303
+ inst = this._dialogInst = this._newInst(this._dialogInput, false);
304
+ inst.settings = {};
305
+ $.data(this._dialogInput[0], PROP_NAME, inst);
306
+ }
307
+ extendRemove(inst.settings, settings || {});
308
+ date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
309
+ this._dialogInput.val(date);
310
+
311
+ this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
312
+ if (!this._pos) {
313
+ browserWidth = document.documentElement.clientWidth;
314
+ browserHeight = document.documentElement.clientHeight;
315
+ scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
316
+ scrollY = document.documentElement.scrollTop || document.body.scrollTop;
317
+ this._pos = // should use actual width/height below
318
+ [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
319
+ }
320
+
321
+ // move input on screen for focus, but hidden behind dialog
322
+ this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
323
+ inst.settings.onSelect = onSelect;
324
+ this._inDialog = true;
325
+ this.dpDiv.addClass(this._dialogClass);
326
+ this._showDatepicker(this._dialogInput[0]);
327
+ if ($.blockUI) {
328
+ $.blockUI(this.dpDiv);
329
+ }
330
+ $.data(this._dialogInput[0], PROP_NAME, inst);
331
+ return this;
332
+ },
333
+
334
+ /* Detach a datepicker from its control.
335
+ * @param target element - the target input field or division or span
336
+ */
337
+ _destroyDatepicker: function(target) {
338
+ var nodeName,
339
+ $target = $(target),
340
+ inst = $.data(target, PROP_NAME);
341
+
342
+ if (!$target.hasClass(this.markerClassName)) {
343
+ return;
344
+ }
345
+
346
+ nodeName = target.nodeName.toLowerCase();
347
+ $.removeData(target, PROP_NAME);
348
+ if (nodeName === "input") {
349
+ inst.append.remove();
350
+ inst.trigger.remove();
351
+ $target.removeClass(this.markerClassName).
352
+ unbind("focus", this._showDatepicker).
353
+ unbind("keydown", this._doKeyDown).
354
+ unbind("keypress", this._doKeyPress).
355
+ unbind("keyup", this._doKeyUp);
356
+ } else if (nodeName === "div" || nodeName === "span") {
357
+ $target.removeClass(this.markerClassName).empty();
358
+ }
359
+ },
360
+
361
+ /* Enable the date picker to a jQuery selection.
362
+ * @param target element - the target input field or division or span
363
+ */
364
+ _enableDatepicker: function(target) {
365
+ var nodeName, inline,
366
+ $target = $(target),
367
+ inst = $.data(target, PROP_NAME);
368
+
369
+ if (!$target.hasClass(this.markerClassName)) {
370
+ return;
371
+ }
372
+
373
+ nodeName = target.nodeName.toLowerCase();
374
+ if (nodeName === "input") {
375
+ target.disabled = false;
376
+ inst.trigger.filter("button").
377
+ each(function() { this.disabled = false; }).end().
378
+ filter("img").css({opacity: "1.0", cursor: ""});
379
+ } else if (nodeName === "div" || nodeName === "span") {
380
+ inline = $target.children("." + this._inlineClass);
381
+ inline.children().removeClass("ui-state-disabled");
382
+ inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
383
+ prop("disabled", false);
384
+ }
385
+ this._disabledInputs = $.map(this._disabledInputs,
386
+ function(value) { return (value === target ? null : value); }); // delete entry
387
+ },
388
+
389
+ /* Disable the date picker to a jQuery selection.
390
+ * @param target element - the target input field or division or span
391
+ */
392
+ _disableDatepicker: function(target) {
393
+ var nodeName, inline,
394
+ $target = $(target),
395
+ inst = $.data(target, PROP_NAME);
396
+
397
+ if (!$target.hasClass(this.markerClassName)) {
398
+ return;
399
+ }
400
+
401
+ nodeName = target.nodeName.toLowerCase();
402
+ if (nodeName === "input") {
403
+ target.disabled = true;
404
+ inst.trigger.filter("button").
405
+ each(function() { this.disabled = true; }).end().
406
+ filter("img").css({opacity: "0.5", cursor: "default"});
407
+ } else if (nodeName === "div" || nodeName === "span") {
408
+ inline = $target.children("." + this._inlineClass);
409
+ inline.children().addClass("ui-state-disabled");
410
+ inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
411
+ prop("disabled", true);
412
+ }
413
+ this._disabledInputs = $.map(this._disabledInputs,
414
+ function(value) { return (value === target ? null : value); }); // delete entry
415
+ this._disabledInputs[this._disabledInputs.length] = target;
416
+ },
417
+
418
+ /* Is the first field in a jQuery collection disabled as a datepicker?
419
+ * @param target element - the target input field or division or span
420
+ * @return boolean - true if disabled, false if enabled
421
+ */
422
+ _isDisabledDatepicker: function(target) {
423
+ if (!target) {
424
+ return false;
425
+ }
426
+ for (var i = 0; i < this._disabledInputs.length; i++) {
427
+ if (this._disabledInputs[i] === target) {
428
+ return true;
429
+ }
430
+ }
431
+ return false;
432
+ },
433
+
434
+ /* Retrieve the instance data for the target control.
435
+ * @param target element - the target input field or division or span
436
+ * @return object - the associated instance data
437
+ * @throws error if a jQuery problem getting data
438
+ */
439
+ _getInst: function(target) {
440
+ try {
441
+ return $.data(target, PROP_NAME);
442
+ }
443
+ catch (err) {
444
+ throw "Missing instance data for this datepicker";
445
+ }
446
+ },
447
+
448
+ /* Update or retrieve the settings for a date picker attached to an input field or division.
449
+ * @param target element - the target input field or division or span
450
+ * @param name object - the new settings to update or
451
+ * string - the name of the setting to change or retrieve,
452
+ * when retrieving also "all" for all instance settings or
453
+ * "defaults" for all global defaults
454
+ * @param value any - the new value for the setting
455
+ * (omit if above is an object or to retrieve a value)
456
+ */
457
+ _optionDatepicker: function(target, name, value) {
458
+ var settings, date, minDate, maxDate,
459
+ inst = this._getInst(target);
460
+
461
+ if (arguments.length === 2 && typeof name === "string") {
462
+ return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
463
+ (inst ? (name === "all" ? $.extend({}, inst.settings) :
464
+ this._get(inst, name)) : null));
465
+ }
466
+
467
+ settings = name || {};
468
+ if (typeof name === "string") {
469
+ settings = {};
470
+ settings[name] = value;
471
+ }
472
+
473
+ if (inst) {
474
+ if (this._curInst === inst) {
475
+ this._hideDatepicker();
476
+ }
477
+
478
+ date = this._getDateDatepicker(target, true);
479
+ minDate = this._getMinMaxDate(inst, "min");
480
+ maxDate = this._getMinMaxDate(inst, "max");
481
+ extendRemove(inst.settings, settings);
482
+ // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
483
+ if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
484
+ inst.settings.minDate = this._formatDate(inst, minDate);
485
+ }
486
+ if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
487
+ inst.settings.maxDate = this._formatDate(inst, maxDate);
488
+ }
489
+ if ( "disabled" in settings ) {
490
+ if ( settings.disabled ) {
491
+ this._disableDatepicker(target);
492
+ } else {
493
+ this._enableDatepicker(target);
494
+ }
495
+ }
496
+ this._attachments($(target), inst);
497
+ this._autoSize(inst);
498
+ this._setDate(inst, date);
499
+ this._updateAlternate(inst);
500
+ this._updateDatepicker(inst);
501
+ }
502
+ },
503
+
504
+ // change method deprecated
505
+ _changeDatepicker: function(target, name, value) {
506
+ this._optionDatepicker(target, name, value);
507
+ },
508
+
509
+ /* Redraw the date picker attached to an input field or division.
510
+ * @param target element - the target input field or division or span
511
+ */
512
+ _refreshDatepicker: function(target) {
513
+ var inst = this._getInst(target);
514
+ if (inst) {
515
+ this._updateDatepicker(inst);
516
+ }
517
+ },
518
+
519
+ /* Set the dates for a jQuery selection.
520
+ * @param target element - the target input field or division or span
521
+ * @param date Date - the new date
522
+ */
523
+ _setDateDatepicker: function(target, date) {
524
+ var inst = this._getInst(target);
525
+ if (inst) {
526
+ this._setDate(inst, date);
527
+ this._updateDatepicker(inst);
528
+ this._updateAlternate(inst);
529
+ }
530
+ },
531
+
532
+ /* Get the date(s) for the first entry in a jQuery selection.
533
+ * @param target element - the target input field or division or span
534
+ * @param noDefault boolean - true if no default date is to be used
535
+ * @return Date - the current date
536
+ */
537
+ _getDateDatepicker: function(target, noDefault) {
538
+ var inst = this._getInst(target);
539
+ if (inst && !inst.inline) {
540
+ this._setDateFromField(inst, noDefault);
541
+ }
542
+ return (inst ? this._getDate(inst) : null);
543
+ },
544
+
545
+ /* Handle keystrokes. */
546
+ _doKeyDown: function(event) {
547
+ var onSelect, dateStr, sel,
548
+ inst = $.datepicker._getInst(event.target),
549
+ handled = true,
550
+ isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
551
+
552
+ inst._keyEvent = true;
553
+ if ($.datepicker._datepickerShowing) {
554
+ switch (event.keyCode) {
555
+ case 9: $.datepicker._hideDatepicker();
556
+ handled = false;
557
+ break; // hide on tab out
558
+ case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
559
+ $.datepicker._currentClass + ")", inst.dpDiv);
560
+ if (sel[0]) {
561
+ $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
562
+ }
563
+
564
+ onSelect = $.datepicker._get(inst, "onSelect");
565
+ if (onSelect) {
566
+ dateStr = $.datepicker._formatDate(inst);
567
+
568
+ // trigger custom callback
569
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
570
+ } else {
571
+ $.datepicker._hideDatepicker();
572
+ }
573
+
574
+ return false; // don't submit the form
575
+ case 27: $.datepicker._hideDatepicker();
576
+ break; // hide on escape
577
+ case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
578
+ -$.datepicker._get(inst, "stepBigMonths") :
579
+ -$.datepicker._get(inst, "stepMonths")), "M");
580
+ break; // previous month/year on page up/+ ctrl
581
+ case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
582
+ +$.datepicker._get(inst, "stepBigMonths") :
583
+ +$.datepicker._get(inst, "stepMonths")), "M");
584
+ break; // next month/year on page down/+ ctrl
585
+ case 35: if (event.ctrlKey || event.metaKey) {
586
+ $.datepicker._clearDate(event.target);
587
+ }
588
+ handled = event.ctrlKey || event.metaKey;
589
+ break; // clear on ctrl or command +end
590
+ case 36: if (event.ctrlKey || event.metaKey) {
591
+ $.datepicker._gotoToday(event.target);
592
+ }
593
+ handled = event.ctrlKey || event.metaKey;
594
+ break; // current on ctrl or command +home
595
+ case 37: if (event.ctrlKey || event.metaKey) {
596
+ $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
597
+ }
598
+ handled = event.ctrlKey || event.metaKey;
599
+ // -1 day on ctrl or command +left
600
+ if (event.originalEvent.altKey) {
601
+ $.datepicker._adjustDate(event.target, (event.ctrlKey ?
602
+ -$.datepicker._get(inst, "stepBigMonths") :
603
+ -$.datepicker._get(inst, "stepMonths")), "M");
604
+ }
605
+ // next month/year on alt +left on Mac
606
+ break;
607
+ case 38: if (event.ctrlKey || event.metaKey) {
608
+ $.datepicker._adjustDate(event.target, -7, "D");
609
+ }
610
+ handled = event.ctrlKey || event.metaKey;
611
+ break; // -1 week on ctrl or command +up
612
+ case 39: if (event.ctrlKey || event.metaKey) {
613
+ $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
614
+ }
615
+ handled = event.ctrlKey || event.metaKey;
616
+ // +1 day on ctrl or command +right
617
+ if (event.originalEvent.altKey) {
618
+ $.datepicker._adjustDate(event.target, (event.ctrlKey ?
619
+ +$.datepicker._get(inst, "stepBigMonths") :
620
+ +$.datepicker._get(inst, "stepMonths")), "M");
621
+ }
622
+ // next month/year on alt +right
623
+ break;
624
+ case 40: if (event.ctrlKey || event.metaKey) {
625
+ $.datepicker._adjustDate(event.target, +7, "D");
626
+ }
627
+ handled = event.ctrlKey || event.metaKey;
628
+ break; // +1 week on ctrl or command +down
629
+ default: handled = false;
630
+ }
631
+ } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
632
+ $.datepicker._showDatepicker(this);
633
+ } else {
634
+ handled = false;
635
+ }
636
+
637
+ if (handled) {
638
+ event.preventDefault();
639
+ event.stopPropagation();
640
+ }
641
+ },
642
+
643
+ /* Filter entered characters - based on date format. */
644
+ _doKeyPress: function(event) {
645
+ var chars, chr,
646
+ inst = $.datepicker._getInst(event.target);
647
+
648
+ if ($.datepicker._get(inst, "constrainInput")) {
649
+ chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
650
+ chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
651
+ return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
652
+ }
653
+ },
654
+
655
+ /* Synchronise manual entry and field/alternate field. */
656
+ _doKeyUp: function(event) {
657
+ var date,
658
+ inst = $.datepicker._getInst(event.target);
659
+
660
+ if (inst.input.val() !== inst.lastVal) {
661
+ try {
662
+ date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
663
+ (inst.input ? inst.input.val() : null),
664
+ $.datepicker._getFormatConfig(inst));
665
+
666
+ if (date) { // only if valid
667
+ $.datepicker._setDateFromField(inst);
668
+ $.datepicker._updateAlternate(inst);
669
+ $.datepicker._updateDatepicker(inst);
670
+ }
671
+ }
672
+ catch (err) {
673
+ }
674
+ }
675
+ return true;
676
+ },
677
+
678
+ /* Pop-up the date picker for a given input field.
679
+ * If false returned from beforeShow event handler do not show.
680
+ * @param input element - the input field attached to the date picker or
681
+ * event - if triggered by focus
682
+ */
683
+ _showDatepicker: function(input) {
684
+ input = input.target || input;
685
+ if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
686
+ input = $("input", input.parentNode)[0];
687
+ }
688
+
689
+ if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
690
+ return;
691
+ }
692
+
693
+ var inst, beforeShow, beforeShowSettings, isFixed,
694
+ offset, showAnim, duration;
695
+
696
+ inst = $.datepicker._getInst(input);
697
+ if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
698
+ $.datepicker._curInst.dpDiv.stop(true, true);
699
+ if ( inst && $.datepicker._datepickerShowing ) {
700
+ $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
701
+ }
702
+ }
703
+
704
+ beforeShow = $.datepicker._get(inst, "beforeShow");
705
+ beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
706
+ if(beforeShowSettings === false){
707
+ return;
708
+ }
709
+ extendRemove(inst.settings, beforeShowSettings);
710
+
711
+ inst.lastVal = null;
712
+ $.datepicker._lastInput = input;
713
+ $.datepicker._setDateFromField(inst);
714
+
715
+ if ($.datepicker._inDialog) { // hide cursor
716
+ input.value = "";
717
+ }
718
+ if (!$.datepicker._pos) { // position below input
719
+ $.datepicker._pos = $.datepicker._findPos(input);
720
+ $.datepicker._pos[1] += input.offsetHeight; // add the height
721
+ }
722
+
723
+ isFixed = false;
724
+ $(input).parents().each(function() {
725
+ isFixed |= $(this).css("position") === "fixed";
726
+ return !isFixed;
727
+ });
728
+
729
+ offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
730
+ $.datepicker._pos = null;
731
+ //to avoid flashes on Firefox
732
+ inst.dpDiv.empty();
733
+ // determine sizing offscreen
734
+ inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
735
+ $.datepicker._updateDatepicker(inst);
736
+ // fix width for dynamic number of date pickers
737
+ // and adjust position before showing
738
+ offset = $.datepicker._checkOffset(inst, offset, isFixed);
739
+ inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
740
+ "static" : (isFixed ? "fixed" : "absolute")), display: "none",
741
+ left: offset.left + "px", top: offset.top + "px"});
742
+
743
+ if (!inst.inline) {
744
+ showAnim = $.datepicker._get(inst, "showAnim");
745
+ duration = $.datepicker._get(inst, "duration");
746
+ inst.dpDiv.zIndex($(input).zIndex()+1);
747
+ $.datepicker._datepickerShowing = true;
748
+
749
+ if ( $.effects && $.effects.effect[ showAnim ] ) {
750
+ inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
751
+ } else {
752
+ inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
753
+ }
754
+
755
+ if ( $.datepicker._shouldFocusInput( inst ) ) {
756
+ inst.input.focus();
757
+ }
758
+
759
+ $.datepicker._curInst = inst;
760
+ }
761
+ },
762
+
763
+ /* Generate the date picker content. */
764
+ _updateDatepicker: function(inst) {
765
+ this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
766
+ instActive = inst; // for delegate hover events
767
+ inst.dpDiv.empty().append(this._generateHTML(inst));
768
+ this._attachHandlers(inst);
769
+ inst.dpDiv.find("." + this._dayOverClass + " a").mouseover();
770
+
771
+ var origyearshtml,
772
+ numMonths = this._getNumberOfMonths(inst),
773
+ cols = numMonths[1],
774
+ width = 17;
775
+
776
+ inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
777
+ if (cols > 1) {
778
+ inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
779
+ }
780
+ inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
781
+ "Class"]("ui-datepicker-multi");
782
+ inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
783
+ "Class"]("ui-datepicker-rtl");
784
+
785
+ if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
786
+ inst.input.focus();
787
+ }
788
+
789
+ // deffered render of the years select (to avoid flashes on Firefox)
790
+ if( inst.yearshtml ){
791
+ origyearshtml = inst.yearshtml;
792
+ setTimeout(function(){
793
+ //assure that inst.yearshtml didn't change.
794
+ if( origyearshtml === inst.yearshtml && inst.yearshtml ){
795
+ inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
796
+ }
797
+ origyearshtml = inst.yearshtml = null;
798
+ }, 0);
799
+ }
800
+ },
801
+
802
+ // #6694 - don't focus the input if it's already focused
803
+ // this breaks the change event in IE
804
+ // Support: IE and jQuery <1.9
805
+ _shouldFocusInput: function( inst ) {
806
+ return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
807
+ },
808
+
809
+ /* Check positioning to remain on screen. */
810
+ _checkOffset: function(inst, offset, isFixed) {
811
+ var dpWidth = inst.dpDiv.outerWidth(),
812
+ dpHeight = inst.dpDiv.outerHeight(),
813
+ inputWidth = inst.input ? inst.input.outerWidth() : 0,
814
+ inputHeight = inst.input ? inst.input.outerHeight() : 0,
815
+ viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
816
+ viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
817
+
818
+ offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
819
+ offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
820
+ offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
821
+
822
+ // now check if datepicker is showing outside window viewport - move to a better place if so.
823
+ offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
824
+ Math.abs(offset.left + dpWidth - viewWidth) : 0);
825
+ offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
826
+ Math.abs(dpHeight + inputHeight) : 0);
827
+
828
+ return offset;
829
+ },
830
+
831
+ /* Find an object's position on the screen. */
832
+ _findPos: function(obj) {
833
+ var position,
834
+ inst = this._getInst(obj),
835
+ isRTL = this._get(inst, "isRTL");
836
+
837
+ while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
838
+ obj = obj[isRTL ? "previousSibling" : "nextSibling"];
839
+ }
840
+
841
+ position = $(obj).offset();
842
+ return [position.left, position.top];
843
+ },
844
+
845
+ /* Hide the date picker from view.
846
+ * @param input element - the input field attached to the date picker
847
+ */
848
+ _hideDatepicker: function(input) {
849
+ var showAnim, duration, postProcess, onClose,
850
+ inst = this._curInst;
851
+
852
+ if (!inst || (input && inst !== $.data(input, PROP_NAME))) {
853
+ return;
854
+ }
855
+
856
+ if (this._datepickerShowing) {
857
+ showAnim = this._get(inst, "showAnim");
858
+ duration = this._get(inst, "duration");
859
+ postProcess = function() {
860
+ $.datepicker._tidyDialog(inst);
861
+ };
862
+
863
+ // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
864
+ if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
865
+ inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
866
+ } else {
867
+ inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
868
+ (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
869
+ }
870
+
871
+ if (!showAnim) {
872
+ postProcess();
873
+ }
874
+ this._datepickerShowing = false;
875
+
876
+ onClose = this._get(inst, "onClose");
877
+ if (onClose) {
878
+ onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
879
+ }
880
+
881
+ this._lastInput = null;
882
+ if (this._inDialog) {
883
+ this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
884
+ if ($.blockUI) {
885
+ $.unblockUI();
886
+ $("body").append(this.dpDiv);
887
+ }
888
+ }
889
+ this._inDialog = false;
890
+ }
891
+ },
892
+
893
+ /* Tidy up after a dialog display. */
894
+ _tidyDialog: function(inst) {
895
+ inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
896
+ },
897
+
898
+ /* Close date picker if clicked elsewhere. */
899
+ _checkExternalClick: function(event) {
900
+ if (!$.datepicker._curInst) {
901
+ return;
902
+ }
903
+
904
+ var $target = $(event.target),
905
+ inst = $.datepicker._getInst($target[0]);
906
+
907
+ if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
908
+ $target.parents("#" + $.datepicker._mainDivId).length === 0 &&
909
+ !$target.hasClass($.datepicker.markerClassName) &&
910
+ !$target.closest("." + $.datepicker._triggerClass).length &&
911
+ $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
912
+ ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
913
+ $.datepicker._hideDatepicker();
914
+ }
915
+ },
916
+
917
+ /* Adjust one of the date sub-fields. */
918
+ _adjustDate: function(id, offset, period) {
919
+ var target = $(id),
920
+ inst = this._getInst(target[0]);
921
+
922
+ if (this._isDisabledDatepicker(target[0])) {
923
+ return;
924
+ }
925
+ this._adjustInstDate(inst, offset +
926
+ (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
927
+ period);
928
+ this._updateDatepicker(inst);
929
+ },
930
+
931
+ /* Action for current link. */
932
+ _gotoToday: function(id) {
933
+ var date,
934
+ target = $(id),
935
+ inst = this._getInst(target[0]);
936
+
937
+ if (this._get(inst, "gotoCurrent") && inst.currentDay) {
938
+ inst.selectedDay = inst.currentDay;
939
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth;
940
+ inst.drawYear = inst.selectedYear = inst.currentYear;
941
+ } else {
942
+ date = new Date();
943
+ inst.selectedDay = date.getDate();
944
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
945
+ inst.drawYear = inst.selectedYear = date.getFullYear();
946
+ }
947
+ this._notifyChange(inst);
948
+ this._adjustDate(target);
949
+ },
950
+
951
+ /* Action for selecting a new month/year. */
952
+ _selectMonthYear: function(id, select, period) {
953
+ var target = $(id),
954
+ inst = this._getInst(target[0]);
955
+
956
+ inst["selected" + (period === "M" ? "Month" : "Year")] =
957
+ inst["draw" + (period === "M" ? "Month" : "Year")] =
958
+ parseInt(select.options[select.selectedIndex].value,10);
959
+
960
+ this._notifyChange(inst);
961
+ this._adjustDate(target);
962
+ },
963
+
964
+ /* Action for selecting a day. */
965
+ _selectDay: function(id, month, year, td) {
966
+ var inst,
967
+ target = $(id);
968
+
969
+ if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
970
+ return;
971
+ }
972
+
973
+ inst = this._getInst(target[0]);
974
+ inst.selectedDay = inst.currentDay = $("a", td).html();
975
+ inst.selectedMonth = inst.currentMonth = month;
976
+ inst.selectedYear = inst.currentYear = year;
977
+ this._selectDate(id, this._formatDate(inst,
978
+ inst.currentDay, inst.currentMonth, inst.currentYear));
979
+ },
980
+
981
+ /* Erase the input field and hide the date picker. */
982
+ _clearDate: function(id) {
983
+ var target = $(id);
984
+ this._selectDate(target, "");
985
+ },
986
+
987
+ /* Update the input field with the selected date. */
988
+ _selectDate: function(id, dateStr) {
989
+ var onSelect,
990
+ target = $(id),
991
+ inst = this._getInst(target[0]);
992
+
993
+ dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
994
+ if (inst.input) {
995
+ inst.input.val(dateStr);
996
+ }
997
+ this._updateAlternate(inst);
998
+
999
+ onSelect = this._get(inst, "onSelect");
1000
+ if (onSelect) {
1001
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
1002
+ } else if (inst.input) {
1003
+ inst.input.trigger("change"); // fire the change event
1004
+ }
1005
+
1006
+ if (inst.inline){
1007
+ this._updateDatepicker(inst);
1008
+ } else {
1009
+ this._hideDatepicker();
1010
+ this._lastInput = inst.input[0];
1011
+ if (typeof(inst.input[0]) !== "object") {
1012
+ inst.input.focus(); // restore focus
1013
+ }
1014
+ this._lastInput = null;
1015
+ }
1016
+ },
1017
+
1018
+ /* Update any alternate field to synchronise with the main field. */
1019
+ _updateAlternate: function(inst) {
1020
+ var altFormat, date, dateStr,
1021
+ altField = this._get(inst, "altField");
1022
+
1023
+ if (altField) { // update alternate field too
1024
+ altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
1025
+ date = this._getDate(inst);
1026
+ dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
1027
+ $(altField).each(function() { $(this).val(dateStr); });
1028
+ }
1029
+ },
1030
+
1031
+ /* Set as beforeShowDay function to prevent selection of weekends.
1032
+ * @param date Date - the date to customise
1033
+ * @return [boolean, string] - is this date selectable?, what is its CSS class?
1034
+ */
1035
+ noWeekends: function(date) {
1036
+ var day = date.getDay();
1037
+ return [(day > 0 && day < 6), ""];
1038
+ },
1039
+
1040
+ /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
1041
+ * @param date Date - the date to get the week for
1042
+ * @return number - the number of the week within the year that contains this date
1043
+ */
1044
+ iso8601Week: function(date) {
1045
+ var time,
1046
+ checkDate = new Date(date.getTime());
1047
+
1048
+ // Find Thursday of this week starting on Monday
1049
+ checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
1050
+
1051
+ time = checkDate.getTime();
1052
+ checkDate.setMonth(0); // Compare with Jan 1
1053
+ checkDate.setDate(1);
1054
+ return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
1055
+ },
1056
+
1057
+ /* Parse a string value into a date object.
1058
+ * See formatDate below for the possible formats.
1059
+ *
1060
+ * @param format string - the expected format of the date
1061
+ * @param value string - the date in the above format
1062
+ * @param settings Object - attributes include:
1063
+ * shortYearCutoff number - the cutoff year for determining the century (optional)
1064
+ * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
1065
+ * dayNames string[7] - names of the days from Sunday (optional)
1066
+ * monthNamesShort string[12] - abbreviated names of the months (optional)
1067
+ * monthNames string[12] - names of the months (optional)
1068
+ * @return Date - the extracted date value or null if value is blank
1069
+ */
1070
+ parseDate: function (format, value, settings) {
1071
+ if (format == null || value == null) {
1072
+ throw "Invalid arguments";
1073
+ }
1074
+
1075
+ value = (typeof value === "object" ? value.toString() : value + "");
1076
+ if (value === "") {
1077
+ return null;
1078
+ }
1079
+
1080
+ var iFormat, dim, extra,
1081
+ iValue = 0,
1082
+ shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
1083
+ shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
1084
+ new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
1085
+ dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
1086
+ dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
1087
+ monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
1088
+ monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
1089
+ year = -1,
1090
+ month = -1,
1091
+ day = -1,
1092
+ doy = -1,
1093
+ literal = false,
1094
+ date,
1095
+ // Check whether a format character is doubled
1096
+ lookAhead = function(match) {
1097
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
1098
+ if (matches) {
1099
+ iFormat++;
1100
+ }
1101
+ return matches;
1102
+ },
1103
+ // Extract a number from the string value
1104
+ getNumber = function(match) {
1105
+ var isDoubled = lookAhead(match),
1106
+ size = (match === "@" ? 14 : (match === "!" ? 20 :
1107
+ (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
1108
+ digits = new RegExp("^\\d{1," + size + "}"),
1109
+ num = value.substring(iValue).match(digits);
1110
+ if (!num) {
1111
+ throw "Missing number at position " + iValue;
1112
+ }
1113
+ iValue += num[0].length;
1114
+ return parseInt(num[0], 10);
1115
+ },
1116
+ // Extract a name from the string value and convert to an index
1117
+ getName = function(match, shortNames, longNames) {
1118
+ var index = -1,
1119
+ names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
1120
+ return [ [k, v] ];
1121
+ }).sort(function (a, b) {
1122
+ return -(a[1].length - b[1].length);
1123
+ });
1124
+
1125
+ $.each(names, function (i, pair) {
1126
+ var name = pair[1];
1127
+ if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
1128
+ index = pair[0];
1129
+ iValue += name.length;
1130
+ return false;
1131
+ }
1132
+ });
1133
+ if (index !== -1) {
1134
+ return index + 1;
1135
+ } else {
1136
+ throw "Unknown name at position " + iValue;
1137
+ }
1138
+ },
1139
+ // Confirm that a literal character matches the string value
1140
+ checkLiteral = function() {
1141
+ if (value.charAt(iValue) !== format.charAt(iFormat)) {
1142
+ throw "Unexpected literal at position " + iValue;
1143
+ }
1144
+ iValue++;
1145
+ };
1146
+
1147
+ for (iFormat = 0; iFormat < format.length; iFormat++) {
1148
+ if (literal) {
1149
+ if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
1150
+ literal = false;
1151
+ } else {
1152
+ checkLiteral();
1153
+ }
1154
+ } else {
1155
+ switch (format.charAt(iFormat)) {
1156
+ case "d":
1157
+ day = getNumber("d");
1158
+ break;
1159
+ case "D":
1160
+ getName("D", dayNamesShort, dayNames);
1161
+ break;
1162
+ case "o":
1163
+ doy = getNumber("o");
1164
+ break;
1165
+ case "m":
1166
+ month = getNumber("m");
1167
+ break;
1168
+ case "M":
1169
+ month = getName("M", monthNamesShort, monthNames);
1170
+ break;
1171
+ case "y":
1172
+ year = getNumber("y");
1173
+ break;
1174
+ case "@":
1175
+ date = new Date(getNumber("@"));
1176
+ year = date.getFullYear();
1177
+ month = date.getMonth() + 1;
1178
+ day = date.getDate();
1179
+ break;
1180
+ case "!":
1181
+ date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
1182
+ year = date.getFullYear();
1183
+ month = date.getMonth() + 1;
1184
+ day = date.getDate();
1185
+ break;
1186
+ case "'":
1187
+ if (lookAhead("'")){
1188
+ checkLiteral();
1189
+ } else {
1190
+ literal = true;
1191
+ }
1192
+ break;
1193
+ default:
1194
+ checkLiteral();
1195
+ }
1196
+ }
1197
+ }
1198
+
1199
+ if (iValue < value.length){
1200
+ extra = value.substr(iValue);
1201
+ if (!/^\s+/.test(extra)) {
1202
+ throw "Extra/unparsed characters found in date: " + extra;
1203
+ }
1204
+ }
1205
+
1206
+ if (year === -1) {
1207
+ year = new Date().getFullYear();
1208
+ } else if (year < 100) {
1209
+ year += new Date().getFullYear() - new Date().getFullYear() % 100 +
1210
+ (year <= shortYearCutoff ? 0 : -100);
1211
+ }
1212
+
1213
+ if (doy > -1) {
1214
+ month = 1;
1215
+ day = doy;
1216
+ do {
1217
+ dim = this._getDaysInMonth(year, month - 1);
1218
+ if (day <= dim) {
1219
+ break;
1220
+ }
1221
+ month++;
1222
+ day -= dim;
1223
+ } while (true);
1224
+ }
1225
+
1226
+ date = this._daylightSavingAdjust(new Date(year, month - 1, day));
1227
+ if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
1228
+ throw "Invalid date"; // E.g. 31/02/00
1229
+ }
1230
+ return date;
1231
+ },
1232
+
1233
+ /* Standard date formats. */
1234
+ ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
1235
+ COOKIE: "D, dd M yy",
1236
+ ISO_8601: "yy-mm-dd",
1237
+ RFC_822: "D, d M y",
1238
+ RFC_850: "DD, dd-M-y",
1239
+ RFC_1036: "D, d M y",
1240
+ RFC_1123: "D, d M yy",
1241
+ RFC_2822: "D, d M yy",
1242
+ RSS: "D, d M y", // RFC 822
1243
+ TICKS: "!",
1244
+ TIMESTAMP: "@",
1245
+ W3C: "yy-mm-dd", // ISO 8601
1246
+
1247
+ _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
1248
+ Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
1249
+
1250
+ /* Format a date object into a string value.
1251
+ * The format can be combinations of the following:
1252
+ * d - day of month (no leading zero)
1253
+ * dd - day of month (two digit)
1254
+ * o - day of year (no leading zeros)
1255
+ * oo - day of year (three digit)
1256
+ * D - day name short
1257
+ * DD - day name long
1258
+ * m - month of year (no leading zero)
1259
+ * mm - month of year (two digit)
1260
+ * M - month name short
1261
+ * MM - month name long
1262
+ * y - year (two digit)
1263
+ * yy - year (four digit)
1264
+ * @ - Unix timestamp (ms since 01/01/1970)
1265
+ * ! - Windows ticks (100ns since 01/01/0001)
1266
+ * "..." - literal text
1267
+ * '' - single quote
1268
+ *
1269
+ * @param format string - the desired format of the date
1270
+ * @param date Date - the date value to format
1271
+ * @param settings Object - attributes include:
1272
+ * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
1273
+ * dayNames string[7] - names of the days from Sunday (optional)
1274
+ * monthNamesShort string[12] - abbreviated names of the months (optional)
1275
+ * monthNames string[12] - names of the months (optional)
1276
+ * @return string - the date in the above format
1277
+ */
1278
+ formatDate: function (format, date, settings) {
1279
+ if (!date) {
1280
+ return "";
1281
+ }
1282
+
1283
+ var iFormat,
1284
+ dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
1285
+ dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
1286
+ monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
1287
+ monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
1288
+ // Check whether a format character is doubled
1289
+ lookAhead = function(match) {
1290
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
1291
+ if (matches) {
1292
+ iFormat++;
1293
+ }
1294
+ return matches;
1295
+ },
1296
+ // Format a number, with leading zero if necessary
1297
+ formatNumber = function(match, value, len) {
1298
+ var num = "" + value;
1299
+ if (lookAhead(match)) {
1300
+ while (num.length < len) {
1301
+ num = "0" + num;
1302
+ }
1303
+ }
1304
+ return num;
1305
+ },
1306
+ // Format a name, short or long as requested
1307
+ formatName = function(match, value, shortNames, longNames) {
1308
+ return (lookAhead(match) ? longNames[value] : shortNames[value]);
1309
+ },
1310
+ output = "",
1311
+ literal = false;
1312
+
1313
+ if (date) {
1314
+ for (iFormat = 0; iFormat < format.length; iFormat++) {
1315
+ if (literal) {
1316
+ if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
1317
+ literal = false;
1318
+ } else {
1319
+ output += format.charAt(iFormat);
1320
+ }
1321
+ } else {
1322
+ switch (format.charAt(iFormat)) {
1323
+ case "d":
1324
+ output += formatNumber("d", date.getDate(), 2);
1325
+ break;
1326
+ case "D":
1327
+ output += formatName("D", date.getDay(), dayNamesShort, dayNames);
1328
+ break;
1329
+ case "o":
1330
+ output += formatNumber("o",
1331
+ Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
1332
+ break;
1333
+ case "m":
1334
+ output += formatNumber("m", date.getMonth() + 1, 2);
1335
+ break;
1336
+ case "M":
1337
+ output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
1338
+ break;
1339
+ case "y":
1340
+ output += (lookAhead("y") ? date.getFullYear() :
1341
+ (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
1342
+ break;
1343
+ case "@":
1344
+ output += date.getTime();
1345
+ break;
1346
+ case "!":
1347
+ output += date.getTime() * 10000 + this._ticksTo1970;
1348
+ break;
1349
+ case "'":
1350
+ if (lookAhead("'")) {
1351
+ output += "'";
1352
+ } else {
1353
+ literal = true;
1354
+ }
1355
+ break;
1356
+ default:
1357
+ output += format.charAt(iFormat);
1358
+ }
1359
+ }
1360
+ }
1361
+ }
1362
+ return output;
1363
+ },
1364
+
1365
+ /* Extract all possible characters from the date format. */
1366
+ _possibleChars: function (format) {
1367
+ var iFormat,
1368
+ chars = "",
1369
+ literal = false,
1370
+ // Check whether a format character is doubled
1371
+ lookAhead = function(match) {
1372
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
1373
+ if (matches) {
1374
+ iFormat++;
1375
+ }
1376
+ return matches;
1377
+ };
1378
+
1379
+ for (iFormat = 0; iFormat < format.length; iFormat++) {
1380
+ if (literal) {
1381
+ if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
1382
+ literal = false;
1383
+ } else {
1384
+ chars += format.charAt(iFormat);
1385
+ }
1386
+ } else {
1387
+ switch (format.charAt(iFormat)) {
1388
+ case "d": case "m": case "y": case "@":
1389
+ chars += "0123456789";
1390
+ break;
1391
+ case "D": case "M":
1392
+ return null; // Accept anything
1393
+ case "'":
1394
+ if (lookAhead("'")) {
1395
+ chars += "'";
1396
+ } else {
1397
+ literal = true;
1398
+ }
1399
+ break;
1400
+ default:
1401
+ chars += format.charAt(iFormat);
1402
+ }
1403
+ }
1404
+ }
1405
+ return chars;
1406
+ },
1407
+
1408
+ /* Get a setting value, defaulting if necessary. */
1409
+ _get: function(inst, name) {
1410
+ return inst.settings[name] !== undefined ?
1411
+ inst.settings[name] : this._defaults[name];
1412
+ },
1413
+
1414
+ /* Parse existing date and initialise date picker. */
1415
+ _setDateFromField: function(inst, noDefault) {
1416
+ if (inst.input.val() === inst.lastVal) {
1417
+ return;
1418
+ }
1419
+
1420
+ var dateFormat = this._get(inst, "dateFormat"),
1421
+ dates = inst.lastVal = inst.input ? inst.input.val() : null,
1422
+ defaultDate = this._getDefaultDate(inst),
1423
+ date = defaultDate,
1424
+ settings = this._getFormatConfig(inst);
1425
+
1426
+ try {
1427
+ date = this.parseDate(dateFormat, dates, settings) || defaultDate;
1428
+ } catch (event) {
1429
+ dates = (noDefault ? "" : dates);
1430
+ }
1431
+ inst.selectedDay = date.getDate();
1432
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
1433
+ inst.drawYear = inst.selectedYear = date.getFullYear();
1434
+ inst.currentDay = (dates ? date.getDate() : 0);
1435
+ inst.currentMonth = (dates ? date.getMonth() : 0);
1436
+ inst.currentYear = (dates ? date.getFullYear() : 0);
1437
+ this._adjustInstDate(inst);
1438
+ },
1439
+
1440
+ /* Retrieve the default date shown on opening. */
1441
+ _getDefaultDate: function(inst) {
1442
+ return this._restrictMinMax(inst,
1443
+ this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
1444
+ },
1445
+
1446
+ /* A date may be specified as an exact value or a relative one. */
1447
+ _determineDate: function(inst, date, defaultDate) {
1448
+ var offsetNumeric = function(offset) {
1449
+ var date = new Date();
1450
+ date.setDate(date.getDate() + offset);
1451
+ return date;
1452
+ },
1453
+ offsetString = function(offset) {
1454
+ try {
1455
+ return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
1456
+ offset, $.datepicker._getFormatConfig(inst));
1457
+ }
1458
+ catch (e) {
1459
+ // Ignore
1460
+ }
1461
+
1462
+ var date = (offset.toLowerCase().match(/^c/) ?
1463
+ $.datepicker._getDate(inst) : null) || new Date(),
1464
+ year = date.getFullYear(),
1465
+ month = date.getMonth(),
1466
+ day = date.getDate(),
1467
+ pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
1468
+ matches = pattern.exec(offset);
1469
+
1470
+ while (matches) {
1471
+ switch (matches[2] || "d") {
1472
+ case "d" : case "D" :
1473
+ day += parseInt(matches[1],10); break;
1474
+ case "w" : case "W" :
1475
+ day += parseInt(matches[1],10) * 7; break;
1476
+ case "m" : case "M" :
1477
+ month += parseInt(matches[1],10);
1478
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
1479
+ break;
1480
+ case "y": case "Y" :
1481
+ year += parseInt(matches[1],10);
1482
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
1483
+ break;
1484
+ }
1485
+ matches = pattern.exec(offset);
1486
+ }
1487
+ return new Date(year, month, day);
1488
+ },
1489
+ newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
1490
+ (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
1491
+
1492
+ newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
1493
+ if (newDate) {
1494
+ newDate.setHours(0);
1495
+ newDate.setMinutes(0);
1496
+ newDate.setSeconds(0);
1497
+ newDate.setMilliseconds(0);
1498
+ }
1499
+ return this._daylightSavingAdjust(newDate);
1500
+ },
1501
+
1502
+ /* Handle switch to/from daylight saving.
1503
+ * Hours may be non-zero on daylight saving cut-over:
1504
+ * > 12 when midnight changeover, but then cannot generate
1505
+ * midnight datetime, so jump to 1AM, otherwise reset.
1506
+ * @param date (Date) the date to check
1507
+ * @return (Date) the corrected date
1508
+ */
1509
+ _daylightSavingAdjust: function(date) {
1510
+ if (!date) {
1511
+ return null;
1512
+ }
1513
+ date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
1514
+ return date;
1515
+ },
1516
+
1517
+ /* Set the date(s) directly. */
1518
+ _setDate: function(inst, date, noChange) {
1519
+ var clear = !date,
1520
+ origMonth = inst.selectedMonth,
1521
+ origYear = inst.selectedYear,
1522
+ newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
1523
+
1524
+ inst.selectedDay = inst.currentDay = newDate.getDate();
1525
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
1526
+ inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
1527
+ if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
1528
+ this._notifyChange(inst);
1529
+ }
1530
+ this._adjustInstDate(inst);
1531
+ if (inst.input) {
1532
+ inst.input.val(clear ? "" : this._formatDate(inst));
1533
+ }
1534
+ },
1535
+
1536
+ /* Retrieve the date(s) directly. */
1537
+ _getDate: function(inst) {
1538
+ var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
1539
+ this._daylightSavingAdjust(new Date(
1540
+ inst.currentYear, inst.currentMonth, inst.currentDay)));
1541
+ return startDate;
1542
+ },
1543
+
1544
+ /* Attach the onxxx handlers. These are declared statically so
1545
+ * they work with static code transformers like Caja.
1546
+ */
1547
+ _attachHandlers: function(inst) {
1548
+ var stepMonths = this._get(inst, "stepMonths"),
1549
+ id = "#" + inst.id.replace( /\\\\/g, "\\" );
1550
+ inst.dpDiv.find("[data-handler]").map(function () {
1551
+ var handler = {
1552
+ prev: function () {
1553
+ $.datepicker._adjustDate(id, -stepMonths, "M");
1554
+ },
1555
+ next: function () {
1556
+ $.datepicker._adjustDate(id, +stepMonths, "M");
1557
+ },
1558
+ hide: function () {
1559
+ $.datepicker._hideDatepicker();
1560
+ },
1561
+ today: function () {
1562
+ $.datepicker._gotoToday(id);
1563
+ },
1564
+ selectDay: function () {
1565
+ $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
1566
+ return false;
1567
+ },
1568
+ selectMonth: function () {
1569
+ $.datepicker._selectMonthYear(id, this, "M");
1570
+ return false;
1571
+ },
1572
+ selectYear: function () {
1573
+ $.datepicker._selectMonthYear(id, this, "Y");
1574
+ return false;
1575
+ }
1576
+ };
1577
+ $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
1578
+ });
1579
+ },
1580
+
1581
+ /* Generate the HTML for the current state of the date picker. */
1582
+ _generateHTML: function(inst) {
1583
+ var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
1584
+ controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
1585
+ monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
1586
+ selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
1587
+ cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
1588
+ printDate, dRow, tbody, daySettings, otherMonth, unselectable,
1589
+ tempDate = new Date(),
1590
+ today = this._daylightSavingAdjust(
1591
+ new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
1592
+ isRTL = this._get(inst, "isRTL"),
1593
+ showButtonPanel = this._get(inst, "showButtonPanel"),
1594
+ hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
1595
+ navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
1596
+ numMonths = this._getNumberOfMonths(inst),
1597
+ showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
1598
+ stepMonths = this._get(inst, "stepMonths"),
1599
+ isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
1600
+ currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
1601
+ new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
1602
+ minDate = this._getMinMaxDate(inst, "min"),
1603
+ maxDate = this._getMinMaxDate(inst, "max"),
1604
+ drawMonth = inst.drawMonth - showCurrentAtPos,
1605
+ drawYear = inst.drawYear;
1606
+
1607
+ if (drawMonth < 0) {
1608
+ drawMonth += 12;
1609
+ drawYear--;
1610
+ }
1611
+ if (maxDate) {
1612
+ maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
1613
+ maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
1614
+ maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
1615
+ while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
1616
+ drawMonth--;
1617
+ if (drawMonth < 0) {
1618
+ drawMonth = 11;
1619
+ drawYear--;
1620
+ }
1621
+ }
1622
+ }
1623
+ inst.drawMonth = drawMonth;
1624
+ inst.drawYear = drawYear;
1625
+
1626
+ prevText = this._get(inst, "prevText");
1627
+ prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
1628
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
1629
+ this._getFormatConfig(inst)));
1630
+
1631
+ prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
1632
+ "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
1633
+ " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
1634
+ (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ prevText +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>"));
1635
+
1636
+ nextText = this._get(inst, "nextText");
1637
+ nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
1638
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
1639
+ this._getFormatConfig(inst)));
1640
+
1641
+ next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
1642
+ "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
1643
+ " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
1644
+ (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>"));
1645
+
1646
+ currentText = this._get(inst, "currentText");
1647
+ gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
1648
+ currentText = (!navigationAsDateFormat ? currentText :
1649
+ this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
1650
+
1651
+ controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
1652
+ this._get(inst, "closeText") + "</button>" : "");
1653
+
1654
+ buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
1655
+ (this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
1656
+ ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
1657
+
1658
+ firstDay = parseInt(this._get(inst, "firstDay"),10);
1659
+ firstDay = (isNaN(firstDay) ? 0 : firstDay);
1660
+
1661
+ showWeek = this._get(inst, "showWeek");
1662
+ dayNames = this._get(inst, "dayNames");
1663
+ dayNamesMin = this._get(inst, "dayNamesMin");
1664
+ monthNames = this._get(inst, "monthNames");
1665
+ monthNamesShort = this._get(inst, "monthNamesShort");
1666
+ beforeShowDay = this._get(inst, "beforeShowDay");
1667
+ showOtherMonths = this._get(inst, "showOtherMonths");
1668
+ selectOtherMonths = this._get(inst, "selectOtherMonths");
1669
+ defaultDate = this._getDefaultDate(inst);
1670
+ html = "";
1671
+ dow;
1672
+ for (row = 0; row < numMonths[0]; row++) {
1673
+ group = "";
1674
+ this.maxRows = 4;
1675
+ for (col = 0; col < numMonths[1]; col++) {
1676
+ selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
1677
+ cornerClass = " ui-corner-all";
1678
+ calender = "";
1679
+ if (isMultiMonth) {
1680
+ calender += "<div class='ui-datepicker-group";
1681
+ if (numMonths[1] > 1) {
1682
+ switch (col) {
1683
+ case 0: calender += " ui-datepicker-group-first";
1684
+ cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
1685
+ case numMonths[1]-1: calender += " ui-datepicker-group-last";
1686
+ cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
1687
+ default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
1688
+ }
1689
+ }
1690
+ calender += "'>";
1691
+ }
1692
+ calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
1693
+ (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
1694
+ (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
1695
+ this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
1696
+ row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
1697
+ "</div><table class='ui-datepicker-calendar'><thead>" +
1698
+ "<tr>";
1699
+ thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
1700
+ for (dow = 0; dow < 7; dow++) { // days of the week
1701
+ day = (dow + firstDay) % 7;
1702
+ thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
1703
+ "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
1704
+ }
1705
+ calender += thead + "</tr></thead><tbody>";
1706
+ daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
1707
+ if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
1708
+ inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
1709
+ }
1710
+ leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
1711
+ curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
1712
+ numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
1713
+ this.maxRows = numRows;
1714
+ printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
1715
+ for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
1716
+ calender += "<tr>";
1717
+ tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
1718
+ this._get(inst, "calculateWeek")(printDate) + "</td>");
1719
+ for (dow = 0; dow < 7; dow++) { // create date picker days
1720
+ daySettings = (beforeShowDay ?
1721
+ beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
1722
+ otherMonth = (printDate.getMonth() !== drawMonth);
1723
+ unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
1724
+ (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
1725
+ tbody += "<td class='" +
1726
+ ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
1727
+ (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
1728
+ ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
1729
+ (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
1730
+ // or defaultDate is current printedDate and defaultDate is selectedDate
1731
+ " " + this._dayOverClass : "") + // highlight selected day
1732
+ (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days
1733
+ (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
1734
+ (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
1735
+ (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
1736
+ ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + // cell title
1737
+ (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
1738
+ (otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
1739
+ (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
1740
+ (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
1741
+ (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
1742
+ (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
1743
+ "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
1744
+ printDate.setDate(printDate.getDate() + 1);
1745
+ printDate = this._daylightSavingAdjust(printDate);
1746
+ }
1747
+ calender += tbody + "</tr>";
1748
+ }
1749
+ drawMonth++;
1750
+ if (drawMonth > 11) {
1751
+ drawMonth = 0;
1752
+ drawYear++;
1753
+ }
1754
+ calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
1755
+ ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
1756
+ group += calender;
1757
+ }
1758
+ html += group;
1759
+ }
1760
+ html += buttonPanel;
1761
+ inst._keyEvent = false;
1762
+ return html;
1763
+ },
1764
+
1765
+ /* Generate the month and year header. */
1766
+ _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
1767
+ secondary, monthNames, monthNamesShort) {
1768
+
1769
+ var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
1770
+ changeMonth = this._get(inst, "changeMonth"),
1771
+ changeYear = this._get(inst, "changeYear"),
1772
+ showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
1773
+ html = "<div class='ui-datepicker-title'>",
1774
+ monthHtml = "";
1775
+
1776
+ // month selection
1777
+ if (secondary || !changeMonth) {
1778
+ monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
1779
+ } else {
1780
+ inMinYear = (minDate && minDate.getFullYear() === drawYear);
1781
+ inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
1782
+ monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
1783
+ for ( month = 0; month < 12; month++) {
1784
+ if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
1785
+ monthHtml += "<option value='" + month + "'" +
1786
+ (month === drawMonth ? " selected='selected'" : "") +
1787
+ ">" + monthNamesShort[month] + "</option>";
1788
+ }
1789
+ }
1790
+ monthHtml += "</select>";
1791
+ }
1792
+
1793
+ if (!showMonthAfterYear) {
1794
+ html += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");
1795
+ }
1796
+
1797
+ // year selection
1798
+ if ( !inst.yearshtml ) {
1799
+ inst.yearshtml = "";
1800
+ if (secondary || !changeYear) {
1801
+ html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
1802
+ } else {
1803
+ // determine range of years to display
1804
+ years = this._get(inst, "yearRange").split(":");
1805
+ thisYear = new Date().getFullYear();
1806
+ determineYear = function(value) {
1807
+ var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
1808
+ (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
1809
+ parseInt(value, 10)));
1810
+ return (isNaN(year) ? thisYear : year);
1811
+ };
1812
+ year = determineYear(years[0]);
1813
+ endYear = Math.max(year, determineYear(years[1] || ""));
1814
+ year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
1815
+ endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
1816
+ inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
1817
+ for (; year <= endYear; year++) {
1818
+ inst.yearshtml += "<option value='" + year + "'" +
1819
+ (year === drawYear ? " selected='selected'" : "") +
1820
+ ">" + year + "</option>";
1821
+ }
1822
+ inst.yearshtml += "</select>";
1823
+
1824
+ html += inst.yearshtml;
1825
+ inst.yearshtml = null;
1826
+ }
1827
+ }
1828
+
1829
+ html += this._get(inst, "yearSuffix");
1830
+ if (showMonthAfterYear) {
1831
+ html += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;
1832
+ }
1833
+ html += "</div>"; // Close datepicker_header
1834
+ return html;
1835
+ },
1836
+
1837
+ /* Adjust one of the date sub-fields. */
1838
+ _adjustInstDate: function(inst, offset, period) {
1839
+ var year = inst.drawYear + (period === "Y" ? offset : 0),
1840
+ month = inst.drawMonth + (period === "M" ? offset : 0),
1841
+ day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
1842
+ date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
1843
+
1844
+ inst.selectedDay = date.getDate();
1845
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
1846
+ inst.drawYear = inst.selectedYear = date.getFullYear();
1847
+ if (period === "M" || period === "Y") {
1848
+ this._notifyChange(inst);
1849
+ }
1850
+ },
1851
+
1852
+ /* Ensure a date is within any min/max bounds. */
1853
+ _restrictMinMax: function(inst, date) {
1854
+ var minDate = this._getMinMaxDate(inst, "min"),
1855
+ maxDate = this._getMinMaxDate(inst, "max"),
1856
+ newDate = (minDate && date < minDate ? minDate : date);
1857
+ return (maxDate && newDate > maxDate ? maxDate : newDate);
1858
+ },
1859
+
1860
+ /* Notify change of month/year. */
1861
+ _notifyChange: function(inst) {
1862
+ var onChange = this._get(inst, "onChangeMonthYear");
1863
+ if (onChange) {
1864
+ onChange.apply((inst.input ? inst.input[0] : null),
1865
+ [inst.selectedYear, inst.selectedMonth + 1, inst]);
1866
+ }
1867
+ },
1868
+
1869
+ /* Determine the number of months to show. */
1870
+ _getNumberOfMonths: function(inst) {
1871
+ var numMonths = this._get(inst, "numberOfMonths");
1872
+ return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
1873
+ },
1874
+
1875
+ /* Determine the current maximum date - ensure no time components are set. */
1876
+ _getMinMaxDate: function(inst, minMax) {
1877
+ return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
1878
+ },
1879
+
1880
+ /* Find the number of days in a given month. */
1881
+ _getDaysInMonth: function(year, month) {
1882
+ return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
1883
+ },
1884
+
1885
+ /* Find the day of the week of the first of a month. */
1886
+ _getFirstDayOfMonth: function(year, month) {
1887
+ return new Date(year, month, 1).getDay();
1888
+ },
1889
+
1890
+ /* Determines if we should allow a "next/prev" month display change. */
1891
+ _canAdjustMonth: function(inst, offset, curYear, curMonth) {
1892
+ var numMonths = this._getNumberOfMonths(inst),
1893
+ date = this._daylightSavingAdjust(new Date(curYear,
1894
+ curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
1895
+
1896
+ if (offset < 0) {
1897
+ date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
1898
+ }
1899
+ return this._isInRange(inst, date);
1900
+ },
1901
+
1902
+ /* Is the given date in the accepted range? */
1903
+ _isInRange: function(inst, date) {
1904
+ var yearSplit, currentYear,
1905
+ minDate = this._getMinMaxDate(inst, "min"),
1906
+ maxDate = this._getMinMaxDate(inst, "max"),
1907
+ minYear = null,
1908
+ maxYear = null,
1909
+ years = this._get(inst, "yearRange");
1910
+ if (years){
1911
+ yearSplit = years.split(":");
1912
+ currentYear = new Date().getFullYear();
1913
+ minYear = parseInt(yearSplit[0], 10);
1914
+ maxYear = parseInt(yearSplit[1], 10);
1915
+ if ( yearSplit[0].match(/[+\-].*/) ) {
1916
+ minYear += currentYear;
1917
+ }
1918
+ if ( yearSplit[1].match(/[+\-].*/) ) {
1919
+ maxYear += currentYear;
1920
+ }
1921
+ }
1922
+
1923
+ return ((!minDate || date.getTime() >= minDate.getTime()) &&
1924
+ (!maxDate || date.getTime() <= maxDate.getTime()) &&
1925
+ (!minYear || date.getFullYear() >= minYear) &&
1926
+ (!maxYear || date.getFullYear() <= maxYear));
1927
+ },
1928
+
1929
+ /* Provide the configuration settings for formatting/parsing. */
1930
+ _getFormatConfig: function(inst) {
1931
+ var shortYearCutoff = this._get(inst, "shortYearCutoff");
1932
+ shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
1933
+ new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
1934
+ return {shortYearCutoff: shortYearCutoff,
1935
+ dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
1936
+ monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
1937
+ },
1938
+
1939
+ /* Format the given date for display. */
1940
+ _formatDate: function(inst, day, month, year) {
1941
+ if (!day) {
1942
+ inst.currentDay = inst.selectedDay;
1943
+ inst.currentMonth = inst.selectedMonth;
1944
+ inst.currentYear = inst.selectedYear;
1945
+ }
1946
+ var date = (day ? (typeof day === "object" ? day :
1947
+ this._daylightSavingAdjust(new Date(year, month, day))) :
1948
+ this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
1949
+ return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
1950
+ }
1951
+ });
1952
+
1953
+ /*
1954
+ * Bind hover events for datepicker elements.
1955
+ * Done via delegate so the binding only occurs once in the lifetime of the parent div.
1956
+ * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
1957
+ */
1958
+ function bindHover(dpDiv) {
1959
+ var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
1960
+ return dpDiv.delegate(selector, "mouseout", function() {
1961
+ $(this).removeClass("ui-state-hover");
1962
+ if (this.className.indexOf("ui-datepicker-prev") !== -1) {
1963
+ $(this).removeClass("ui-datepicker-prev-hover");
1964
+ }
1965
+ if (this.className.indexOf("ui-datepicker-next") !== -1) {
1966
+ $(this).removeClass("ui-datepicker-next-hover");
1967
+ }
1968
+ })
1969
+ .delegate(selector, "mouseover", function(){
1970
+ if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
1971
+ $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
1972
+ $(this).addClass("ui-state-hover");
1973
+ if (this.className.indexOf("ui-datepicker-prev") !== -1) {
1974
+ $(this).addClass("ui-datepicker-prev-hover");
1975
+ }
1976
+ if (this.className.indexOf("ui-datepicker-next") !== -1) {
1977
+ $(this).addClass("ui-datepicker-next-hover");
1978
+ }
1979
+ }
1980
+ });
1981
+ }
1982
+
1983
+ /* jQuery extend now ignores nulls! */
1984
+ function extendRemove(target, props) {
1985
+ $.extend(target, props);
1986
+ for (var name in props) {
1987
+ if (props[name] == null) {
1988
+ target[name] = props[name];
1989
+ }
1990
+ }
1991
+ return target;
1992
+ }
1993
+
1994
+ /* Invoke the datepicker functionality.
1995
+ @param options string - a command, optionally followed by additional parameters or
1996
+ Object - settings for attaching new datepicker functionality
1997
+ @return jQuery object */
1998
+ $.fn.datepicker = function(options){
1999
+
2000
+ /* Verify an empty collection wasn't passed - Fixes #6976 */
2001
+ if ( !this.length ) {
2002
+ return this;
2003
+ }
2004
+
2005
+ /* Initialise the date picker. */
2006
+ if (!$.datepicker.initialized) {
2007
+ $(document).mousedown($.datepicker._checkExternalClick);
2008
+ $.datepicker.initialized = true;
2009
+ }
2010
+
2011
+ /* Append datepicker main container to body if not exist. */
2012
+ if ($("#"+$.datepicker._mainDivId).length === 0) {
2013
+ $("body").append($.datepicker.dpDiv);
2014
+ }
2015
+
2016
+ var otherArgs = Array.prototype.slice.call(arguments, 1);
2017
+ if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
2018
+ return $.datepicker["_" + options + "Datepicker"].
2019
+ apply($.datepicker, [this[0]].concat(otherArgs));
2020
+ }
2021
+ if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
2022
+ return $.datepicker["_" + options + "Datepicker"].
2023
+ apply($.datepicker, [this[0]].concat(otherArgs));
2024
+ }
2025
+ return this.each(function() {
2026
+ typeof options === "string" ?
2027
+ $.datepicker["_" + options + "Datepicker"].
2028
+ apply($.datepicker, [this].concat(otherArgs)) :
2029
+ $.datepicker._attachDatepicker(this, options);
2030
+ });
2031
+ };
2032
+
2033
+ $.datepicker = new Datepicker(); // singleton instance
2034
+ $.datepicker.initialized = false;
2035
+ $.datepicker.uuid = new Date().getTime();
2036
+ $.datepicker.version = "1.10.4";
2037
+
2038
+ })(jQuery);
lib/{metabox → cmb_metaboxes}/js/jquery.timePicker.min.js RENAMED
@@ -1,13 +1,13 @@
1
- /**
2
- * A time picker for jQuery.
3
- *
4
- * Dual licensed under the MIT and GPL licenses.
5
- * Copyright (c) 2009 Anders Fajerson
6
- *
7
- * @name timePicker
8
- * @author Anders Fajerson (http://perifer.se)
9
- * @see http://github.com/perifer/timePicker
10
- * @example $("#mytime").timePicker();
11
- * @example $("#mytime").timePicker({step:30, startTime:"15:00", endTime:"18:00"});
12
- */
13
  (function(a){function g(a){a.setFullYear(2001),a.setMonth(0),a.setDate(0);return a}function f(a,b){if(a){var c=a.split(b.separator),d=parseFloat(c[0]),e=parseFloat(c[1]);b.show24Hours||(d===12&&a.indexOf("AM")!==-1?d=0:d!==12&&a.indexOf("PM")!==-1&&(d+=12));var f=new Date(0,0,0,d,e,0);return g(f)}return null}function e(a,b){return typeof a=="object"?g(a):f(a,b)}function d(a){return(a<10?"0":"")+a}function c(a,b){var c=a.getHours(),e=b.show24Hours?c:(c+11)%12+1,f=a.getMinutes();return d(e)+b.separator+d(f)+(b.show24Hours?"":c<12?" AM":" PM")}function b(b,c,d,e){b.value=a(c).text(),a(b).change(),a.browser.msie||b.focus(),d.hide()}a.fn.timePicker=function(b){var c=a.extend({},a.fn.timePicker.defaults,b);return this.each(function(){a.timePicker(this,c)})},a.timePicker=function(b,c){var d=a(b)[0];return d.timePicker||(d.timePicker=new jQuery._timePicker(d,c))},a.timePicker.version="0.3",a._timePicker=function(d,h){var i=!1,j=!1,k=e(h.startTime,h),l=e(h.endTime,h),m="selected",n="li."+m;a(d).attr("autocomplete","OFF");var o=[],p=new Date(k);while(p<=l)o[o.length]=c(p,h),p=new Date(p.setMinutes(p.getMinutes()+h.step));var q=a('<div class="time-picker'+(h.show24Hours?"":" time-picker-12hours")+'"></div>'),r=a("<ul></ul>");for(var s=0;s<o.length;s++)r.append("<li>"+o[s]+"</li>");q.append(r),q.appendTo("body").hide(),q.mouseover(function(){i=!0}).mouseout(function(){i=!1}),a("li",r).mouseover(function(){j||(a(n,q).removeClass(m),a(this).addClass(m))}).mousedown(function(){i=!0}).click(function(){b(d,this,q,h),i=!1});var t=function(){if(q.is(":visible"))return!1;a("li",q).removeClass(m);var b=a(d).offset();q.css({top:b.top+d.offsetHeight,left:b.left}),q.show();var e=d.value?f(d.value,h):k,i=k.getHours()*60+k.getMinutes(),j=e.getHours()*60+e.getMinutes()-i,n=Math.round(j/h.step),o=g(new Date(0,0,0,0,n*h.step+i,0));o=k<o&&o<=l?o:k;var p=a("li:contains("+c(o,h)+")",q);p.length&&(p.addClass(m),q[0].scrollTop=p[0].offsetTop);return!0};a(d).focus(t).click(t),a(d).blur(function(){i||q.hide()});var u=a.browser.opera||a.browser.mozilla?"keypress":"keydown";a(d)[u](function(c){var e;j=!0;var f=q[0].scrollTop;switch(c.keyCode){case 38:if(t())return!1;e=a(n,r);var g=e.prev().addClass(m)[0];g?(e.removeClass(m),g.offsetTop<f&&(q[0].scrollTop=f-g.offsetHeight)):(e.removeClass(m),g=a("li:last",r).addClass(m)[0],q[0].scrollTop=g.offsetTop-g.offsetHeight);return!1;case 40:if(t())return!1;e=a(n,r);var i=e.next().addClass(m)[0];i?(e.removeClass(m),i.offsetTop+i.offsetHeight>f+q[0].offsetHeight&&(q[0].scrollTop=f+i.offsetHeight)):(e.removeClass(m),i=a("li:first",r).addClass(m)[0],q[0].scrollTop=0);return!1;case 13:if(q.is(":visible")){var k=a(n,r)[0];b(d,k,q,h)}return!1;case 27:q.hide();return!1}return!0}),a(d).keyup(function(a){j=!1}),this.getTime=function(){return f(d.value,h)},this.setTime=function(b){d.value=c(e(b,h),h),a(d).change()}},a.fn.timePicker.defaults={step:30,startTime:new Date(0,0,0,0,0,0),endTime:new Date(0,0,0,23,30,0),separator:":",show24Hours:!0}})(jQuery)
1
+ /**
2
+ * A time picker for jQuery.
3
+ *
4
+ * Dual licensed under the MIT and GPL licenses.
5
+ * Copyright (c) 2009 Anders Fajerson
6
+ *
7
+ * @name timePicker
8
+ * @author Anders Fajerson (http://perifer.se)
9
+ * @see http://github.com/perifer/timePicker
10
+ * @example $("#mytime").timePicker();
11
+ * @example $("#mytime").timePicker({step:30, startTime:"15:00", endTime:"18:00"});
12
+ */
13
  (function(a){function g(a){a.setFullYear(2001),a.setMonth(0),a.setDate(0);return a}function f(a,b){if(a){var c=a.split(b.separator),d=parseFloat(c[0]),e=parseFloat(c[1]);b.show24Hours||(d===12&&a.indexOf("AM")!==-1?d=0:d!==12&&a.indexOf("PM")!==-1&&(d+=12));var f=new Date(0,0,0,d,e,0);return g(f)}return null}function e(a,b){return typeof a=="object"?g(a):f(a,b)}function d(a){return(a<10?"0":"")+a}function c(a,b){var c=a.getHours(),e=b.show24Hours?c:(c+11)%12+1,f=a.getMinutes();return d(e)+b.separator+d(f)+(b.show24Hours?"":c<12?" AM":" PM")}function b(b,c,d,e){b.value=a(c).text(),a(b).change(),a.browser.msie||b.focus(),d.hide()}a.fn.timePicker=function(b){var c=a.extend({},a.fn.timePicker.defaults,b);return this.each(function(){a.timePicker(this,c)})},a.timePicker=function(b,c){var d=a(b)[0];return d.timePicker||(d.timePicker=new jQuery._timePicker(d,c))},a.timePicker.version="0.3",a._timePicker=function(d,h){var i=!1,j=!1,k=e(h.startTime,h),l=e(h.endTime,h),m="selected",n="li."+m;a(d).attr("autocomplete","OFF");var o=[],p=new Date(k);while(p<=l)o[o.length]=c(p,h),p=new Date(p.setMinutes(p.getMinutes()+h.step));var q=a('<div class="time-picker'+(h.show24Hours?"":" time-picker-12hours")+'"></div>'),r=a("<ul></ul>");for(var s=0;s<o.length;s++)r.append("<li>"+o[s]+"</li>");q.append(r),q.appendTo("body").hide(),q.mouseover(function(){i=!0}).mouseout(function(){i=!1}),a("li",r).mouseover(function(){j||(a(n,q).removeClass(m),a(this).addClass(m))}).mousedown(function(){i=!0}).click(function(){b(d,this,q,h),i=!1});var t=function(){if(q.is(":visible"))return!1;a("li",q).removeClass(m);var b=a(d).offset();q.css({top:b.top+d.offsetHeight,left:b.left}),q.show();var e=d.value?f(d.value,h):k,i=k.getHours()*60+k.getMinutes(),j=e.getHours()*60+e.getMinutes()-i,n=Math.round(j/h.step),o=g(new Date(0,0,0,0,n*h.step+i,0));o=k<o&&o<=l?o:k;var p=a("li:contains("+c(o,h)+")",q);p.length&&(p.addClass(m),q[0].scrollTop=p[0].offsetTop);return!0};a(d).focus(t).click(t),a(d).blur(function(){i||q.hide()});var u=a.browser.opera||a.browser.mozilla?"keypress":"keydown";a(d)[u](function(c){var e;j=!0;var f=q[0].scrollTop;switch(c.keyCode){case 38:if(t())return!1;e=a(n,r);var g=e.prev().addClass(m)[0];g?(e.removeClass(m),g.offsetTop<f&&(q[0].scrollTop=f-g.offsetHeight)):(e.removeClass(m),g=a("li:last",r).addClass(m)[0],q[0].scrollTop=g.offsetTop-g.offsetHeight);return!1;case 40:if(t())return!1;e=a(n,r);var i=e.next().addClass(m)[0];i?(e.removeClass(m),i.offsetTop+i.offsetHeight>f+q[0].offsetHeight&&(q[0].scrollTop=f+i.offsetHeight)):(e.removeClass(m),i=a("li:first",r).addClass(m)[0],q[0].scrollTop=0);return!1;case 13:if(q.is(":visible")){var k=a(n,r)[0];b(d,k,q,h)}return!1;case 27:q.hide();return!1}return!0}),a(d).keyup(function(a){j=!1}),this.getTime=function(){return f(d.value,h)},this.setTime=function(b){d.value=c(e(b,h),h),a(d).change()}},a.fn.timePicker.defaults={step:30,startTime:new Date(0,0,0,0,0,0),endTime:new Date(0,0,0,23,30,0),separator:":",show24Hours:!0}})(jQuery)
lib/cmb_metaboxes/readme.md ADDED
@@ -0,0 +1,296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Custom Metaboxes and Fields for WordPress
2
+
3
+ **Contributors**:
4
+
5
+ * WebDevStudios ( [@webdevstudios](http://twitter.com/webdevstudios ) / [webdevstudios.com](http://webdevstudios.com) )
6
+ * Justin Sternberg ( [@jtsternberg](http://twitter.com/jtsternberg ) / [webdevstudios.com](http://webdevstudios.com) )
7
+ * Jared Atchison ( [@jaredatch](http://twitter.com/jaredatch ) / [jaredatchison.com](http://jaredatchison.com/) )
8
+ * Bill Erickson ( [@billerickson](http://twitter.com/billerickson ) / [billerickson.net](http://billerickson.net/) )
9
+ * Andrew Norcross ( [@norcross](http://twitter.com/norcross ) / [andrewnorcross.com](http://andrewnorcross.com/) )
10
+
11
+ **Version**: 1.2.0
12
+ **Requires at least**: 3.5
13
+ **Tested up to**: 3.9
14
+ **License**: GPLv2
15
+
16
+ ## Description
17
+
18
+ Custom Metaboxes and Fields (CMB for short) will create metaboxes and forms with custom fields that will blow your mind.
19
+
20
+ ##### Features:
21
+
22
+ * Create metaboxes to be used on post edit screens.
23
+ * Create forms to be used on options pages.
24
+ * Create forms to handle user meta and display them on user profile add/edit pages.
25
+ * Flexible API that allows you to use CMB forms almost anywhere, even on the front-end.
26
+ * Several field types are included and are [listed below](#field-types).
27
+ * Custom API hook that allows you to create your own field types.
28
+ * There are numerous hooks and filters, allowing you to modify many aspects of the library (without editing it directly).
29
+ * Repeatable fields for most field types are supported, as well as repeatable field groups.
30
+
31
+ ##### Field Types:
32
+ 1. [`title`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#title) An arbitrary title field *
33
+ 1. [`text`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text)
34
+ 1. [`text_small`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_small)
35
+ 1. [`text_medium`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_medium)
36
+ 1. [`text_email`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_email)
37
+ 1. [`text_url`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_url)
38
+ 1. [`text_money`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_money)
39
+ 1. [`textarea`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#textarea)
40
+ 1. [`textarea_small`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#textarea_small)
41
+ 1. [`textarea_code`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#textarea_code)
42
+ 1. [`text_date`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_date) Date Picker
43
+ 1. [`text_time`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_time) Time picker
44
+ 1. [`select_timezone`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#select_timezone) Time zone dropdown
45
+ 1. [`text_date_timestamp`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_date_timestamp) Date Picker (UNIX timestamp)
46
+ 1. [`text_datetime_timestamp`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_datetime_timestamp) Test Date/Time Picker Combo (UNIX timestamp)
47
+ 1. [`text_datetime_timestamp_timezone`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#text_datetime_timestamp_timezone) Test Date/Time Picker/Time zone Combo (serialized DateTime object)
48
+ 1. [`colorpicker`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#colorpicker) Color picker
49
+ 1. [`radio`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#radio) *
50
+ 1. [`radio_inline`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#radio_inline) *
51
+ 1. [`taxonomy_radio`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#taxonomy_radio) *
52
+ 1. [`taxonomy_radio_inline`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#taxonomy_radio_inline) *
53
+ 1. [`select`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#select)
54
+ 1. [`taxonomy_select`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#taxonomy_select) *
55
+ 1. [`checkbox`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#checkbox) *
56
+ 1. [`multicheck`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#multicheck)
57
+ 1. [`taxonomy_multicheck`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#taxonomy_multicheck) *
58
+ 1. [`taxonomy_multicheck_inline`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#taxonomy_multicheck_inline)
59
+ 1. [`wysiwyg`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#wysiwyg) (TinyMCE) *
60
+ 1. [`file`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#file) Image/File upload *†
61
+ 1. [`file_list`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#file_list) Image/File list upload
62
+ 1. [`oembed`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#oembed) Converts oembed urls (instagram, twitter, youtube, etc. [oEmbed in the Codex](https://codex.wordpress.org/Embeds))
63
+ 1. [`group`](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#group) Hybrid field that supports adding other fields as a repeatable group. *
64
+ 1. [Create your own custom field type](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#Custom)
65
+
66
+ \* Not available as a repeatable field
67
+ † Use `file_list` for repeatable
68
+
69
+ [More on field types (GitHub wiki)](https://github.com/webdevstudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types)
70
+
71
+ ##### 3rd Party Resources
72
+ * [CMB Attached Posts Field](https://github.com/coreymcollins/cmb-attached-posts) from [coreymcollins](https://github.com/coreymcollins): Custom field type for attaching posts to a page.
73
+ * [CMB Field Type: Google Maps](https://github.com/mustardBees/cmb_field_map) from [mustardBees](https://github.com/mustardBees): Custom field type for Google Maps.
74
+ > The `pw_map` field stores the latitude/longitude values which you can then use to display a map in your theme.
75
+ * [CMB Field Type: Select2](https://github.com/mustardBees/cmb-field-select2) from [mustardBees](https://github.com/mustardBees): Custom field types which use the [Select2](http://ivaynberg.github.io/select2/) script:
76
+
77
+ > 1. The `pw_select field` acts much like the default select field. However, it adds typeahead-style search allowing you to quickly make a selection from a large list
78
+ > 2. The `pw_multiselect` field allows you to select multiple values with typeahead-style search. The values can be dragged and dropped to reorder
79
+ * [Taxonomy_MetaData](https://github.com/jtsternberg/Taxonomy_MetaData#to-use-taxonomy_metadata-with-custom-metaboxes-and-fields): WordPress Helper Class for saving pseudo-metadata for taxonomy terms. Includes an extended class for using CMB to generate the actual form fields.
80
+
81
+ ##### Contribution
82
+ All contributions welcome. If you would like to submit a pull request, please check out the [trunk branch](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/tree/trunk) and pull request against it.
83
+
84
+ ##### Links
85
+ * [Github project page](https://github.com/webdevstudios/Custom-Metaboxes-and-Fields-for-WordPress)
86
+ * [Documentation (GitHub wiki)](https://github.com/webdevstudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki)
87
+
88
+
89
+ ## Installation
90
+
91
+ 1. Place the CMB directory inside of your theme or plugin.
92
+ 2. Copy (and rename if desired) `example-functions.php` into a folder *above* the CMB directory OR copy the entirety of its contents to your theme's `functions.php` file.
93
+ 2. Edit to only include the fields you need and rename the functions (CMB directory should be left unedited in order to easily update the library).
94
+ 4. Profit.
95
+
96
+ ## Changelog
97
+
98
+ ### 1.2.0
99
+
100
+ **Enhancements**
101
+
102
+ * Add support for custom date/time formats. Props [@Scrent](https://github.com/Scrent). ([#506](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/506))
103
+ * Simplify `wysiwyg` escaping and allow it to be overridden via the `escape_cb` parameter. ([#491](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/491))
104
+ * Add a 'Select/Deselect all' button for the `multicheck` field type.
105
+ * Add title option for [repeatable groups](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#group). Title field takes an optional replacement hash, "{#}" that will be replaced by the row number.
106
+ * New field parameter, `show_on_cb`, allows you to conditionally display a field via a callback. ([#47](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/47))
107
+ * Unit testing (the beginning). Props [@brichards](https://github.com/brichards) and [@camdensegal](https://github.com/camdensegal).
108
+
109
+ **Bug Fixes**
110
+
111
+ * Fixed issue where remove file button wouldn't clear the url field. ([#514](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/514))
112
+ * `wysiwyg` fields now allow underscores. Fixes some wysiwyg display issues in WordPress 3.8. Props [@lswilson](https://github.com/lswilson). ([#491](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/491))
113
+ * Nonce field should only be added once per page. ([#521](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/521))
114
+ * Fix `in_array` issue when a post does not have any saved terms for a taxonomy multicheck. ([#527](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/527))
115
+ * Fixed error: 'Uninitialized string offset: 0 in cmb_Meta_Box_field.php...`. Props [@DevinWalker](https://github.com/DevinWalker). ([#539](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/539), [#549](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/549)))
116
+ * Fix missing `file` field description. ([#543](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/543), [#547](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/547))
117
+
118
+
119
+
120
+ ### 1.1.3
121
+ **Bug Fixes**
122
+
123
+ * Update `cmb_get_field_value` function as it was passing the parameters to `cmb_get_field` in the wrong order.
124
+ * Fix repeating fields not working correctly if meta key or prefix contained an integer. ([#503](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/503))
125
+
126
+ ### 1.1.2
127
+
128
+ **Bug Fixes**
129
+
130
+ * Fix issue with `cmb_Meta_Box_types.php` calling a missing method, `image_id_from_url`. ([#502](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/502))
131
+
132
+
133
+ ### 1.1.1
134
+
135
+ **Bug Fixes**
136
+
137
+ * Radio button values were not showing saved value. ([#500](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/500))
138
+
139
+ ### 1.1.0
140
+
141
+ **Enhancements**
142
+
143
+ * [Repeatable groups](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#group)
144
+ * Support for more fields to be repeatable, including oEmbed field, and date, time, and color picker fields, etc.
145
+ * Codebase has been revamped to be more modular and object-oriented.
146
+ * New filter, `"cmb_{$element}_attributes" ` for modifying an element's attributes.
147
+ * Every field now supports an `attributes` parameter that takes an array of attributes. [Read more](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types#attributes).
148
+ * Removed `cmb_std_filter` in favor of `cmb_default_filter`. **THIS IS A BREAKING CHANGE**
149
+ * Better handling of labels in sidebar. They are now placed on top of the input rather than adjacent.
150
+ * Added i18n compatibility to text_money. props [@ArchCarrier](https://github.com/ArchCarrier), ([#485](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/485))
151
+ * New helper functions: `cmb_get_field` and `cmb_get_field_value` for getting access to CMB's field object and/or value.
152
+ * New JavaScript events, `cmb_add_row` and `cmb_remove_row` for hooking in and manipulating the new row's data.
153
+ * New filter, `cmb_localized_data`, for modifiying localized data passed to the CMB JS.
154
+
155
+ **Bug Fixes**
156
+ * Resolved occasional issue where only the first character of the label/value was diplayed. props [@mustardBees](https://github.com/mustardBees), ([#486](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/486))
157
+
158
+
159
+ ### 1.0.2
160
+
161
+ **Enhancements**
162
+
163
+ * Change the way the `'cmb_validate_{$field['type']}'` filter works.
164
+ It is now passed a null value vs saved value. If null is returned, default sanitization will follow. **THIS IS A BREAKING CHANGE**. If you're already using this filter, take note.
165
+ * All field types that take an option array have been simplified to take `key => value` pairs (vs `array( 'name' => 'value', 'value' => 'key', )`). This effects the 'select', 'radio', 'radio_inline' field types. The 'multicheck' field type was already using the `key => value` format. Backwards compatibility has been maintained for those using the older style.
166
+ * Added default value option for `taxonomy_select` field type. props [@darlantc](https://github.com/darlantc), ([#473](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/473))
167
+ * Added `preview_size` parameter for `file_list` field type. props [@IgorCode](https://github.com/IgorCode), ([#471](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/471))
168
+ * Updated `file_list` images to be displayed horizontally instead of vertically. props [@IgorCode](https://github.com/IgorCode), ([#467](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/467))
169
+ * Use `get_the_terms` where possible since the data is cached.
170
+
171
+ **Bug Fixes**
172
+
173
+ * Fixed wysiwyg escaping slashes. props [@gregrickaby](https://github.com/gregrickaby), ([#465](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/465))
174
+ * Replaced `__DIR__`, as `dirname( __FILE__ )` is easier to maintain back-compatibility.
175
+ * Fixed missing table styling on new posts. props [@mustardBees](https://github.com/mustardBees), ([#438](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/438))
176
+ * Fix undeclared JS variable. [@veelen](https://github.com/veelen), ([#451](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/451))
177
+ * Fix `file_list` errors when removing all files and saving.
178
+ * Set correct `object_id` to be used later in `cmb_show_on` filter. [@lauravaq](https://github.com/lauravaq), ([#445](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/445))
179
+ * Fix sanitization recursion memeory issues.
180
+
181
+ ### 1.0.1
182
+
183
+ **Enhancements**
184
+
185
+ * Now works with option pages and site settings. ([view example in wiki](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Using-CMB-to-create-an-Admin-Theme-Options-Page))
186
+ * two filters to override the setting and getting of options, `cmb_override_option_get_$option_key` and `cmb_override_option_save_$option_key` respectively. Handy for using plugins like [WP Large Options](https://github.com/voceconnect/wp-large-options/) ([also here](http://vip.wordpress.com/plugins/wp-large-options/)).
187
+ * Improved styling on taxonomy (\*tease\*) and options pages and for new 3.8 admin UI.
188
+ * New sanitization class to sanitize data when saved.
189
+ * New callback field parameter, `sanitization_cb`, for performing your own sanitization.
190
+ * new `cmb_Meta_Box_types::esc()` method that handles escaping data for display.
191
+ * New callback field parameter, `escape_cb`, for performing your own data escaping, as well as a new filter, `'cmb_types_esc_'. $field['type']`.
192
+
193
+ **Bug Fixes**
194
+
195
+ * Fixed wysiwyg editor button padding. props [@corvannoorloos](https://github.com/corvannoorloos), ([#391](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/pull/391))
196
+ * A few php < 5.3 errors were addressed.
197
+ * Fields with quotation marks no longer break the input/textarea fields.
198
+ * metaboxes for Attachment pages now save correctly. Thanks [@nciske](https://github.com/nciske) for reporting. ([#412](https://github.com/WebDevStudios/Custom-Metaboxes-and-Fields-for-WordPress/issues/412))
199
+ * Occasionally fields wouldn't save because of the admin show_on filter.
200
+ * Smaller images loaded to the file field type will no longer be blown up larger than their dimensions.
201
+
202
+ ### 1.0.0
203
+ * Added `text_datetime_timestamp_timezone` type, a datetime combo field with an additional timezone drop down, props [@dessibelle](https://github.com/dessibelle)
204
+ * Added `select_timezone` type, a standalone time zone select dropdown. The time zone select can be used with standalone `text_datetime_timestamp` if desired. Props [@dessibelle](https://github.com/dessibelle)
205
+ * Added `text_url` type, a basic url field. Props [@dessibelle](https://github.com/dessibelle)
206
+ * Added `text_email` type, a basic email field. Props [@dessibelle](https://github.com/dessibelle)
207
+ * Added ability to display metabox fields in frontend. Default is true, but can be overriden using the `cmb_allow_frontend filter`. If set to true, an entire metabox form can be output with the `cmb_metabox_form( $meta_box, $object_id, $echo )` function. Props [@dessibelle](https://github.com/dessibelle), [@messenlehner](https://github.com/messenlehner) & [@jtsternberg](https://github.com/jtsternberg).
208
+ * Added hook `cmb_after_table` after all metabox output. Props [@wpsmith](https://github.com/wpsmith)
209
+ * `file_list` now works like a repeatable field. Add as many files as you want. Props [@coreymcollins](https://github.com/coreymcollins)
210
+ * `text`, `text_small`, `text_medium`, `text_url`, `text_email`, & `text_money` fields now all have the option to be repeatable. Props [@jtsternberg](https://github.com/jtsternberg)
211
+ * Custom metaboxes can now be added for user meta. Add them on the user add/edit screen, or in a custom user profile edit page on the front-end. Props [@tw2113](https://github.com/tw2113), [@jtsternberg](https://github.com/jtsternberg)
212
+
213
+ ### 0.9.4
214
+ * Added field "before" and "after" options for each field. Solves issue with '$' not being the desired text_money monetary symbol, props [@GaryJones](https://github.com/GaryJones)
215
+ * Added filter for 'std' default fallback value, props [@messenlehner](https://github.com/messenlehner)
216
+ * Ensure oEmbed videos fit in their respective metaboxes, props [@jtsternberg](https://github.com/jtsternberg)
217
+ * Fixed issue where an upload field with 'show_names' disabled wouldn't have the correct button label, props [@jtsternberg](https://github.com/jtsternberg)
218
+ * Better file-extension check for images, props [@GhostToast](https://github.com/GhostToast)
219
+ * New filter, `cmb_valid_img_types`, for whitelisted image file-extensions, props [@jtsternberg](https://github.com/jtsternberg)
220
+
221
+ ### 0.9.3
222
+ * Added field type and field id classes to each cmb table row, props [@jtsternberg](https://github.com/jtsternberg)
223
+
224
+ ### 0.9.2
225
+ * Added post type comparison to prevent storing null values for taxonomy selectors, props [@norcross](https://github.com/norcross)
226
+
227
+ ### 0.9.1
228
+ * Added `oEmbed` field type with ajax display, props [@jtsternberg](https://github.com/jtsternberg)
229
+
230
+ ### 0.9
231
+ * __Note: This release requires WordPress 3.3+__
232
+ * Cleaned up scripts being queued, props [@jaredatch](https://github.com/jaredatch)
233
+ * Cleaned up and reorganized jQuery, props [@GaryJones](https://github.com/GaryJones)
234
+ * Use $pagenow instead of custom $current_page, props [@jaredatch](https://github.com/jaredatch)
235
+ * Fixed CSS, removed inline styles, now all in style.css, props [@jaredatch](https://github.com/jaredatch)
236
+ * Fixed multicheck issues (issue #48), props [@jaredatch](https://github.com/jaredatch)
237
+ * Fixed jQuery UI datepicker CSS conflicting with WordPress UI elements, props [@jaredatch](https://github.com/jaredatch)
238
+ * Fixed zeros not saving in fields, props [@GaryJones](https://github.com/GaryJones)
239
+ * Fixed improper labels on radio and multicheck fields, props [@jaredatch](https://github.com/jaredatch)
240
+ * Fixed fields not rendering properly when in sidebar, props [@jaredatch](https://github.com/jaredatch)
241
+ * Fixed bug where datepicker triggers extra space after footer in Firefox (issue #14), props [@jaredatch](https://github.com/jaredatch)
242
+ * Added jQuery UI datepicker packaged with 3.3 core, props [@jaredatch](https://github.com/jaredatch)
243
+ * Added date time combo picker, props [@jaredatch](https://github.com/jaredatch)
244
+ * Added color picker, props [@jaredatch](https://github.com/jaredatch)
245
+ * Added readme.md markdown file, props [@jaredatch](https://github.com/jaredatch)
246
+
247
+ ### 0.8
248
+ * Added jQuery timepicker, props [@norcross](https://github.com/norcross)
249
+ * Added 'raw' textarea to convert special HTML entities back to characters, props [@norcross](https://github.com/norcross)
250
+ * Added missing examples on example-functions.php, props [@norcross](https://github.com/norcross)
251
+
252
+ ### 0.7
253
+ * Added the new wp_editor() function for the WYSIWYG dialog box, props [@jcpry](https://github.com/jcpry)
254
+ * Created 'cmb_show_on' filter to define your own Show On Filters, props [@billerickson](https://github.com/billerickson)
255
+ * Added page template show_on filter, props [@billerickson](https://github.com/billerickson)
256
+ * Improvements to the 'file' field type, props [@randyhoyt](https://github.com/randyhoyt)
257
+ * Allow for default values on 'radio' and 'radio_inline' field types, props [@billerickson](https://github.com/billerickson)
258
+
259
+ ### 0.6.1
260
+ * Enabled the ability to define your own custom field types (issue #28). props [@randyhoyt](https://github.com/randyhoyt)
261
+
262
+ ### 0.6
263
+ * Added the ability to limit metaboxes to certain posts by id. props [@billerickson](https://github.com/billerickson)
264
+
265
+ ### 0.5
266
+ * Fixed define to prevent notices. props [@destos](https://github.com/destos)
267
+ * Added text_date_timestap option. props [@andrewyno](https://github.com/andrewyno)
268
+ * Fixed WYSIWYG paragraph breaking/spacing bug. props [@wpsmith](https://github.com/wpsmith)
269
+ * Added taxonomy_radio and taxonomies_select options. props [@c3mdigital](https://github.com/c3mdigital)
270
+ * Fixed script causing the dashboard widgets to not be collapsible.
271
+ * Fixed various spacing and whitespace inconsistencies
272
+
273
+ ### 0.4
274
+ * Think we have a release that is mostly working. We'll say the initial release :)
275
+
276
+ ## Known Issues
277
+
278
+ * Problem inserting file url inside field for image with caption (issue #50) May be fixed, needs testing.
279
+ * `CMB_META_BOX_URL` does not define properly in WAMP/XAMP (Windows) (issue #31) May be fixed, needs testing.
280
+ * Metabox containing WYSIWYG editor cannot be moved (this is a TinyMCE issue)
281
+
282
+ ## To-do
283
+ **Enhancements**
284
+
285
+ * Fix known issues (above)
286
+ * move timepicker and datepicker jQuery inline
287
+ * support for multiple configurable timepickers/datepickers
288
+ * add ability to save fields in a single custom field
289
+ * add ability to mark fields as required
290
+ * repeatable fields (halfway there)
291
+ * look at possiblity of tabs
292
+ * look at preserving taxonomy hierarchies
293
+ * Add input attributes filter
294
+ * Always load newest version of CMB
295
+ * Helper function to easily get oembed from stored oEmbed field
296
+
lib/{metabox → cmb_metaboxes}/style.css RENAMED
@@ -1,343 +1,621 @@
1
- /**
2
- * CMB Styling
3
- */
4
- table.cmb_metabox tr:first-of-type td, table.cmb_metabox tr:first-of-type th { border:0; }
5
- table.cmb_metabox td, table.cmb_metabox th { border-top: 1px solid #E9E9E9; }
6
- table.cmb_metabox th { text-align: right; font-weight:bold;}
7
- table.cmb_metabox th label { margin-top:5px; display:block;}
8
- p.cmb_metabox_description { color: #AAA; font-style: italic; margin: 2px 0 !important;}
9
- span.cmb_metabox_description { color: #AAA; font-style: italic;}
10
- table.cmb_metabox input, table.cmb_metabox textarea { font-size:12px; padding: 5px; }
11
- table.cmb_metabox input[type=text], table.cmb_metabox textarea { width: 97%; }
12
- table.cmb_metabox textarea.cmb_textarea_code { font-family: Consolas,Monaco,monospace; line-height: 16px; }
13
- table.cmb_metabox input.cmb_text_small { width: 100px; margin-right: 15px;}
14
- table.cmb_metabox input.cmb_timepicker { width: 100px; margin-right: 15px;}
15
- table.cmb_metabox input.cmb_text_money { width: 90px; margin-right: 15px;}
16
- table.cmb_metabox input.cmb_text_medium { width: 230px; margin-right: 15px;}
17
- table.cmb_metabox input.cmb_upload_file { width: 65%; }
18
- table.cmb_metabox input.ed_button { padding: 2px 4px; }
19
- table.cmb_metabox li { font-size:12px; margin: 1px 0 5px 0; line-height: 16px; }
20
- table.cmb_metabox ul { padding-top:5px; margin: 0; }
21
- table.cmb_metabox select { font-size:12px; margin-top: 3px;}
22
- table.cmb_metabox input:focus, table.cmb_metabox textarea:focus { background: #fffff8;}
23
- .cmb_metabox_title { margin: 0 0 5px 0; padding: 5px 0 0 0; font: italic 24px/35px Georgia,"Times New Roman","Bitstream Charter",Times,serif;}
24
- .cmb_radio_inline { padding: 4px 0 0 0;}
25
- .cmb_radio_inline_option {display: inline; padding-right: 18px;}
26
- table.cmb_metabox input[type="radio"] { margin: 0 5px 0 0; padding: 0;}
27
- table.cmb_metabox input[type="checkbox"] { margin: 0 5px 0 0; padding: 0;}
28
- table.cmb_metabox .mceLayout {border:1px solid #DFDFDF !important;}
29
- table.cmb_metabox .mceIframeContainer {background:#FFF;}
30
- table.cmb_metabox .meta_mce {width:97%;}
31
- table.cmb_metabox .meta_mce textarea {width:100%;}
32
- table.cmb_metabox .cmb_media_status { margin: 10px 0 0 0;}
33
- table.cmb_metabox .cmb_media_status .img_status, table.cmb_metabox .cmb_media_status .embed_status { position: relative; }
34
- table.cmb_metabox .cmb_media_status .img_status img, table.cmb_metabox .cmb_media_status .embed_status { border:1px solid #DFDFDF; background: #FAFAFA; max-width:350px; padding: 5px; -moz-border-radius: 2px; border-radius: 2px;}
35
- table.cmb_metabox .cmb_media_status .embed_status { float: left; max-width:800px;}
36
- table.cmb_metabox .cmb_media_status .img_status .cmb_remove_file_button, table.cmb_metabox .cmb_media_status .embed_status .cmb_remove_file_button { text-indent: -9999px; background: url(images/ico-delete.png); width: 16px; height: 16px; position: absolute; top: -5px; left: -5px;}
37
- table.cmb_metabox .attach_list li { clear: both; display: inline-block; margin-bottom: 25px; width: 100%; }
38
- table.cmb_metabox .attach_list li img { float: left; margin-right: 10px; }
39
- /* Sidebar placement adjustments */
40
- .inner-sidebar table.cmb_metabox input[type=text], #side-sortables table.cmb_metabox input[type=text], table.cmb_metabox textarea { width: 95%; }
41
- .inner-sidebar table.cmb_metabox .cmb_media_status .img_status img, #side-sortables table.cmb_metabox .cmb_media_status .img_status img, .inner-sidebar table.cmb_metabox .cmb_media_status .embed_status img, #side-sortables table.cmb_metabox .cmb_media_status .embed_status img { width: 90%; }
42
- .postbox table.cmb_metabox .cmb-spinner { float: left; }
43
- /**
44
- * Color picker
45
- */
46
- table.cmb_metabox .wp-color-result, table.cmb_metabox .wp-picker-input-wrap { vertical-align: middle; }
47
- table.cmb_metabox .wp-color-result, table.cmb_metabox .wp-picker-container { margin: 0 10px 0 0; }
48
-
49
- /**
50
- * Timepicker
51
- */
52
- div.time-picker { position: absolute; height: 191px; width:6em; /* needed for IE */overflow: auto; background: #fff; border: 1px solid #aaa; z-index: 99; margin: 0;}
53
- div.time-picker-12hours { width:8em; /* needed for IE */}
54
- div.time-picker ul { list-style-type: none; margin: 0; padding: 0; }
55
- div.time-picker li { cursor: pointer; height: 10px; font: 12px/1 Helvetica, Arial, sans-serif; padding: 4px 3px; }
56
- div.time-picker li.selected { background: #0063CE; color: #fff; }
57
-
58
- /**
59
- * jQuery UI CSS Framework 1.8.16
60
- *
61
- * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
62
- * Dual licensed under the MIT or GPL Version 2 licenses.
63
- * http://jquery.org/license
64
- *
65
- * http://docs.jquery.com/UI/Theming/API
66
- */
67
- .cmb_element .ui-helper-hidden { display: none; }
68
- .cmb_element .ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
69
- .cmb_element .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
70
- .cmb_element .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
71
- .cmb_element .ui-helper-clearfix { display: inline-block; }
72
- * html .ui-helper-clearfix { height:1%; }
73
- .cmb_element .ui-helper-clearfix { display:block; }
74
- .cmb_element .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
75
- .cmb_element .ui-state-disabled { cursor: default !important; }
76
- .cmb_element .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
77
- .cmb_element .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
78
- .cmb_element .ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
79
- .cmb_element .ui-widget .ui-widget { font-size: 1em; }
80
- .cmb_element .ui-widget input, .cmb_element .ui-widget select, .cmb_element .ui-widget textarea, .cmb_element .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
81
- .cmb_element .ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
82
- .cmb_element .ui-widget-content a { color: #222222; }
83
- .cmb_element .ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
84
- .cmb_element .ui-widget-header a { color: #222222; }
85
- .cmb_element .ui-state-default, .cmb_element .ui-widget-content .ui-state-default, .cmb_element .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
86
- .cmb_element .ui-state-default a, .cmb_element .ui-state-default a:link, .cmb_element .ui-state-default a:visited { color: #555555; text-decoration: none; }
87
- .cmb_element .ui-state-hover, .cmb_element .ui-widget-content .ui-state-hover, .cmb_element .ui-widget-header .ui-state-hover, .cmb_element .ui-state-focus, .cmb_element .ui-widget-content .ui-state-focus, .cmb_element .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
88
- .cmb_element .ui-state-hover a, .cmb_element .ui-state-hover a:hover { color: #212121; text-decoration: none; }
89
- .cmb_element .ui-state-active, .cmb_element .ui-widget-content .ui-state-active, .cmb_element .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
90
- .cmb_element .ui-state-active a, .cmb_element .ui-state-active a:link, .cmb_element .ui-state-active a:visited { color: #212121; text-decoration: none; }
91
- .cmb_element .ui-widget :active { outline: none; }
92
- .cmb_element .ui-state-highlight, .cmb_element .ui-widget-content .ui-state-highlight, .cmb_element .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
93
- .cmb_element .ui-state-highlight a, .cmb_element .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
94
- .cmb_element .ui-state-error, .cmb_element .ui-widget-content .ui-state-error, .cmb_element .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
95
- .cmb_element .ui-state-error a, .cmb_element .ui-widget-content .ui-state-error a, .cmb_element .ui-widget-header .ui-state-error a { color: #cd0a0a; }
96
- .cmb_element .ui-state-error-text, .cmb_element .ui-widget-content .ui-state-error-text, .cmb_element .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
97
- .cmb_element .ui-priority-primary, .cmb_element .ui-widget-content .ui-priority-primary, .cmb_element .ui-widget-header .ui-priority-primary { font-weight: bold; }
98
- .cmb_element .ui-priority-secondary, .cmb_element .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
99
- .cmb_element .ui-state-disabled, .cmb_element .ui-widget-content .ui-state-disabled, .cmb_element .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
100
- .cmb_element .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
101
- .cmb_element .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
102
- .cmb_element .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
103
- .cmb_element .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
104
- .cmb_element .ui-state-hover .ui-icon, .cmb_element .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
105
- .cmb_element .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
106
- .cmb_element .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
107
- .cmb_element .ui-state-error .ui-icon, .cmb_element .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
108
- .cmb_element .ui-icon-carat-1-n { background-position: 0 0; }
109
- .cmb_element .ui-icon-carat-1-ne { background-position: -16px 0; }
110
- .cmb_element .ui-icon-carat-1-e { background-position: -32px 0; }
111
- .cmb_element .ui-icon-carat-1-se { background-position: -48px 0; }
112
- .cmb_element .ui-icon-carat-1-s { background-position: -64px 0; }
113
- .cmb_element .ui-icon-carat-1-sw { background-position: -80px 0; }
114
- .cmb_element .ui-icon-carat-1-w { background-position: -96px 0; }
115
- .cmb_element .ui-icon-carat-1-nw { background-position: -112px 0; }
116
- .cmb_element .ui-icon-carat-2-n-s { background-position: -128px 0; }
117
- .cmb_element .ui-icon-carat-2-e-w { background-position: -144px 0; }
118
- .cmb_element .ui-icon-triangle-1-n { background-position: 0 -16px; }
119
- .cmb_element .ui-icon-triangle-1-ne { background-position: -16px -16px; }
120
- .cmb_element .ui-icon-triangle-1-e { background-position: -32px -16px; }
121
- .cmb_element .ui-icon-triangle-1-se { background-position: -48px -16px; }
122
- .cmb_element .ui-icon-triangle-1-s { background-position: -64px -16px; }
123
- .cmb_element .ui-icon-triangle-1-sw { background-position: -80px -16px; }
124
- .cmb_element .ui-icon-triangle-1-w { background-position: -96px -16px; }
125
- .cmb_element .ui-icon-triangle-1-nw { background-position: -112px -16px; }
126
- .cmb_element .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
127
- .cmb_element .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
128
- .cmb_element .ui-icon-arrow-1-n { background-position: 0 -32px; }
129
- .cmb_element .ui-icon-arrow-1-ne { background-position: -16px -32px; }
130
- .cmb_element .ui-icon-arrow-1-e { background-position: -32px -32px; }
131
- .cmb_element .ui-icon-arrow-1-se { background-position: -48px -32px; }
132
- .cmb_element .ui-icon-arrow-1-s { background-position: -64px -32px; }
133
- .cmb_element .ui-icon-arrow-1-sw { background-position: -80px -32px; }
134
- .cmb_element .ui-icon-arrow-1-w { background-position: -96px -32px; }
135
- .cmb_element .ui-icon-arrow-1-nw { background-position: -112px -32px; }
136
- .cmb_element .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
137
- .cmb_element .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
138
- .cmb_element .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
139
- .cmb_element .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
140
- .cmb_element .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
141
- .cmb_element .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
142
- .cmb_element .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
143
- .cmb_element .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
144
- .cmb_element .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
145
- .cmb_element .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
146
- .cmb_element .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
147
- .cmb_element .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
148
- .cmb_element .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
149
- .cmb_element .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
150
- .cmb_element .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
151
- .cmb_element .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
152
- .cmb_element .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
153
- .cmb_element .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
154
- .cmb_element .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
155
- .cmb_element .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
156
- .cmb_element .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
157
- .cmb_element .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
158
- .cmb_element .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
159
- .cmb_element .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
160
- .cmb_element .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
161
- .cmb_element .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
162
- .cmb_element .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
163
- .cmb_element .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
164
- .cmb_element .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
165
- .cmb_element .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
166
- .cmb_element .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
167
- .cmb_element .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
168
- .cmb_element .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
169
- .cmb_element .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
170
- .cmb_element .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
171
- .cmb_element .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
172
- .cmb_element .ui-icon-arrow-4 { background-position: 0 -80px; }
173
- .cmb_element .ui-icon-arrow-4-diag { background-position: -16px -80px; }
174
- .cmb_element .ui-icon-extlink { background-position: -32px -80px; }
175
- .cmb_element .ui-icon-newwin { background-position: -48px -80px; }
176
- .cmb_element .ui-icon-refresh { background-position: -64px -80px; }
177
- .cmb_element .ui-icon-shuffle { background-position: -80px -80px; }
178
- .cmb_element .ui-icon-transfer-e-w { background-position: -96px -80px; }
179
- .cmb_element .ui-icon-transferthick-e-w { background-position: -112px -80px; }
180
- .cmb_element .ui-icon-folder-collapsed { background-position: 0 -96px; }
181
- .cmb_element .ui-icon-folder-open { background-position: -16px -96px; }
182
- .cmb_element .ui-icon-document { background-position: -32px -96px; }
183
- .cmb_element .ui-icon-document-b { background-position: -48px -96px; }
184
- .cmb_element .ui-icon-note { background-position: -64px -96px; }
185
- .cmb_element .ui-icon-mail-closed { background-position: -80px -96px; }
186
- .cmb_element .ui-icon-mail-open { background-position: -96px -96px; }
187
- .cmb_element .ui-icon-suitcase { background-position: -112px -96px; }
188
- .cmb_element .ui-icon-comment { background-position: -128px -96px; }
189
- .cmb_element .ui-icon-person { background-position: -144px -96px; }
190
- .cmb_element .ui-icon-print { background-position: -160px -96px; }
191
- .cmb_element .ui-icon-trash { background-position: -176px -96px; }
192
- .cmb_element .ui-icon-locked { background-position: -192px -96px; }
193
- .cmb_element .ui-icon-unlocked { background-position: -208px -96px; }
194
- .cmb_element .ui-icon-bookmark { background-position: -224px -96px; }
195
- .cmb_element .ui-icon-tag { background-position: -240px -96px; }
196
- .cmb_element .ui-icon-home { background-position: 0 -112px; }
197
- .cmb_element .ui-icon-flag { background-position: -16px -112px; }
198
- .cmb_element .ui-icon-calendar { background-position: -32px -112px; }
199
- .cmb_element .ui-icon-cart { background-position: -48px -112px; }
200
- .cmb_element .ui-icon-pencil { background-position: -64px -112px; }
201
- .cmb_element .ui-icon-clock { background-position: -80px -112px; }
202
- .cmb_element .ui-icon-disk { background-position: -96px -112px; }
203
- .cmb_element .ui-icon-calculator { background-position: -112px -112px; }
204
- .cmb_element .ui-icon-zoomin { background-position: -128px -112px; }
205
- .cmb_element .ui-icon-zoomout { background-position: -144px -112px; }
206
- .cmb_element .ui-icon-search { background-position: -160px -112px; }
207
- .cmb_element .ui-icon-wrench { background-position: -176px -112px; }
208
- .cmb_element .ui-icon-gear { background-position: -192px -112px; }
209
- .cmb_element .ui-icon-heart { background-position: -208px -112px; }
210
- .cmb_element .ui-icon-star { background-position: -224px -112px; }
211
- .cmb_element .ui-icon-link { background-position: -240px -112px; }
212
- .cmb_element .ui-icon-cancel { background-position: 0 -128px; }
213
- .cmb_element .ui-icon-plus { background-position: -16px -128px; }
214
- .cmb_element .ui-icon-plusthick { background-position: -32px -128px; }
215
- .cmb_element .ui-icon-minus { background-position: -48px -128px; }
216
- .cmb_element .ui-icon-minusthick { background-position: -64px -128px; }
217
- .cmb_element .ui-icon-close { background-position: -80px -128px; }
218
- .cmb_element .ui-icon-closethick { background-position: -96px -128px; }
219
- .cmb_element .ui-icon-key { background-position: -112px -128px; }
220
- .cmb_element .ui-icon-lightbulb { background-position: -128px -128px; }
221
- .cmb_element .ui-icon-scissors { background-position: -144px -128px; }
222
- .cmb_element .ui-icon-clipboard { background-position: -160px -128px; }
223
- .cmb_element .ui-icon-copy { background-position: -176px -128px; }
224
- .cmb_element .ui-icon-contact { background-position: -192px -128px; }
225
- .cmb_element .ui-icon-image { background-position: -208px -128px; }
226
- .cmb_element .ui-icon-video { background-position: -224px -128px; }
227
- .cmb_element .ui-icon-script { background-position: -240px -128px; }
228
- .cmb_element .ui-icon-alert { background-position: 0 -144px; }
229
- .cmb_element .ui-icon-info { background-position: -16px -144px; }
230
- .cmb_element .ui-icon-notice { background-position: -32px -144px; }
231
- .cmb_element .ui-icon-help { background-position: -48px -144px; }
232
- .cmb_element .ui-icon-check { background-position: -64px -144px; }
233
- .cmb_element .ui-icon-bullet { background-position: -80px -144px; }
234
- .cmb_element .ui-icon-radio-off { background-position: -96px -144px; }
235
- .cmb_element .ui-icon-radio-on { background-position: -112px -144px; }
236
- .cmb_element .ui-icon-pin-w { background-position: -128px -144px; }
237
- .cmb_element .ui-icon-pin-s { background-position: -144px -144px; }
238
- .cmb_element .ui-icon-play { background-position: 0 -160px; }
239
- .cmb_element .ui-icon-pause { background-position: -16px -160px; }
240
- .cmb_element .ui-icon-seek-next { background-position: -32px -160px; }
241
- .cmb_element .ui-icon-seek-prev { background-position: -48px -160px; }
242
- .cmb_element .ui-icon-seek-end { background-position: -64px -160px; }
243
- .cmb_element .ui-icon-seek-start { background-position: -80px -160px; }
244
- .cmb_element .ui-icon-seek-first { background-position: -80px -160px; }
245
- .cmb_element .ui-icon-stop { background-position: -96px -160px; }
246
- .cmb_element .ui-icon-eject { background-position: -112px -160px; }
247
- .cmb_element .ui-icon-volume-off { background-position: -128px -160px; }
248
- .cmb_element .ui-icon-volume-on { background-position: -144px -160px; }
249
- .cmb_element .ui-icon-power { background-position: 0 -176px; }
250
- .cmb_element .ui-icon-signal-diag { background-position: -16px -176px; }
251
- .cmb_element .ui-icon-signal { background-position: -32px -176px; }
252
- .cmb_element .ui-icon-battery-0 { background-position: -48px -176px; }
253
- .cmb_element .ui-icon-battery-1 { background-position: -64px -176px; }
254
- .cmb_element .ui-icon-battery-2 { background-position: -80px -176px; }
255
- .cmb_element .ui-icon-battery-3 { background-position: -96px -176px; }
256
- .cmb_element .ui-icon-circle-plus { background-position: 0 -192px; }
257
- .cmb_element .ui-icon-circle-minus { background-position: -16px -192px; }
258
- .cmb_element .ui-icon-circle-close { background-position: -32px -192px; }
259
- .cmb_element .ui-icon-circle-triangle-e { background-position: -48px -192px; }
260
- .cmb_element .ui-icon-circle-triangle-s { background-position: -64px -192px; }
261
- .cmb_element .ui-icon-circle-triangle-w { background-position: -80px -192px; }
262
- .cmb_element .ui-icon-circle-triangle-n { background-position: -96px -192px; }
263
- .cmb_element .ui-icon-circle-arrow-e { background-position: -112px -192px; }
264
- .cmb_element .ui-icon-circle-arrow-s { background-position: -128px -192px; }
265
- .cmb_element .ui-icon-circle-arrow-w { background-position: -144px -192px; }
266
- .cmb_element .ui-icon-circle-arrow-n { background-position: -160px -192px; }
267
- .cmb_element .ui-icon-circle-zoomin { background-position: -176px -192px; }
268
- .cmb_element .ui-icon-circle-zoomout { background-position: -192px -192px; }
269
- .cmb_element .ui-icon-circle-check { background-position: -208px -192px; }
270
- .cmb_element .ui-icon-circlesmall-plus { background-position: 0 -208px; }
271
- .cmb_element .ui-icon-circlesmall-minus { background-position: -16px -208px; }
272
- .cmb_element .ui-icon-circlesmall-close { background-position: -32px -208px; }
273
- .cmb_element .ui-icon-squaresmall-plus { background-position: -48px -208px; }
274
- .cmb_element .ui-icon-squaresmall-minus { background-position: -64px -208px; }
275
- .cmb_element .ui-icon-squaresmall-close { background-position: -80px -208px; }
276
- .cmb_element .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
277
- .cmb_element .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
278
- .cmb_element .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
279
- .cmb_element .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
280
- .cmb_element .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
281
- .cmb_element .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
282
- .cmb_element .ui-corner-all, .cmb_element .ui-corner-top, .cmb_element .ui-corner-left, .cmb_element .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; }
283
- .cmb_element .ui-corner-all, .cmb_element .ui-corner-top, .cmb_element .ui-corner-right, .cmb_element .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; }
284
- .cmb_element .ui-corner-all, .cmb_element .ui-corner-bottom, .cmb_element .ui-corner-left, .cmb_element .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
285
- .cmb_element .ui-corner-all, .cmb_element .ui-corner-bottom, .cmb_element .ui-corner-right, .cmb_element .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
286
- .cmb_element .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
287
- .cmb_element .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
288
- .cmb_element .ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
289
- .cmb_element .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
290
- .cmb_element .ui-datepicker .ui-datepicker-prev, .cmb_element .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
291
- .cmb_element .ui-datepicker .ui-datepicker-prev-hover, .cmb_element .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
292
- .cmb_element .ui-datepicker .ui-datepicker-prev { left:2px; }
293
- .cmb_element .ui-datepicker .ui-datepicker-next { right:2px; }
294
- .cmb_element .ui-datepicker .ui-datepicker-prev-hover { left:1px; }
295
- .cmb_element .ui-datepicker .ui-datepicker-next-hover { right:1px; }
296
- .cmb_element .ui-datepicker .ui-datepicker-prev span, .cmb_element .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; margin-left: 5px; margin-top: 5px; }
297
- .cmb_element .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
298
- .cmb_element .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
299
- .cmb_element .ui-datepicker select.ui-datepicker-month-year {width: 100%;}
300
- .cmb_element .ui-datepicker select.ui-datepicker-month,
301
- .cmb_element .ui-datepicker select.ui-datepicker-year { width: 49%;}
302
- .cmb_element .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
303
- .cmb_element .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
304
- .cmb_element .ui-datepicker td { border: 0; padding: 1px; }
305
- .cmb_element .ui-datepicker td span, .cmb_element .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
306
- .cmb_element .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
307
- .cmb_element .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
308
- .cmb_element .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
309
- .cmb_element .ui-datepicker.ui-datepicker-multi { width:auto; }
310
- .cmb_element .ui-datepicker-multi .ui-datepicker-group { float:left; }
311
- .cmb_element .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
312
- .cmb_element .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
313
- .cmb_element .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
314
- .cmb_element .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
315
- .cmb_element .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
316
- .cmb_element .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
317
- .cmb_element .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
318
- .cmb_element .ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
319
- .cmb_element .ui-datepicker-rtl { direction: rtl; }
320
- .cmb_element .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
321
- .cmb_element .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
322
- .cmb_element .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
323
- .cmb_element .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
324
- .cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
325
- .cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
326
- .cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
327
- .cmb_element .ui-datepicker-rtl .ui-datepicker-group { float:right; }
328
- .cmb_element .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
329
- .cmb_element .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
330
- .cmb_element .ui-datepicker-cover {
331
- display: none; /*sorry for IE5*/
332
- display/**/: block; /*sorry for IE5*/
333
- position: absolute; /*must have*/
334
- z-index: -1; /*must have*/
335
- filter: mask(); /*must have*/
336
- top: -4px; /*must have*/
337
- left: -4px; /*must have*/
338
- width: 200px; /*must have*/
339
- height: 200px; /*must have*/
340
- }
341
- #ui-datepicker-div { z-index: 999999 !important; }
342
- .ui-datepicker-prev:hover,.ui-datepicker-next:hover { cursor: pointer !important; }
343
- .wp-picker-holder { position: absolute; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * CMB Styling
3
+ */
4
+
5
+ table.cmb_metabox {
6
+ clear: both;
7
+ }
8
+
9
+ table.cmb_metabox > tr:first-of-type > td,
10
+ table.cmb_metabox > tr:first-of-type > th,
11
+ table.cmb_metabox tbody > tr:first-of-type > td,
12
+ table.cmb_metabox tbody > tr:first-of-type > th,
13
+ .post-php table.cmb_metabox .cmb-nested-table td,
14
+ .post-new-php table.cmb_metabox .cmb-nested-table td,
15
+ .post-php table.cmb_metabox .repeatable-group th,
16
+ .post-new-php table.cmb_metabox .repeatable-group th,
17
+ .post-php table.cmb_metabox .repeatable-group:first-of-type,
18
+ .post-new-php table.cmb_metabox .repeatable-group:first-of-type {
19
+ border: 0;
20
+ }
21
+
22
+ .post-php table.cmb_metabox td,
23
+ .post-new-php table.cmb_metabox td,
24
+ .post-php table.cmb_metabox th,
25
+ .post-new-php table.cmb_metabox th,
26
+ .post-php table.cmb_metabox .repeatable-group,
27
+ .post-new-php table.cmb_metabox .repeatable-group,
28
+ .post-php table.cmb_metabox .repeatable-group,
29
+ .post-new-php table.cmb_metabox .repeatable-group {
30
+ border-top: 1px solid #E9E9E9;
31
+ }
32
+
33
+ .repeatable-group th {
34
+ padding: 5px;
35
+ }
36
+
37
+ .repeatable-group .shift-rows {
38
+ text-decoration: none;
39
+ margin-right: 5px;
40
+ font-size: 1.2em;
41
+ }
42
+
43
+ .repeatable-group .cmb_upload_button {
44
+ float: right;
45
+ }
46
+
47
+ #poststuff .repeatable-group h2 {
48
+ margin: 0;
49
+ }
50
+
51
+ .cmb-group-title h4 {
52
+ font-size: 1.2em;
53
+ font-weight: 500;
54
+ border-bottom: 1px solid #ddd;
55
+ }
56
+
57
+ .post-php table.cmb_metabox th, .post-new-php table.cmb_metabox th {
58
+ text-align: right;
59
+ font-weight:bold;
60
+ }
61
+
62
+ .post-php table.cmb_metabox table th, .post-new-php table.cmb_metabox table th {
63
+ text-align: left;
64
+ }
65
+
66
+ table.cmb_metabox th label {
67
+ margin-top:5px;
68
+ display:block
69
+ }
70
+
71
+ p.cmb_metabox_description {
72
+ color: #AAA;
73
+ font-style: italic;
74
+ margin: 2px 0 !important
75
+ }
76
+
77
+ span.cmb_metabox_description {
78
+ color: #AAA;
79
+ font-style: italic
80
+ }
81
+
82
+ table.cmb_metabox input, table.cmb_metabox textarea {
83
+ font-size:14px;
84
+ padding: 5px;
85
+ }
86
+
87
+ table.cmb_metabox input[type=text], table.cmb_metabox textarea {
88
+ width: 97%;
89
+ }
90
+
91
+ table.cmb_metabox textarea.cmb_textarea_code {
92
+ font-family: Consolas,Monaco,monospace;
93
+ line-height: 16px;
94
+ }
95
+
96
+ table.cmb_metabox input.cmb_text_small {
97
+ width: 100px;
98
+ margin-right: 15px
99
+ }
100
+
101
+ table.cmb_metabox input.cmb_timepicker {
102
+ width: 100px;
103
+ margin-right: 15px
104
+ }
105
+
106
+ table.cmb_metabox input.cmb_text_money {
107
+ width: 90px;
108
+ margin-right: 15px
109
+ }
110
+
111
+ table.cmb_metabox input.cmb_text_medium {
112
+ width: 230px;
113
+ margin-right: 15px
114
+ }
115
+
116
+ table.cmb_metabox input.cmb_upload_file {
117
+ width: 65%;
118
+ }
119
+
120
+ table.cmb_metabox input.ed_button{
121
+ padding:2px 4px
122
+ }
123
+
124
+ table.cmb_metabox li {
125
+ font-size:14px;
126
+ margin: 1px 0 5px 0;
127
+ line-height: 16px;
128
+ }
129
+
130
+ table.cmb_metabox ul {
131
+ padding-top:5px;
132
+ margin: 0;
133
+ }
134
+
135
+ table.cmb_metabox select {
136
+ font-size:14px;
137
+ margin-top: 3px
138
+ }
139
+
140
+ table.cmb_metabox input:focus, table.cmb_metabox textarea:focus {
141
+ background: #fffff8
142
+ }
143
+
144
+ .cmb_metabox_title {
145
+ margin: 0 0 5px 0;
146
+ padding: 5px 0 0 0;
147
+ }
148
+
149
+ .edit-tags-php .cmb_metabox_title, .profile-php .cmb_metabox_title, .user-edit-php .cmb_metabox_title {
150
+ margin-left: -10px;
151
+ }
152
+
153
+ .cmb-inline ul {
154
+ padding: 4px 0 0 0
155
+ }
156
+
157
+ .cmb-inline li {display: inline-block;
158
+ padding-right: 18px
159
+ }
160
+
161
+ table.cmb_metabox input[type="radio"] {
162
+ margin: 0 5px 0 0;
163
+ padding: 0
164
+ }
165
+
166
+ table.cmb_metabox input[type="checkbox"] {
167
+ margin: 0 5px 0 0;
168
+ padding: 0
169
+ }
170
+
171
+ table.cmb_metabox .mceLayout {
172
+ border:1px solid #DFDFDF !important
173
+ }
174
+
175
+ table.cmb_metabox .mceIframeContainer {
176
+ background:#FFF
177
+ }
178
+
179
+ table.cmb_metabox .meta_mce {
180
+ width:97%
181
+ }
182
+
183
+ table.cmb_metabox .meta_mce textarea {
184
+ width:100%
185
+ }
186
+
187
+ table.cmb_metabox .cmb_media_status {
188
+ margin: 10px 0 0 0
189
+ }
190
+
191
+ table.cmb_metabox .cmb_media_status .img_status {
192
+ clear: none;
193
+ float: left;
194
+ display: inline-block;
195
+ margin-right: 10px;
196
+ width: auto;
197
+ }
198
+
199
+ table.cmb_metabox .cmb-type-file_list .cmb_media_status .img_status {
200
+ clear: none;
201
+ float: left;
202
+ margin-right: 10px;
203
+ width: auto;
204
+ }
205
+
206
+ table.cmb_metabox .cmb_media_status .img_status, table.cmb_metabox .cmb_media_status .embed_status {
207
+ position: relative;
208
+ }
209
+
210
+ table.cmb_metabox .cmb_media_status .img_status img, table.cmb_metabox .cmb_media_status .embed_status {
211
+ border:1px solid #DFDFDF;
212
+ background: #FAFAFA;
213
+ max-width:350px;
214
+ padding: 5px;
215
+ -moz-border-radius: 2px;
216
+ border-radius: 2px
217
+ }
218
+
219
+ table.cmb_metabox .cmb_media_status .embed_status {
220
+ float: left;
221
+ max-width:800px
222
+ }
223
+
224
+ table.cmb_metabox .cmb_media_status .img_status .cmb_remove_file_button, table.cmb_metabox .cmb_media_status .embed_status .cmb_remove_file_button {
225
+ text-indent: -9999px;
226
+ background: url(images/ico-delete.png);
227
+ width: 16px;
228
+ height: 16px;
229
+ position: absolute;
230
+ top: -5px;
231
+ left: -5px
232
+ }
233
+
234
+ table.cmb_metabox .attach_list li {
235
+ clear: both;
236
+ display: inline-block;
237
+ margin-bottom: 25px;
238
+ width: 100%;
239
+ }
240
+
241
+ table.cmb_metabox .attach_list li img {
242
+ float: left;
243
+ margin-right: 10px;
244
+ }
245
+
246
+ /**
247
+ * Sidebar placement adjustments
248
+ */
249
+ .inner-sidebar table.cmb_metabox input[type=text],
250
+ #side-sortables table.cmb_metabox input[type=text],
251
+ table.cmb_metabox textarea {
252
+ width: 95%;
253
+ }
254
+
255
+ .inner-sidebar table.cmb_metabox .cmb_media_status .img_status img,
256
+ #side-sortables table.cmb_metabox .cmb_media_status .img_status img,
257
+ .inner-sidebar table.cmb_metabox .cmb_media_status .embed_status img,
258
+ #side-sortables table.cmb_metabox .cmb_media_status .embed_status img {
259
+ width: 90%;
260
+ }
261
+
262
+ .inner-sidebar table.cmb_metabox label,
263
+ #side-sortables table.cmb_metabox label {
264
+ display: block;
265
+ font-weight: bold;
266
+ padding: 0 0 5px;
267
+ }
268
+
269
+ .inner-sidebar table.cmb_metabox .cmb_list label,
270
+ #side-sortables table.cmb_metabox .cmb_list label {
271
+ display: inline;
272
+ font-weight: normal;
273
+ }
274
+
275
+ .inner-sidebar table.cmb_metabox .cmb_metabox_description,
276
+ #side-sortables table.cmb_metabox .cmb_metabox_description {
277
+ display: block;
278
+ padding: 7px 0 0;
279
+ }
280
+
281
+ .inner-sidebar table.cmb_metabox .cmb_metabox_title,
282
+ #side-sortables table.cmb_metabox .cmb_metabox_title {
283
+ font-size: 1.2em;
284
+ font-style: italic;
285
+ }
286
+
287
+ .postbox table.cmb_metabox .cmb-spinner {
288
+ float: left;
289
+ }
290
+
291
+ /**
292
+ * Color picker
293
+ */
294
+ table.cmb_metabox .wp-color-result, table.cmb_metabox .wp-picker-input-wrap {
295
+ vertical-align: middle;
296
+ }
297
+
298
+ table.cmb_metabox .wp-color-result, table.cmb_metabox .wp-picker-container {
299
+ margin: 0 10px 0 0;
300
+ }
301
+
302
+
303
+ /**
304
+ * Timepicker
305
+ */
306
+ div.time-picker {
307
+ position: absolute;
308
+ height: 191px;
309
+ width:6em;
310
+ /* needed for IE */overflow: auto;
311
+ background: #fff;
312
+ border: 1px solid #aaa;
313
+ z-index: 99;
314
+ margin: 0
315
+ }
316
+
317
+ div.time-picker-12hours {
318
+ width:8em; /* needed for IE */
319
+ }
320
+
321
+ div.time-picker ul {
322
+ list-style-type: none;
323
+ margin: 0;
324
+ padding: 0;
325
+ }
326
+
327
+ div.time-picker li {
328
+ cursor: pointer;
329
+ height: 10px;
330
+ font: 14px/1 Helvetica, Arial, sans-serif;
331
+ padding: 4px 3px;
332
+ }
333
+
334
+ div.time-picker li.selected {
335
+ background: #0063CE;
336
+ color: #fff;
337
+ }
338
+
339
+ /**
340
+ * jQuery UI CSS Framework 1.8.16
341
+ *
342
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
343
+ * Dual licensed under the MIT or GPL Version 2 licenses.
344
+ * http://jquery.org/license
345
+ *
346
+ * http://docs.jquery.com/UI/Theming/API
347
+ */
348
+ .cmb_element .ui-helper-hidden { display: none; }
349
+ .cmb_element .ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
350
+ .cmb_element .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
351
+ .cmb_element .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
352
+ .cmb_element .ui-helper-clearfix { display: inline-block; }
353
+ * html .ui-helper-clearfix { height:1%; }
354
+ .cmb_element .ui-helper-clearfix { display:block; }
355
+ .cmb_element .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
356
+ .cmb_element .ui-state-disabled { cursor: default !important; }
357
+ .cmb_element .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
358
+ .cmb_element .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
359
+ .cmb_element .ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
360
+ .cmb_element .ui-widget .ui-widget { font-size: 1em; }
361
+ .cmb_element .ui-widget input, .cmb_element .ui-widget select, .cmb_element .ui-widget textarea, .cmb_element .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
362
+ .cmb_element .ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
363
+ .cmb_element .ui-widget-content a { color: #222222; }
364
+ .cmb_element .ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
365
+ .cmb_element .ui-widget-header a { color: #222222; }
366
+ .cmb_element .ui-state-default, .cmb_element .ui-widget-content .ui-state-default, .cmb_element .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
367
+ .cmb_element .ui-state-default a, .cmb_element .ui-state-default a:link, .cmb_element .ui-state-default a:visited { color: #555555; text-decoration: none; }
368
+ .cmb_element .ui-state-hover, .cmb_element .ui-widget-content .ui-state-hover, .cmb_element .ui-widget-header .ui-state-hover, .cmb_element .ui-state-focus, .cmb_element .ui-widget-content .ui-state-focus, .cmb_element .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
369
+ .cmb_element .ui-state-hover a, .cmb_element .ui-state-hover a:hover { color: #212121; text-decoration: none; }
370
+ .cmb_element .ui-state-active, .cmb_element .ui-widget-content .ui-state-active, .cmb_element .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
371
+ .cmb_element .ui-state-active a, .cmb_element .ui-state-active a:link, .cmb_element .ui-state-active a:visited { color: #212121; text-decoration: none; }
372
+ .cmb_element .ui-widget :active { outline: none; }
373
+ .cmb_element .ui-state-highlight, .cmb_element .ui-widget-content .ui-state-highlight, .cmb_element .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
374
+ .cmb_element .ui-state-highlight a, .cmb_element .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
375
+ .cmb_element .ui-state-error, .cmb_element .ui-widget-content .ui-state-error, .cmb_element .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
376
+ .cmb_element .ui-state-error a, .cmb_element .ui-widget-content .ui-state-error a, .cmb_element .ui-widget-header .ui-state-error a { color: #cd0a0a; }
377
+ .cmb_element .ui-state-error-text, .cmb_element .ui-widget-content .ui-state-error-text, .cmb_element .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
378
+ .cmb_element .ui-priority-primary, .cmb_element .ui-widget-content .ui-priority-primary, .cmb_element .ui-widget-header .ui-priority-primary { font-weight: bold; }
379
+ .cmb_element .ui-priority-secondary, .cmb_element .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
380
+ .cmb_element .ui-state-disabled, .cmb_element .ui-widget-content .ui-state-disabled, .cmb_element .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
381
+ .cmb_element .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
382
+ .cmb_element .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
383
+ .cmb_element .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
384
+ .cmb_element .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
385
+ .cmb_element .ui-state-hover .ui-icon, .cmb_element .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
386
+ .cmb_element .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
387
+ .cmb_element .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
388
+ .cmb_element .ui-state-error .ui-icon, .cmb_element .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
389
+ .cmb_element .ui-icon-carat-1-n { background-position: 0 0; }
390
+ .cmb_element .ui-icon-carat-1-ne { background-position: -16px 0; }
391
+ .cmb_element .ui-icon-carat-1-e { background-position: -32px 0; }
392
+ .cmb_element .ui-icon-carat-1-se { background-position: -48px 0; }
393
+ .cmb_element .ui-icon-carat-1-s { background-position: -64px 0; }
394
+ .cmb_element .ui-icon-carat-1-sw { background-position: -80px 0; }
395
+ .cmb_element .ui-icon-carat-1-w { background-position: -96px 0; }
396
+ .cmb_element .ui-icon-carat-1-nw { background-position: -112px 0; }
397
+ .cmb_element .ui-icon-carat-2-n-s { background-position: -128px 0; }
398
+ .cmb_element .ui-icon-carat-2-e-w { background-position: -144px 0; }
399
+ .cmb_element .ui-icon-triangle-1-n { background-position: 0 -16px; }
400
+ .cmb_element .ui-icon-triangle-1-ne { background-position: -16px -16px; }
401
+ .cmb_element .ui-icon-triangle-1-e { background-position: -32px -16px; }
402
+ .cmb_element .ui-icon-triangle-1-se { background-position: -48px -16px; }
403
+ .cmb_element .ui-icon-triangle-1-s { background-position: -64px -16px; }
404
+ .cmb_element .ui-icon-triangle-1-sw { background-position: -80px -16px; }
405
+ .cmb_element .ui-icon-triangle-1-w { background-position: -96px -16px; }
406
+ .cmb_element .ui-icon-triangle-1-nw { background-position: -112px -16px; }
407
+ .cmb_element .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
408
+ .cmb_element .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
409
+ .cmb_element .ui-icon-arrow-1-n { background-position: 0 -32px; }
410
+ .cmb_element .ui-icon-arrow-1-ne { background-position: -16px -32px; }
411
+ .cmb_element .ui-icon-arrow-1-e { background-position: -32px -32px; }
412
+ .cmb_element .ui-icon-arrow-1-se { background-position: -48px -32px; }
413
+ .cmb_element .ui-icon-arrow-1-s { background-position: -64px -32px; }
414
+ .cmb_element .ui-icon-arrow-1-sw { background-position: -80px -32px; }
415
+ .cmb_element .ui-icon-arrow-1-w { background-position: -96px -32px; }
416
+ .cmb_element .ui-icon-arrow-1-nw { background-position: -112px -32px; }
417
+ .cmb_element .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
418
+ .cmb_element .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
419
+ .cmb_element .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
420
+ .cmb_element .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
421
+ .cmb_element .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
422
+ .cmb_element .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
423
+ .cmb_element .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
424
+ .cmb_element .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
425
+ .cmb_element .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
426
+ .cmb_element .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
427
+ .cmb_element .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
428
+ .cmb_element .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
429
+ .cmb_element .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
430
+ .cmb_element .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
431
+ .cmb_element .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
432
+ .cmb_element .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
433
+ .cmb_element .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
434
+ .cmb_element .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
435
+ .cmb_element .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
436
+ .cmb_element .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
437
+ .cmb_element .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
438
+ .cmb_element .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
439
+ .cmb_element .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
440
+ .cmb_element .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
441
+ .cmb_element .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
442
+ .cmb_element .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
443
+ .cmb_element .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
444
+ .cmb_element .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
445
+ .cmb_element .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
446
+ .cmb_element .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
447
+ .cmb_element .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
448
+ .cmb_element .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
449
+ .cmb_element .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
450
+ .cmb_element .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
451
+ .cmb_element .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
452
+ .cmb_element .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
453
+ .cmb_element .ui-icon-arrow-4 { background-position: 0 -80px; }
454
+ .cmb_element .ui-icon-arrow-4-diag { background-position: -16px -80px; }
455
+ .cmb_element .ui-icon-extlink { background-position: -32px -80px; }
456
+ .cmb_element .ui-icon-newwin { background-position: -48px -80px; }
457
+ .cmb_element .ui-icon-refresh { background-position: -64px -80px; }
458
+ .cmb_element .ui-icon-shuffle { background-position: -80px -80px; }
459
+ .cmb_element .ui-icon-transfer-e-w { background-position: -96px -80px; }
460
+ .cmb_element .ui-icon-transferthick-e-w { background-position: -112px -80px; }
461
+ .cmb_element .ui-icon-folder-collapsed { background-position: 0 -96px; }
462
+ .cmb_element .ui-icon-folder-open { background-position: -16px -96px; }
463
+ .cmb_element .ui-icon-document { background-position: -32px -96px; }
464
+ .cmb_element .ui-icon-document-b { background-position: -48px -96px; }
465
+ .cmb_element .ui-icon-note { background-position: -64px -96px; }
466
+ .cmb_element .ui-icon-mail-closed { background-position: -80px -96px; }
467
+ .cmb_element .ui-icon-mail-open { background-position: -96px -96px; }
468
+ .cmb_element .ui-icon-suitcase { background-position: -112px -96px; }
469
+ .cmb_element .ui-icon-comment { background-position: -128px -96px; }
470
+ .cmb_element .ui-icon-person { background-position: -144px -96px; }
471
+ .cmb_element .ui-icon-print { background-position: -160px -96px; }
472
+ .cmb_element .ui-icon-trash { background-position: -176px -96px; }
473
+ .cmb_element .ui-icon-locked { background-position: -192px -96px; }
474
+ .cmb_element .ui-icon-unlocked { background-position: -208px -96px; }
475
+ .cmb_element .ui-icon-bookmark { background-position: -224px -96px; }
476
+ .cmb_element .ui-icon-tag { background-position: -240px -96px; }
477
+ .cmb_element .ui-icon-home { background-position: 0 -112px; }
478
+ .cmb_element .ui-icon-flag { background-position: -16px -112px; }
479
+ .cmb_element .ui-icon-calendar { background-position: -32px -112px; }
480
+ .cmb_element .ui-icon-cart { background-position: -48px -112px; }
481
+ .cmb_element .ui-icon-pencil { background-position: -64px -112px; }
482
+ .cmb_element .ui-icon-clock { background-position: -80px -112px; }
483
+ .cmb_element .ui-icon-disk { background-position: -96px -112px; }
484
+ .cmb_element .ui-icon-calculator { background-position: -112px -112px; }
485
+ .cmb_element .ui-icon-zoomin { background-position: -128px -112px; }
486
+ .cmb_element .ui-icon-zoomout { background-position: -144px -112px; }
487
+ .cmb_element .ui-icon-search { background-position: -160px -112px; }
488
+ .cmb_element .ui-icon-wrench { background-position: -176px -112px; }
489
+ .cmb_element .ui-icon-gear { background-position: -192px -112px; }
490
+ .cmb_element .ui-icon-heart { background-position: -208px -112px; }
491
+ .cmb_element .ui-icon-star { background-position: -224px -112px; }
492
+ .cmb_element .ui-icon-link { background-position: -240px -112px; }
493
+ .cmb_element .ui-icon-cancel { background-position: 0 -128px; }
494
+ .cmb_element .ui-icon-plus { background-position: -16px -128px; }
495
+ .cmb_element .ui-icon-plusthick { background-position: -32px -128px; }
496
+ .cmb_element .ui-icon-minus { background-position: -48px -128px; }
497
+ .cmb_element .ui-icon-minusthick { background-position: -64px -128px; }
498
+ .cmb_element .ui-icon-close { background-position: -80px -128px; }
499
+ .cmb_element .ui-icon-closethick { background-position: -96px -128px; }
500
+ .cmb_element .ui-icon-key { background-position: -112px -128px; }
501
+ .cmb_element .ui-icon-lightbulb { background-position: -128px -128px; }
502
+ .cmb_element .ui-icon-scissors { background-position: -144px -128px; }
503
+ .cmb_element .ui-icon-clipboard { background-position: -160px -128px; }
504
+ .cmb_element .ui-icon-copy { background-position: -176px -128px; }
505
+ .cmb_element .ui-icon-contact { background-position: -192px -128px; }
506
+ .cmb_element .ui-icon-image { background-position: -208px -128px; }
507
+ .cmb_element .ui-icon-video { background-position: -224px -128px; }
508
+ .cmb_element .ui-icon-script { background-position: -240px -128px; }
509
+ .cmb_element .ui-icon-alert { background-position: 0 -144px; }
510
+ .cmb_element .ui-icon-info { background-position: -16px -144px; }
511
+ .cmb_element .ui-icon-notice { background-position: -32px -144px; }
512
+ .cmb_element .ui-icon-help { background-position: -48px -144px; }
513
+ .cmb_element .ui-icon-check { background-position: -64px -144px; }
514
+ .cmb_element .ui-icon-bullet { background-position: -80px -144px; }
515
+ .cmb_element .ui-icon-radio-off { background-position: -96px -144px; }
516
+ .cmb_element .ui-icon-radio-on { background-position: -112px -144px; }
517
+ .cmb_element .ui-icon-pin-w { background-position: -128px -144px; }
518
+ .cmb_element .ui-icon-pin-s { background-position: -144px -144px; }
519
+ .cmb_element .ui-icon-play { background-position: 0 -160px; }
520
+ .cmb_element .ui-icon-pause { background-position: -16px -160px; }
521
+ .cmb_element .ui-icon-seek-next { background-position: -32px -160px; }
522
+ .cmb_element .ui-icon-seek-prev { background-position: -48px -160px; }
523
+ .cmb_element .ui-icon-seek-end { background-position: -64px -160px; }
524
+ .cmb_element .ui-icon-seek-start { background-position: -80px -160px; }
525
+ .cmb_element .ui-icon-seek-first { background-position: -80px -160px; }
526
+ .cmb_element .ui-icon-stop { background-position: -96px -160px; }
527
+ .cmb_element .ui-icon-eject { background-position: -112px -160px; }
528
+ .cmb_element .ui-icon-volume-off { background-position: -128px -160px; }
529
+ .cmb_element .ui-icon-volume-on { background-position: -144px -160px; }
530
+ .cmb_element .ui-icon-power { background-position: 0 -176px; }
531
+ .cmb_element .ui-icon-signal-diag { background-position: -16px -176px; }
532
+ .cmb_element .ui-icon-signal { background-position: -32px -176px; }
533
+ .cmb_element .ui-icon-battery-0 { background-position: -48px -176px; }
534
+ .cmb_element .ui-icon-battery-1 { background-position: -64px -176px; }
535
+ .cmb_element .ui-icon-battery-2 { background-position: -80px -176px; }
536
+ .cmb_element .ui-icon-battery-3 { background-position: -96px -176px; }
537
+ .cmb_element .ui-icon-circle-plus { background-position: 0 -192px; }
538
+ .cmb_element .ui-icon-circle-minus { background-position: -16px -192px; }
539
+ .cmb_element .ui-icon-circle-close { background-position: -32px -192px; }
540
+ .cmb_element .ui-icon-circle-triangle-e { background-position: -48px -192px; }
541
+ .cmb_element .ui-icon-circle-triangle-s { background-position: -64px -192px; }
542
+ .cmb_element .ui-icon-circle-triangle-w { background-position: -80px -192px; }
543
+ .cmb_element .ui-icon-circle-triangle-n { background-position: -96px -192px; }
544
+ .cmb_element .ui-icon-circle-arrow-e { background-position: -112px -192px; }
545
+ .cmb_element .ui-icon-circle-arrow-s { background-position: -128px -192px; }
546
+ .cmb_element .ui-icon-circle-arrow-w { background-position: -144px -192px; }
547
+ .cmb_element .ui-icon-circle-arrow-n { background-position: -160px -192px; }
548
+ .cmb_element .ui-icon-circle-zoomin { background-position: -176px -192px; }
549
+ .cmb_element .ui-icon-circle-zoomout { background-position: -192px -192px; }
550
+ .cmb_element .ui-icon-circle-check { background-position: -208px -192px; }
551
+ .cmb_element .ui-icon-circlesmall-plus { background-position: 0 -208px; }
552
+ .cmb_element .ui-icon-circlesmall-minus { background-position: -16px -208px; }
553
+ .cmb_element .ui-icon-circlesmall-close { background-position: -32px -208px; }
554
+ .cmb_element .ui-icon-squaresmall-plus { background-position: -48px -208px; }
555
+ .cmb_element .ui-icon-squaresmall-minus { background-position: -64px -208px; }
556
+ .cmb_element .ui-icon-squaresmall-close { background-position: -80px -208px; }
557
+ .cmb_element .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
558
+ .cmb_element .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
559
+ .cmb_element .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
560
+ .cmb_element .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
561
+ .cmb_element .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
562
+ .cmb_element .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
563
+ .cmb_element .ui-corner-all, .cmb_element .ui-corner-top, .cmb_element .ui-corner-left, .cmb_element .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; }
564
+ .cmb_element .ui-corner-all, .cmb_element .ui-corner-top, .cmb_element .ui-corner-right, .cmb_element .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; }
565
+ .cmb_element .ui-corner-all, .cmb_element .ui-corner-bottom, .cmb_element .ui-corner-left, .cmb_element .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
566
+ .cmb_element .ui-corner-all, .cmb_element .ui-corner-bottom, .cmb_element .ui-corner-right, .cmb_element .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
567
+ .cmb_element .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
568
+ .cmb_element .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
569
+ .cmb_element .ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
570
+ .cmb_element .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
571
+ .cmb_element .ui-datepicker .ui-datepicker-prev, .cmb_element .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
572
+ .cmb_element .ui-datepicker .ui-datepicker-prev-hover, .cmb_element .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
573
+ .cmb_element .ui-datepicker .ui-datepicker-prev { left:2px; }
574
+ .cmb_element .ui-datepicker .ui-datepicker-next { right:2px; }
575
+ .cmb_element .ui-datepicker .ui-datepicker-prev-hover { left:1px; }
576
+ .cmb_element .ui-datepicker .ui-datepicker-next-hover { right:1px; }
577
+ .cmb_element .ui-datepicker .ui-datepicker-prev span, .cmb_element .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
578
+ .cmb_element .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
579
+ .cmb_element .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
580
+ .cmb_element .ui-datepicker select.ui-datepicker-month-year {width: 100%;}
581
+ .cmb_element .ui-datepicker select.ui-datepicker-month,
582
+ .cmb_element .ui-datepicker select.ui-datepicker-year { width: 49%;}
583
+ .cmb_element .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
584
+ .cmb_element .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
585
+ .cmb_element .ui-datepicker td { border: 0; padding: 1px; }
586
+ .cmb_element .ui-datepicker td span, .cmb_element .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
587
+ .cmb_element .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
588
+ .cmb_element .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
589
+ .cmb_element .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
590
+ .cmb_element .ui-datepicker.ui-datepicker-multi { width:auto; }
591
+ .cmb_element .ui-datepicker-multi .ui-datepicker-group { float:left; }
592
+ .cmb_element .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
593
+ .cmb_element .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
594
+ .cmb_element .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
595
+ .cmb_element .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
596
+ .cmb_element .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
597
+ .cmb_element .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
598
+ .cmb_element .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
599
+ .cmb_element .ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
600
+ .cmb_element .ui-datepicker-rtl { direction: rtl; }
601
+ .cmb_element .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
602
+ .cmb_element .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
603
+ .cmb_element .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
604
+ .cmb_element .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
605
+ .cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
606
+ .cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
607
+ .cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
608
+ .cmb_element .ui-datepicker-rtl .ui-datepicker-group { float:right; }
609
+ .cmb_element .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
610
+ .cmb_element .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
611
+ .cmb_element .ui-datepicker-cover {
612
+ display: none; /*sorry for IE5*/
613
+ display/**/: block; /*sorry for IE5*/
614
+ position: absolute; /*must have*/
615
+ z-index: -1; /*must have*/
616
+ filter: mask(); /*must have*/
617
+ top: -4px; /*must have*/
618
+ left: -4px; /*must have*/
619
+ width: 200px; /*must have*/
620
+ height: 200px; /*must have*/
621
+ }
lib/cmb_metaboxes/style.min.css ADDED
@@ -0,0 +1 @@
 
1
+ table.cmb_metabox{clear:both}.post-new-php table.cmb_metabox .cmb-nested-table td,.post-new-php table.cmb_metabox .repeatable-group th,.post-new-php table.cmb_metabox .repeatable-group:first-of-type,.post-php table.cmb_metabox .cmb-nested-table td,.post-php table.cmb_metabox .repeatable-group th,.post-php table.cmb_metabox .repeatable-group:first-of-type,table.cmb_metabox tbody>tr:first-of-type>td,table.cmb_metabox tbody>tr:first-of-type>th,table.cmb_metabox>tr:first-of-type>td,table.cmb_metabox>tr:first-of-type>th{border:0}.post-new-php table.cmb_metabox .repeatable-group,.post-new-php table.cmb_metabox td,.post-new-php table.cmb_metabox th,.post-php table.cmb_metabox .repeatable-group,.post-php table.cmb_metabox td,.post-php table.cmb_metabox th{border-top:1px solid #E9E9E9}.repeatable-group th{padding:5px}.repeatable-group .shift-rows{text-decoration:none;margin-right:5px;font-size:1.2em}.repeatable-group .cmb_upload_button{float:right}#poststuff .repeatable-group h2{margin:0}.cmb-group-title h4{font-size:1.2em;font-weight:500;border-bottom:1px solid #ddd}.post-new-php table.cmb_metabox th,.post-php table.cmb_metabox th{text-align:right;font-weight:700}.post-new-php table.cmb_metabox table th,.post-php table.cmb_metabox table th{text-align:left}table.cmb_metabox th label{margin-top:5px;display:block}p.cmb_metabox_description{color:#AAA;font-style:italic;margin:2px 0!important}span.cmb_metabox_description{color:#AAA;font-style:italic}table.cmb_metabox input,table.cmb_metabox textarea{font-size:14px;padding:5px}table.cmb_metabox input[type=text],table.cmb_metabox textarea{width:97%}table.cmb_metabox textarea.cmb_textarea_code{font-family:Consolas,Monaco,monospace;line-height:16px}table.cmb_metabox input.cmb_text_small,table.cmb_metabox input.cmb_timepicker{width:100px;margin-right:15px}table.cmb_metabox input.cmb_text_money{width:90px;margin-right:15px}table.cmb_metabox input.cmb_text_medium{width:230px;margin-right:15px}table.cmb_metabox input.cmb_upload_file{width:65%}table.cmb_metabox input.ed_button{padding:2px 4px}table.cmb_metabox li{font-size:14px;margin:1px 0 5px;line-height:16px}table.cmb_metabox ul{padding-top:5px;margin:0}table.cmb_metabox select{font-size:14px;margin-top:3px}table.cmb_metabox input:focus,table.cmb_metabox textarea:focus{background:#fffff8}.cmb_metabox_title{margin:0 0 5px;padding:5px 0 0}.edit-tags-php .cmb_metabox_title,.profile-php .cmb_metabox_title,.user-edit-php .cmb_metabox_title{margin-left:-10px}.cmb-inline ul{padding:4px 0 0}.cmb-inline li{display:inline-block;padding-right:18px}table.cmb_metabox input[type=checkbox],table.cmb_metabox input[type=radio]{margin:0 5px 0 0;padding:0}table.cmb_metabox .mceLayout{border:1px solid #DFDFDF!important}table.cmb_metabox .mceIframeContainer{background:#FFF}table.cmb_metabox .meta_mce{width:97%}table.cmb_metabox .meta_mce textarea{width:100%}table.cmb_metabox .cmb_media_status{margin:10px 0 0}table.cmb_metabox .cmb_media_status .img_status{clear:none;float:left;display:inline-block;margin-right:10px;width:auto}table.cmb_metabox .cmb-type-file_list .cmb_media_status .img_status{clear:none;float:left;margin-right:10px;width:auto}table.cmb_metabox .cmb_media_status .embed_status,table.cmb_metabox .cmb_media_status .img_status{position:relative}table.cmb_metabox .cmb_media_status .embed_status,table.cmb_metabox .cmb_media_status .img_status img{border:1px solid #DFDFDF;background:#FAFAFA;max-width:350px;padding:5px;-moz-border-radius:2px;border-radius:2px}table.cmb_metabox .cmb_media_status .embed_status{float:left;max-width:800px}table.cmb_metabox .cmb_media_status .embed_status .cmb_remove_file_button,table.cmb_metabox .cmb_media_status .img_status .cmb_remove_file_button{text-indent:-9999px;background:url(images/ico-delete.png);width:16px;height:16px;position:absolute;top:-5px;left:-5px}table.cmb_metabox .attach_list li{clear:both;display:inline-block;margin-bottom:25px;width:100%}table.cmb_metabox .attach_list li img{float:left;margin-right:10px}#side-sortables table.cmb_metabox input[type=text],.inner-sidebar table.cmb_metabox input[type=text],table.cmb_metabox textarea{width:95%}#side-sortables table.cmb_metabox .cmb_media_status .embed_status img,#side-sortables table.cmb_metabox .cmb_media_status .img_status img,.inner-sidebar table.cmb_metabox .cmb_media_status .embed_status img,.inner-sidebar table.cmb_metabox .cmb_media_status .img_status img{width:90%}#side-sortables table.cmb_metabox label,.inner-sidebar table.cmb_metabox label{display:block;font-weight:700;padding:0 0 5px}#side-sortables table.cmb_metabox .cmb_list label,.inner-sidebar table.cmb_metabox .cmb_list label{display:inline;font-weight:400}#side-sortables table.cmb_metabox .cmb_metabox_description,.inner-sidebar table.cmb_metabox .cmb_metabox_description{display:block;padding:7px 0 0}#side-sortables table.cmb_metabox .cmb_metabox_title,.inner-sidebar table.cmb_metabox .cmb_metabox_title{font-size:1.2em;font-style:italic}.postbox table.cmb_metabox .cmb-spinner{float:left}table.cmb_metabox .wp-color-result,table.cmb_metabox .wp-picker-input-wrap{vertical-align:middle}table.cmb_metabox .wp-color-result,table.cmb_metabox .wp-picker-container{margin:0 10px 0 0}div.time-picker{position:absolute;height:191px;width:6em;overflow:auto;background:#fff;border:1px solid #aaa;z-index:99;margin:0}div.time-picker-12hours{width:8em}div.time-picker ul{list-style-type:none;margin:0;padding:0}div.time-picker li{cursor:pointer;height:10px;font:14px/1 Helvetica,Arial,sans-serif;padding:4px 3px}div.time-picker li.selected{background:#0063CE;color:#fff}.cmb_element .ui-helper-hidden{display:none}.cmb_element .ui-helper-hidden-accessible{position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.cmb_element .ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.cmb_element .ui-helper-clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden}* html .ui-helper-clearfix{height:1%}.cmb_element .ui-helper-clearfix{display:block}.cmb_element .ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.cmb_element .ui-state-disabled{cursor:default!important}.cmb_element .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.cmb_element .ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.cmb_element .ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.cmb_element .ui-widget .ui-widget{font-size:1em}.cmb_element .ui-widget button,.cmb_element .ui-widget input,.cmb_element .ui-widget select,.cmb_element .ui-widget textarea{font-family:Verdana,Arial,sans-serif;font-size:1em}.cmb_element .ui-widget-content{border:1px solid #aaa;background:#fff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x;color:#222}.cmb_element .ui-widget-content a{color:#222}.cmb_element .ui-widget-header{border:1px solid #aaa;background:#ccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x;color:#222;font-weight:700}.cmb_element .ui-widget-header a{color:#222}.cmb_element .ui-state-default,.cmb_element .ui-widget-content .ui-state-default,.cmb_element .ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;font-weight:400;color:#555}.cmb_element .ui-state-default a,.cmb_element .ui-state-default a:link,.cmb_element .ui-state-default a:visited{color:#555;text-decoration:none}.cmb_element .ui-state-focus,.cmb_element .ui-state-hover,.cmb_element .ui-widget-content .ui-state-focus,.cmb_element .ui-widget-content .ui-state-hover,.cmb_element .ui-widget-header .ui-state-focus,.cmb_element .ui-widget-header .ui-state-hover{border:1px solid #999;background:#dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x;font-weight:400;color:#212121}.cmb_element .ui-state-hover a,.cmb_element .ui-state-hover a:hover{color:#212121;text-decoration:none}.cmb_element .ui-state-active,.cmb_element .ui-widget-content .ui-state-active,.cmb_element .ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:400;color:#212121}.cmb_element .ui-state-active a,.cmb_element .ui-state-active a:link,.cmb_element .ui-state-active a:visited{color:#212121;text-decoration:none}.cmb_element .ui-widget :active{outline:0}.cmb_element .ui-state-highlight,.cmb_element .ui-widget-content .ui-state-highlight,.cmb_element .ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x;color:#363636}.cmb_element .ui-state-highlight a,.cmb_element .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.cmb_element .ui-state-error,.cmb_element .ui-widget-content .ui-state-error,.cmb_element .ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;color:#cd0a0a}.cmb_element .ui-state-error a,.cmb_element .ui-state-error-text,.cmb_element .ui-widget-content .ui-state-error a,.cmb_element .ui-widget-content .ui-state-error-text,.cmb_element .ui-widget-header .ui-state-error a,.cmb_element .ui-widget-header .ui-state-error-text{color:#cd0a0a}.cmb_element .ui-priority-primary,.cmb_element .ui-widget-content .ui-priority-primary,.cmb_element .ui-widget-header .ui-priority-primary{font-weight:700}.cmb_element .ui-priority-secondary,.cmb_element .ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:400}.cmb_element .ui-state-disabled,.cmb_element .ui-widget-content .ui-state-disabled,.cmb_element .ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.cmb_element .ui-icon{width:16px;height:16px;background-image:url(images/ui-icons_222222_256x240.png)}.cmb_element .ui-widget-content .ui-icon,.cmb_element .ui-widget-header .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.cmb_element .ui-state-default .ui-icon{background-image:url(images/ui-icons_888888_256x240.png)}.cmb_element .ui-state-active .ui-icon,.cmb_element .ui-state-focus .ui-icon,.cmb_element .ui-state-hover .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.cmb_element .ui-state-highlight .ui-icon{background-image:url(images/ui-icons_2e83ff_256x240.png)}.cmb_element .ui-state-error .ui-icon,.cmb_element .ui-state-error-text .ui-icon{background-image:url(images/ui-icons_cd0a0a_256x240.png)}.cmb_element .ui-icon-carat-1-n{background-position:0 0}.cmb_element .ui-icon-carat-1-ne{background-position:-16px 0}.cmb_element .ui-icon-carat-1-e{background-position:-32px 0}.cmb_element .ui-icon-carat-1-se{background-position:-48px 0}.cmb_element .ui-icon-carat-1-s{background-position:-64px 0}.cmb_element .ui-icon-carat-1-sw{background-position:-80px 0}.cmb_element .ui-icon-carat-1-w{background-position:-96px 0}.cmb_element .ui-icon-carat-1-nw{background-position:-112px 0}.cmb_element .ui-icon-carat-2-n-s{background-position:-128px 0}.cmb_element .ui-icon-carat-2-e-w{background-position:-144px 0}.cmb_element .ui-icon-triangle-1-n{background-position:0 -16px}.cmb_element .ui-icon-triangle-1-ne{background-position:-16px -16px}.cmb_element .ui-icon-triangle-1-e{background-position:-32px -16px}.cmb_element .ui-icon-triangle-1-se{background-position:-48px -16px}.cmb_element .ui-icon-triangle-1-s{background-position:-64px -16px}.cmb_element .ui-icon-triangle-1-sw{background-position:-80px -16px}.cmb_element .ui-icon-triangle-1-w{background-position:-96px -16px}.cmb_element .ui-icon-triangle-1-nw{background-position:-112px -16px}.cmb_element .ui-icon-triangle-2-n-s{background-position:-128px -16px}.cmb_element .ui-icon-triangle-2-e-w{background-position:-144px -16px}.cmb_element .ui-icon-arrow-1-n{background-position:0 -32px}.cmb_element .ui-icon-arrow-1-ne{background-position:-16px -32px}.cmb_element .ui-icon-arrow-1-e{background-position:-32px -32px}.cmb_element .ui-icon-arrow-1-se{background-position:-48px -32px}.cmb_element .ui-icon-arrow-1-s{background-position:-64px -32px}.cmb_element .ui-icon-arrow-1-sw{background-position:-80px -32px}.cmb_element .ui-icon-arrow-1-w{background-position:-96px -32px}.cmb_element .ui-icon-arrow-1-nw{background-position:-112px -32px}.cmb_element .ui-icon-arrow-2-n-s{background-position:-128px -32px}.cmb_element .ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.cmb_element .ui-icon-arrow-2-e-w{background-position:-160px -32px}.cmb_element .ui-icon-arrow-2-se-nw{background-position:-176px -32px}.cmb_element .ui-icon-arrowstop-1-n{background-position:-192px -32px}.cmb_element .ui-icon-arrowstop-1-e{background-position:-208px -32px}.cmb_element .ui-icon-arrowstop-1-s{background-position:-224px -32px}.cmb_element .ui-icon-arrowstop-1-w{background-position:-240px -32px}.cmb_element .ui-icon-arrowthick-1-n{background-position:0 -48px}.cmb_element .ui-icon-arrowthick-1-ne{background-position:-16px -48px}.cmb_element .ui-icon-arrowthick-1-e{background-position:-32px -48px}.cmb_element .ui-icon-arrowthick-1-se{background-position:-48px -48px}.cmb_element .ui-icon-arrowthick-1-s{background-position:-64px -48px}.cmb_element .ui-icon-arrowthick-1-sw{background-position:-80px -48px}.cmb_element .ui-icon-arrowthick-1-w{background-position:-96px -48px}.cmb_element .ui-icon-arrowthick-1-nw{background-position:-112px -48px}.cmb_element .ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.cmb_element .ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.cmb_element .ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.cmb_element .ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.cmb_element .ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.cmb_element .ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.cmb_element .ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.cmb_element .ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.cmb_element .ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.cmb_element .ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.cmb_element .ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.cmb_element .ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.cmb_element .ui-icon-arrowreturn-1-w{background-position:-64px -64px}.cmb_element .ui-icon-arrowreturn-1-n{background-position:-80px -64px}.cmb_element .ui-icon-arrowreturn-1-e{background-position:-96px -64px}.cmb_element .ui-icon-arrowreturn-1-s{background-position:-112px -64px}.cmb_element .ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.cmb_element .ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.cmb_element .ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.cmb_element .ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.cmb_element .ui-icon-arrow-4{background-position:0 -80px}.cmb_element .ui-icon-arrow-4-diag{background-position:-16px -80px}.cmb_element .ui-icon-extlink{background-position:-32px -80px}.cmb_element .ui-icon-newwin{background-position:-48px -80px}.cmb_element .ui-icon-refresh{background-position:-64px -80px}.cmb_element .ui-icon-shuffle{background-position:-80px -80px}.cmb_element .ui-icon-transfer-e-w{background-position:-96px -80px}.cmb_element .ui-icon-transferthick-e-w{background-position:-112px -80px}.cmb_element .ui-icon-folder-collapsed{background-position:0 -96px}.cmb_element .ui-icon-folder-open{background-position:-16px -96px}.cmb_element .ui-icon-document{background-position:-32px -96px}.cmb_element .ui-icon-document-b{background-position:-48px -96px}.cmb_element .ui-icon-note{background-position:-64px -96px}.cmb_element .ui-icon-mail-closed{background-position:-80px -96px}.cmb_element .ui-icon-mail-open{background-position:-96px -96px}.cmb_element .ui-icon-suitcase{background-position:-112px -96px}.cmb_element .ui-icon-comment{background-position:-128px -96px}.cmb_element .ui-icon-person{background-position:-144px -96px}.cmb_element .ui-icon-print{background-position:-160px -96px}.cmb_element .ui-icon-trash{background-position:-176px -96px}.cmb_element .ui-icon-locked{background-position:-192px -96px}.cmb_element .ui-icon-unlocked{background-position:-208px -96px}.cmb_element .ui-icon-bookmark{background-position:-224px -96px}.cmb_element .ui-icon-tag{background-position:-240px -96px}.cmb_element .ui-icon-home{background-position:0 -112px}.cmb_element .ui-icon-flag{background-position:-16px -112px}.cmb_element .ui-icon-calendar{background-position:-32px -112px}.cmb_element .ui-icon-cart{background-position:-48px -112px}.cmb_element .ui-icon-pencil{background-position:-64px -112px}.cmb_element .ui-icon-clock{background-position:-80px -112px}.cmb_element .ui-icon-disk{background-position:-96px -112px}.cmb_element .ui-icon-calculator{background-position:-112px -112px}.cmb_element .ui-icon-zoomin{background-position:-128px -112px}.cmb_element .ui-icon-zoomout{background-position:-144px -112px}.cmb_element .ui-icon-search{background-position:-160px -112px}.cmb_element .ui-icon-wrench{background-position:-176px -112px}.cmb_element .ui-icon-gear{background-position:-192px -112px}.cmb_element .ui-icon-heart{background-position:-208px -112px}.cmb_element .ui-icon-star{background-position:-224px -112px}.cmb_element .ui-icon-link{background-position:-240px -112px}.cmb_element .ui-icon-cancel{background-position:0 -128px}.cmb_element .ui-icon-plus{background-position:-16px -128px}.cmb_element .ui-icon-plusthick{background-position:-32px -128px}.cmb_element .ui-icon-minus{background-position:-48px -128px}.cmb_element .ui-icon-minusthick{background-position:-64px -128px}.cmb_element .ui-icon-close{background-position:-80px -128px}.cmb_element .ui-icon-closethick{background-position:-96px -128px}.cmb_element .ui-icon-key{background-position:-112px -128px}.cmb_element .ui-icon-lightbulb{background-position:-128px -128px}.cmb_element .ui-icon-scissors{background-position:-144px -128px}.cmb_element .ui-icon-clipboard{background-position:-160px -128px}.cmb_element .ui-icon-copy{background-position:-176px -128px}.cmb_element .ui-icon-contact{background-position:-192px -128px}.cmb_element .ui-icon-image{background-position:-208px -128px}.cmb_element .ui-icon-video{background-position:-224px -128px}.cmb_element .ui-icon-script{background-position:-240px -128px}.cmb_element .ui-icon-alert{background-position:0 -144px}.cmb_element .ui-icon-info{background-position:-16px -144px}.cmb_element .ui-icon-notice{background-position:-32px -144px}.cmb_element .ui-icon-help{background-position:-48px -144px}.cmb_element .ui-icon-check{background-position:-64px -144px}.cmb_element .ui-icon-bullet{background-position:-80px -144px}.cmb_element .ui-icon-radio-off{background-position:-96px -144px}.cmb_element .ui-icon-radio-on{background-position:-112px -144px}.cmb_element .ui-icon-pin-w{background-position:-128px -144px}.cmb_element .ui-icon-pin-s{background-position:-144px -144px}.cmb_element .ui-icon-play{background-position:0 -160px}.cmb_element .ui-icon-pause{background-position:-16px -160px}.cmb_element .ui-icon-seek-next{background-position:-32px -160px}.cmb_element .ui-icon-seek-prev{background-position:-48px -160px}.cmb_element .ui-icon-seek-end{background-position:-64px -160px}.cmb_element .ui-icon-seek-first,.cmb_element .ui-icon-seek-start{background-position:-80px -160px}.cmb_element .ui-icon-stop{background-position:-96px -160px}.cmb_element .ui-icon-eject{background-position:-112px -160px}.cmb_element .ui-icon-volume-off{background-position:-128px -160px}.cmb_element .ui-icon-volume-on{background-position:-144px -160px}.cmb_element .ui-icon-power{background-position:0 -176px}.cmb_element .ui-icon-signal-diag{background-position:-16px -176px}.cmb_element .ui-icon-signal{background-position:-32px -176px}.cmb_element .ui-icon-battery-0{background-position:-48px -176px}.cmb_element .ui-icon-battery-1{background-position:-64px -176px}.cmb_element .ui-icon-battery-2{background-position:-80px -176px}.cmb_element .ui-icon-battery-3{background-position:-96px -176px}.cmb_element .ui-icon-circle-plus{background-position:0 -192px}.cmb_element .ui-icon-circle-minus{background-position:-16px -192px}.cmb_element .ui-icon-circle-close{background-position:-32px -192px}.cmb_element .ui-icon-circle-triangle-e{background-position:-48px -192px}.cmb_element .ui-icon-circle-triangle-s{background-position:-64px -192px}.cmb_element .ui-icon-circle-triangle-w{background-position:-80px -192px}.cmb_element .ui-icon-circle-triangle-n{background-position:-96px -192px}.cmb_element .ui-icon-circle-arrow-e{background-position:-112px -192px}.cmb_element .ui-icon-circle-arrow-s{background-position:-128px -192px}.cmb_element .ui-icon-circle-arrow-w{background-position:-144px -192px}.cmb_element .ui-icon-circle-arrow-n{background-position:-160px -192px}.cmb_element .ui-icon-circle-zoomin{background-position:-176px -192px}.cmb_element .ui-icon-circle-zoomout{background-position:-192px -192px}.cmb_element .ui-icon-circle-check{background-position:-208px -192px}.cmb_element .ui-icon-circlesmall-plus{background-position:0 -208px}.cmb_element .ui-icon-circlesmall-minus{background-position:-16px -208px}.cmb_element .ui-icon-circlesmall-close{background-position:-32px -208px}.cmb_element .ui-icon-squaresmall-plus{background-position:-48px -208px}.cmb_element .ui-icon-squaresmall-minus{background-position:-64px -208px}.cmb_element .ui-icon-squaresmall-close{background-position:-80px -208px}.cmb_element .ui-icon-grip-dotted-vertical{background-position:0 -224px}.cmb_element .ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.cmb_element .ui-icon-grip-solid-vertical{background-position:-32px -224px}.cmb_element .ui-icon-grip-solid-horizontal{background-position:-48px -224px}.cmb_element .ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.cmb_element .ui-icon-grip-diagonal-se{background-position:-80px -224px}.cmb_element .ui-corner-all,.cmb_element .ui-corner-left,.cmb_element .ui-corner-tl,.cmb_element .ui-corner-top{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;-khtml-border-top-left-radius:4px;border-top-left-radius:4px}.cmb_element .ui-corner-all,.cmb_element .ui-corner-right,.cmb_element .ui-corner-top,.cmb_element .ui-corner-tr{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;-khtml-border-top-right-radius:4px;border-top-right-radius:4px}.cmb_element .ui-corner-all,.cmb_element .ui-corner-bl,.cmb_element .ui-corner-bottom,.cmb_element .ui-corner-left{-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;-khtml-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.cmb_element .ui-corner-all,.cmb_element .ui-corner-bottom,.cmb_element .ui-corner-br,.cmb_element .ui-corner-right{-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;-khtml-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.cmb_element .ui-widget-overlay{background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.cmb_element .ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);-moz-border-radius:8px;-khtml-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}.cmb_element .ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.cmb_element .ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.cmb_element .ui-datepicker .ui-datepicker-next,.cmb_element .ui-datepicker .ui-datepicker-prev{position:absolute;top:2px;width:1.8em;height:1.8em}.cmb_element .ui-datepicker .ui-datepicker-next-hover,.cmb_element .ui-datepicker .ui-datepicker-prev-hover{top:1px}.cmb_element .ui-datepicker .ui-datepicker-prev{left:2px}.cmb_element .ui-datepicker .ui-datepicker-next{right:2px}.cmb_element .ui-datepicker .ui-datepicker-prev-hover{left:1px}.cmb_element .ui-datepicker .ui-datepicker-next-hover{right:1px}.cmb_element .ui-datepicker .ui-datepicker-next span,.cmb_element .ui-datepicker .ui-datepicker-prev span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.cmb_element .ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.cmb_element .ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.cmb_element .ui-datepicker select.ui-datepicker-month-year{width:100%}.cmb_element .ui-datepicker select.ui-datepicker-month,.cmb_element .ui-datepicker select.ui-datepicker-year{width:49%}.cmb_element .ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.cmb_element .ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:700;border:0}.cmb_element .ui-datepicker td{border:0;padding:1px}.cmb_element .ui-datepicker td a,.cmb_element .ui-datepicker td span{display:block;padding:.2em;text-align:right;text-decoration:none}.cmb_element .ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.cmb_element .ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em;width:auto;overflow:visible}.cmb_element .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.cmb_element .ui-datepicker.ui-datepicker-multi{width:auto}.cmb_element .ui-datepicker-multi .ui-datepicker-group{float:left}.cmb_element .ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.cmb_element .ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.cmb_element .ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.cmb_element .ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.cmb_element .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.cmb_element .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.cmb_element .ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.cmb_element .ui-datepicker-row-break{clear:both;width:100%;font-size:0}.cmb_element .ui-datepicker-rtl{direction:rtl}.cmb_element .ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.cmb_element .ui-datepicker-rtl .ui-datepicker-group{float:right}.cmb_element .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.cmb_element .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.cmb_element .ui-datepicker-cover{display:none;display:block;position:absolute;z-index:-1;filter:mask();top:-4px;left:-4px;width:200px;height:200px}
lib/metabox/example-functions.php DELETED
@@ -1,333 +0,0 @@
1
- <?php
2
- /**
3
- * Include and setup custom metaboxes and fields.
4
- *
5
- * @category YourThemeOrPlugin
6
- * @package Metaboxes
7
- * @license http://www.opensource.org/licenses/gpl-license.php GPL v2.0 (or later)
8
- * @link https://github.com/jaredatch/Custom-Metaboxes-and-Fields-for-WordPress
9
- */
10
-
11
- add_filter( 'cmb_meta_boxes', 'cmb_sample_metaboxes' );
12
- /**
13
- * Define the metabox and field configurations.
14
- *
15
- * @param array $meta_boxes
16
- * @return array
17
- */
18
- function cmb_sample_metaboxes( array $meta_boxes ) {
19
-
20
- // Start with an underscore to hide fields from custom fields list
21
- $prefix = '_cmb_';
22
-
23
- $meta_boxes['test_metabox'] = array(
24
- 'id' => 'test_metabox',
25
- 'title' => __( 'Test Metabox', 'cmb' ),
26
- 'pages' => array( 'page', ), // Post type
27
- 'context' => 'normal',
28
- 'priority' => 'high',
29
- 'show_names' => true, // Show field names on the left
30
- // 'cmb_styles' => true, // Enqueue the CMB stylesheet on the frontend
31
- 'fields' => array(
32
- array(
33
- 'name' => __( 'Test Text', 'cmb' ),
34
- 'desc' => __( 'field description (optional)', 'cmb' ),
35
- 'id' => $prefix . 'test_text',
36
- 'type' => 'text',
37
- // 'repeatable' => true,
38
- // 'on_front' => false, // Optionally designate a field to wp-admin only
39
- ),
40
- array(
41
- 'name' => __( 'Test Text Small', 'cmb' ),
42
- 'desc' => __( 'field description (optional)', 'cmb' ),
43
- 'id' => $prefix . 'test_textsmall',
44
- 'type' => 'text_small',
45
- // 'repeatable' => true,
46
- ),
47
- array(
48
- 'name' => __( 'Test Text Medium', 'cmb' ),
49
- 'desc' => __( 'field description (optional)', 'cmb' ),
50
- 'id' => $prefix . 'test_textmedium',
51
- 'type' => 'text_medium',
52
- // 'repeatable' => true,
53
- ),
54
- array(
55
- 'name' => __( 'Website URL', 'cmb' ),
56
- 'desc' => __( 'field description (optional)', 'cmb' ),
57
- 'id' => $prefix . 'url',
58
- 'type' => 'text_url',
59
- // 'protocols' => array('http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet'), // Array of allowed protocols
60
- // 'repeatable' => true,
61
- ),
62
- array(
63
- 'name' => __( 'Test Text Email', 'cmb' ),
64
- 'desc' => __( 'field description (optional)', 'cmb' ),
65
- 'id' => $prefix . 'email',
66
- 'type' => 'text_email',
67
- // 'repeatable' => true,
68
- ),
69
- array(
70
- 'name' => __( 'Test Time', 'cmb' ),
71
- 'desc' => __( 'field description (optional)', 'cmb' ),
72
- 'id' => $prefix . 'test_time',
73
- 'type' => 'text_time',
74
- ),
75
- array(
76
- 'name' => __( 'Time zone', 'cmb' ),
77
- 'desc' => __( 'Time zone', 'cmb' ),
78
- 'id' => $prefix . 'timezone',
79
- 'type' => 'select_timezone',
80
- ),
81
- array(
82
- 'name' => __( 'Test Date Picker', 'cmb' ),
83
- 'desc' => __( 'field description (optional)', 'cmb' ),
84
- 'id' => $prefix . 'test_textdate',
85
- 'type' => 'text_date',
86
- ),
87
- array(
88
- 'name' => __( 'Test Date Picker (UNIX timestamp)', 'cmb' ),
89
- 'desc' => __( 'field description (optional)', 'cmb' ),
90
- 'id' => $prefix . 'test_textdate_timestamp',
91
- 'type' => 'text_date_timestamp',
92
- // 'timezone_meta_key' => $prefix . 'timezone', // Optionally make this field honor the timezone selected in the select_timezone specified above
93
- ),
94
- array(
95
- 'name' => __( 'Test Date/Time Picker Combo (UNIX timestamp)', 'cmb' ),
96
- 'desc' => __( 'field description (optional)', 'cmb' ),
97
- 'id' => $prefix . 'test_datetime_timestamp',
98
- 'type' => 'text_datetime_timestamp',
99
- ),
100
- array(
101
- 'name' => __( 'Test Date/Time Picker/Time zone Combo (serialized DateTime object)', 'cmb' ),
102
- 'desc' => __( 'field description (optional)', 'cmb' ),
103
- 'id' => $prefix . 'test_datetime_timestamp_timezone',
104
- 'type' => 'text_datetime_timestamp_timezone',
105
- ),
106
- array(
107
- 'name' => __( 'Test Money', 'cmb' ),
108
- 'desc' => __( 'field description (optional)', 'cmb' ),
109
- 'id' => $prefix . 'test_textmoney',
110
- 'type' => 'text_money',
111
- // 'before' => '£', // override '$' symbol if needed
112
- // 'repeatable' => true,
113
- ),
114
- array(
115
- 'name' => __( 'Test Color Picker', 'cmb' ),
116
- 'desc' => __( 'field description (optional)', 'cmb' ),
117
- 'id' => $prefix . 'test_colorpicker',
118
- 'type' => 'colorpicker',
119
- 'std' => '#ffffff'
120
- ),
121
- array(
122
- 'name' => __( 'Test Text Area', 'cmb' ),
123
- 'desc' => __( 'field description (optional)', 'cmb' ),
124
- 'id' => $prefix . 'test_textarea',
125
- 'type' => 'textarea',
126
- ),
127
- array(
128
- 'name' => __( 'Test Text Area Small', 'cmb' ),
129
- 'desc' => __( 'field description (optional)', 'cmb' ),
130
- 'id' => $prefix . 'test_textareasmall',
131
- 'type' => 'textarea_small',
132
- ),
133
- array(
134
- 'name' => __( 'Test Text Area for Code', 'cmb' ),
135
- 'desc' => __( 'field description (optional)', 'cmb' ),
136
- 'id' => $prefix . 'test_textarea_code',
137
- 'type' => 'textarea_code',
138
- ),
139
- array(
140
- 'name' => __( 'Test Title Weeeee', 'cmb' ),
141
- 'desc' => __( 'This is a title description', 'cmb' ),
142
- 'id' => $prefix . 'test_title',
143
- 'type' => 'title',
144
- ),
145
- array(
146
- 'name' => __( 'Test Select', 'cmb' ),
147
- 'desc' => __( 'field description (optional)', 'cmb' ),
148
- 'id' => $prefix . 'test_select',
149
- 'type' => 'select',
150
- 'options' => array(
151
- array( 'name' => __( 'Option One', 'cmb' ), 'value' => 'standard', ),
152
- array( 'name' => __( 'Option Two', 'cmb' ), 'value' => 'custom', ),
153
- array( 'name' => __( 'Option Three', 'cmb' ), 'value' => 'none', ),
154
- ),
155
- ),
156
- array(
157
- 'name' => __( 'Test Radio inline', 'cmb' ),
158
- 'desc' => __( 'field description (optional)', 'cmb' ),
159
- 'id' => $prefix . 'test_radio_inline',
160
- 'type' => 'radio_inline',
161
- 'options' => array(
162
- array( 'name' => __( 'Option One', 'cmb' ), 'value' => 'standard', ),
163
- array( 'name' => __( 'Option Two', 'cmb' ), 'value' => 'custom', ),
164
- array( 'name' => __( 'Option Three', 'cmb' ), 'value' => 'none', ),
165
- ),
166
- ),
167
- array(
168
- 'name' => __( 'Test Radio', 'cmb' ),
169
- 'desc' => __( 'field description (optional)', 'cmb' ),
170
- 'id' => $prefix . 'test_radio',
171
- 'type' => 'radio',
172
- 'options' => array(
173
- array( 'name' => __( 'Option One', 'cmb' ), 'value' => 'standard', ),
174
- array( 'name' => __( 'Option Two', 'cmb' ), 'value' => 'custom', ),
175
- array( 'name' => __( 'Option Three', 'cmb' ), 'value' => 'none', ),
176
- ),
177
- ),
178
- array(
179
- 'name' => __( 'Test Taxonomy Radio', 'cmb' ),
180
- 'desc' => __( 'field description (optional)', 'cmb' ),
181
- 'id' => $prefix . 'text_taxonomy_radio',
182
- 'type' => 'taxonomy_radio',
183
- 'taxonomy' => 'category', // Taxonomy Slug
184
- ),
185
- array(
186
- 'name' => __( 'Test Taxonomy Select', 'cmb' ),
187
- 'desc' => __( 'field description (optional)', 'cmb' ),
188
- 'id' => $prefix . 'text_taxonomy_select',
189
- 'type' => 'taxonomy_select',
190
- 'taxonomy' => 'category', // Taxonomy Slug
191
- ),
192
- array(
193
- 'name' => __( 'Test Taxonomy Multi Checkbox', 'cmb' ),
194
- 'desc' => __( 'field description (optional)', 'cmb' ),
195
- 'id' => $prefix . 'test_multitaxonomy',
196
- 'type' => 'taxonomy_multicheck',
197
- 'taxonomy' => 'post_tag', // Taxonomy Slug
198
- ),
199
- array(
200
- 'name' => __( 'Test Checkbox', 'cmb' ),
201
- 'desc' => __( 'field description (optional)', 'cmb' ),
202
- 'id' => $prefix . 'test_checkbox',
203
- 'type' => 'checkbox',
204
- ),
205
- array(
206
- 'name' => __( 'Test Multi Checkbox', 'cmb' ),
207
- 'desc' => __( 'field description (optional)', 'cmb' ),
208
- 'id' => $prefix . 'test_multicheckbox',
209
- 'type' => 'multicheck',
210
- 'options' => array(
211
- 'check1' => __( 'Check One', 'cmb' ),
212
- 'check2' => __( 'Check Two', 'cmb' ),
213
- 'check3' => __( 'Check Three', 'cmb' ),
214
- ),
215
- ),
216
- array(
217
- 'name' => __( 'Test wysiwyg', 'cmb' ),
218
- 'desc' => __( 'field description (optional)', 'cmb' ),
219
- 'id' => $prefix . 'test_wysiwyg',
220
- 'type' => 'wysiwyg',
221
- 'options' => array( 'textarea_rows' => 5, ),
222
- ),
223
- array(
224
- 'name' => __( 'Test Image', 'cmb' ),
225
- 'desc' => __( 'Upload an image or enter a URL.', 'cmb' ),
226
- 'id' => $prefix . 'test_image',
227
- 'type' => 'file',
228
- ),
229
- array(
230
- 'name' => __( 'Multiple Files', 'cmb' ),
231
- 'desc' => __( 'Upload or add multiple images/attachments.', 'cmb' ),
232
- 'id' => $prefix . 'test_file_list',
233
- 'type' => 'file_list',
234
- ),
235
- array(
236
- 'name' => __( 'oEmbed', 'cmb' ),
237
- 'desc' => __( 'Enter a youtube, twitter, or instagram URL. Supports services listed at <a href="http://codex.wordpress.org/Embeds">http://codex.wordpress.org/Embeds</a>.', 'cmb' ),
238
- 'id' => $prefix . 'test_embed',
239
- 'type' => 'oembed',
240
- ),
241
- ),
242
- );
243
-
244
- $meta_boxes['about_page_metabox'] = array(
245
- 'id' => 'about_page_metabox',
246
- 'title' => __( 'About Page Metabox', 'cmb' ),
247
- 'pages' => array( 'page', ), // Post type
248
- 'context' => 'normal',
249
- 'priority' => 'high',
250
- 'show_names' => true, // Show field names on the left
251
- 'show_on' => array( 'key' => 'id', 'value' => array( 2, ), ), // Specific post IDs to display this metabox
252
- 'fields' => array(
253
- array(
254
- 'name' => __( 'Test Text', 'cmb' ),
255
- 'desc' => __( 'field description (optional)', 'cmb' ),
256
- 'id' => $prefix . 'test_text',
257
- 'type' => 'text',
258
- ),
259
- )
260
- );
261
-
262
- /**
263
- * Metabox for the user profile screen
264
- */
265
- $meta_boxes['user_edit'] = array(
266
- 'id' => 'user_edit',
267
- 'title' => __( 'User Profile Metabox', 'cmb' ),
268
- 'pages' => array( 'user' ), // Tells CMB to use user_meta vs post_meta
269
- 'show_names' => true,
270
- // 'cmb_styles' => true, // Show cmb bundled styles.. not needed on user profile page
271
- 'fields' => array(
272
- array(
273
- 'name' => __( 'Extra Info', 'cmb' ),
274
- 'desc' => __( 'field description (optional)', 'cmb' ),
275
- 'id' => $prefix . 'exta_info',
276
- 'type' => 'title',
277
- 'on_front' => false,
278
- ),
279
- array(
280
- 'name' => __( 'Avatar', 'cmb' ),
281
- 'desc' => __( 'field description (optional)', 'cmb' ),
282
- 'id' => $prefix . 'avatar',
283
- 'type' => 'file',
284
- 'save_id' => true,
285
- ),
286
- array(
287
- 'name' => __( 'Facebook URL', 'cmb' ),
288
- 'desc' => __( 'field description (optional)', 'cmb' ),
289
- 'id' => $prefix . 'facebookurl',
290
- 'type' => 'text_url',
291
- ),
292
- array(
293
- 'name' => __( 'Twitter URL', 'cmb' ),
294
- 'desc' => __( 'field description (optional)', 'cmb' ),
295
- 'id' => $prefix . 'twitterurl',
296
- 'type' => 'text_url',
297
- ),
298
- array(
299
- 'name' => __( 'Google+ URL', 'cmb' ),
300
- 'desc' => __( 'field description (optional)', 'cmb' ),
301
- 'id' => $prefix . 'googleplusurl',
302
- 'type' => 'text_url',
303
- ),
304
- array(
305
- 'name' => __( 'Linkedin URL', 'cmb' ),
306
- 'desc' => __( 'field description (optional)', 'cmb' ),
307
- 'id' => $prefix . 'linkedinurl',
308
- 'type' => 'text_url',
309
- ),
310
- array(
311
- 'name' => __( 'User Field', 'cmb' ),
312
- 'desc' => __( 'field description (optional)', 'cmb' ),
313
- 'id' => $prefix . 'user_text_field',
314
- 'type' => 'text',
315
- ),
316
- )
317
- );
318
-
319
- // Add other metaboxes as needed
320
-
321
- return $meta_boxes;
322
- }
323
-
324
- add_action( 'init', 'cmb_initialize_cmb_meta_boxes', 9999 );
325
- /**
326
- * Initialize the metabox class.
327
- */
328
- function cmb_initialize_cmb_meta_boxes() {
329
-
330
- if ( ! class_exists( 'cmb_Meta_Box' ) )
331
- require_once 'init.php';
332
-
333
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/metabox/helpers/timeline_express_MetaBox_types.php DELETED
@@ -1,539 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * CMB field types
5
- * @since 1.0.0
6
- */
7
- class timeline_express_MetaBox_types {
8
-
9
- /**
10
- * @todo test taxonomy methods with non-post objects
11
- * @todo test all methods with non-post objects
12
- */
13
-
14
- /**
15
- * A single instance of this class.
16
- * @var cmb_Meta_Box_types object
17
- */
18
- public static $instance = null;
19
-
20
- /**
21
- * An iterator value for repeatable fields
22
- * @var integer
23
- */
24
- public static $iterator = 0;
25
-
26
- /**
27
- * Holds cmb_valid_img_types
28
- * @var array
29
- */
30
- public static $valid = array();
31
-
32
- /**
33
- * Current field type
34
- * @var string
35
- */
36
- public static $type = 'text';
37
-
38
- /**
39
- * Current field
40
- * @var array
41
- */
42
- public static $field;
43
-
44
- /**
45
- * Current field meta value
46
- * @var mixed
47
- */
48
- public static $meta;
49
-
50
- /**
51
- * Creates or returns an instance of this class.
52
- * @since 1.0.0
53
- * @return cmb_Meta_Box_types A single instance of this class.
54
- */
55
- public static function get() {
56
- if ( self::$instance === null )
57
- self::$instance = new self();
58
-
59
- return self::$instance;
60
- }
61
-
62
- /**
63
- * Generates a field's description markup
64
- * @since 1.0.0
65
- * @param string $desc Field's description
66
- * @param boolean $paragraph Paragraph tag or span
67
- * @return strgin Field's description markup
68
- */
69
- private static function desc( $desc, $paragraph = false ) {
70
- $tag = $paragraph ? 'p' : 'span';
71
- return "\n<$tag class=\"cmb_metabox_description\">$desc</$tag>\n";
72
- }
73
-
74
- /**
75
- * Generates repeatable text fields
76
- * @since 1.0.0
77
- * @param string $field Metabox field
78
- * @param mixed $meta Field's meta value
79
- * @param string $class Field's class attribute
80
- * @param string $type Field Type
81
- */
82
- private static function repeat_text_field( $field, $meta, $class = '', $type = 'text' ) {
83
-
84
- self::$field = $field; self::$meta = $meta; self::$type = $type;
85
-
86
- // check for default content
87
- $std = isset( $field['std'] ) ? array( $field['std'] ) : false;
88
- // check for saved data
89
- $meta = !empty( $meta ) && array_filter( $meta ) ? $meta : $std;
90
-
91
-
92
- self::repeat_table_open( $class );
93
-
94
- $class = $class ? $class .' widefat' : 'widefat';
95
-
96
- if ( !empty( $meta ) ) {
97
- foreach ( (array) $meta as $val ) {
98
- self::repeat_row( self::text_input( $class, $val ) );
99
- }
100
- } else {
101
- self::repeat_row( self::text_input( $class ) );
102
- }
103
-
104
- self::empty_row( self::text_input( $class ) );
105
- self::repeat_table_close();
106
- // reset iterator
107
- self::$iterator = 0;
108
- }
109
-
110
- /**
111
- * Text input field used by repeatable fields
112
- * @since 1.0.0
113
- * @param string $class Field's class attribute
114
- * @param mixed $val Field's meta value
115
- * @return string HTML text input
116
- */
117
- private static function text_input( $class = '', $val = '' ) {
118
- self::$iterator = self::$iterator ? self::$iterator + 1 : 1;
119
- $before = '';
120
- if ( self::$field['type'] == 'text_money' )
121
- $before = ! empty( self::$field['before'] ) ? ' ' : '$ ';
122
- return $before . '<input type="'. self::$type .'" class="'. $class .'" name="'. self::$field['id'] .'[]" id="'. self::$field['id'] .'_'. self::$iterator .'" value="'. $val .'" data-id="'. self::$field['id'] .'" data-count="'. self::$iterator .'"/>';
123
- }
124
-
125
- /**
126
- * Generates repeatable field opening table markup for repeatable fields
127
- * @since 1.0.0
128
- * @param string $class Field's class attribute
129
- */
130
- private static function repeat_table_open( $class = '' ) {
131
- echo self::desc( self::$field['desc'] ), '<table id="', self::$field['id'], '_repeat" class="cmb-repeat-table ', $class ,'"><tbody>';
132
- }
133
-
134
- /**
135
- * Generates repeatable feild closing table markup for repeatable fields
136
- * @since 1.0.0
137
- */
138
- private static function repeat_table_close() {
139
- echo '</tbody></table><p class="add-row"><a data-selector="', self::$field['id'] ,'_repeat" class="add-row-button button" href="#">'. __( 'Add Row', 'cmb' ) .'</a></p>';
140
- }
141
-
142
- /**
143
- * Generates table row markup for repeatable fields
144
- * @since 1.0.0
145
- * @param string $input Table cell markup
146
- */
147
- private static function repeat_row( $input ) {
148
- echo '<tr class="repeat-row">', self::repeat_cell( $input ) ,'</tr>';
149
- }
150
-
151
- /**
152
- * Generates the empty table row markup (for duplication) for repeatable fields
153
- * @since 1.0.0
154
- * @param string $input Table cell markup
155
- */
156
- private static function empty_row( $input ) {
157
- echo '<tr class="empty-row">', self::repeat_cell( $input ) ,'</tr>';
158
- }
159
-
160
- /**
161
- * Generates table cell markup for repeatable fields
162
- * @since 1.0.0
163
- * @param string $input Text input field
164
- * @return string HTML table cell markup
165
- */
166
- private static function repeat_cell( $input ) {
167
- return '<td>'. $input .'</td><td class="remove-row"><a class="button remove-row-button" href="#">'. __( 'Remove', 'cmb' ) .'</a></td>';
168
- }
169
-
170
- /**
171
- * Determine a file's extension
172
- * @since 1.0.0
173
- * @param string $file File url
174
- * @return string|false File extension or false
175
- */
176
- public static function get_file_ext( $file ) {
177
- $parsed = @parse_url( $file, PHP_URL_PATH );
178
- return $parsed ? strtolower( pathinfo( $parsed, PATHINFO_EXTENSION ) ) : false;
179
- }
180
-
181
- /**
182
- * Determines if a file has a valid image extension
183
- * @since 1.0.0
184
- * @param string $file File url
185
- * @return bool Whether file has a valid image extension
186
- */
187
- public static function is_valid_img_ext( $file ) {
188
- $file_ext = self::get_file_ext( $file );
189
-
190
- self::$valid = empty( self::$valid ) ? (array) apply_filters( 'cmb_valid_img_types', array( 'jpg', 'jpeg', 'png', 'gif', 'ico', 'icon' ) ) : self::$valid;
191
-
192
- return ( $file_ext && in_array( $file_ext, self::$valid ) );
193
- }
194
-
195
-
196
- /**
197
- * Begin Field Types
198
- */
199
- /** Custom About Type */
200
- public static function custom_about_the_author_callback( $field, $meta ) {
201
- require_once TIMELINE_EXPRESS_PATH . '/lib/metabox/about-template.php';
202
- }
203
-
204
- public static function text( $field, $meta ) {
205
- echo '<input type="text" name="', $field['id'], '" id="', $field['id'], '" value="', '' !== $meta ? $meta : $field['std'], '" />', self::desc( $field['desc'], true );
206
- }
207
-
208
- public static function text_repeat( $field, $meta ) {
209
- self::repeat_text_field( $field, $meta );
210
- }
211
-
212
- public static function text_small( $field, $meta ) {
213
- echo '<input class="cmb_text_small" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', '' !== $meta ? $meta : $field['std'], '" />', self::desc( $field['desc'] );
214
- }
215
-
216
- public static function text_small_repeat( $field, $meta ) {
217
- self::repeat_text_field( $field, $meta, 'cmb_text_small' );
218
- }
219
-
220
- public static function text_medium( $field, $meta ) {
221
- echo '<input class="cmb_text_medium" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', '' !== $meta ? $meta : $field['std'], '" />', self::desc( $field['desc'] );
222
- }
223
-
224
- public static function text_medium_repeat( $field, $meta ) {
225
- self::repeat_text_field( $field, $meta, 'cmb_text_medium' );
226
- }
227
-
228
- public static function text_email( $field, $meta ) {
229
- echo '<input class="cmb_text_email cmb_text_medium" type="email" name="', $field['id'], '" id="', $field['id'], '" value="', '' !== $meta ? $meta : $field['std'], '" />', self::desc( $field['desc'], true );
230
- }
231
-
232
- public static function text_email_repeat( $field, $meta ) {
233
- self::repeat_text_field( $field, $meta, 'cmb_text_email cmb_text_medium', 'email' );
234
- }
235
-
236
- public static function text_url( $field, $meta ) {
237
- $val = ! empty( $meta ) ? $meta : $field['std'];
238
- $protocols = isset( $field['protocols'] ) ? (array) $field['protocols'] : null;
239
- $val = $val ? esc_url( $val, $protocols ) : '';
240
-
241
- echo '<input class="cmb_text_url cmb_text_medium" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', $val, '" />', self::desc( $field['desc'], true );
242
- }
243
-
244
- public static function text_url_repeat( $field, $meta ) {
245
- $val = ! empty( $meta ) ? $meta : $field['std'];
246
- $protocols = isset( $field['protocols'] ) ? (array) $field['protocols'] : null;
247
- $val = $val ? esc_url( $val, $protocols ) : '';
248
- self::repeat_text_field( $field, $val, 'cmb_text_url cmb_text_medium' );
249
- }
250
-
251
- public static function text_date( $field, $meta ) {
252
- echo '<input class="cmb_text_small cmb_datepicker" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', '' !== $meta ? $meta : $field['std'], '" />', self::desc( $field['desc'] );
253
- }
254
-
255
- public static function text_date_timestamp( $field, $meta ) {
256
- echo '<input class="cmb_text_small cmb_datepicker" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', '' !== $meta ? date( 'm\/d\/Y', $meta ) : $field['std'], '" />', self::desc( $field['desc'] );
257
- }
258
-
259
- public static function text_datetime_timestamp( $field, $meta, $object_id ) {
260
-
261
- // This will be used if there is a select_timezone set for this field
262
- $tz_offset = cmb_Meta_Box::field_timezone_offset( $object_id );
263
- if ( !empty( $tz_offset ) ) {
264
- $meta -= $tz_offset;
265
- }
266
-
267
- echo '<input class="cmb_text_small cmb_datepicker" type="text" name="', $field['id'], '[date]" id="', $field['id'], '_date" value="', '' !== $meta ? date( 'm\/d\/Y', $meta ) : $field['std'], '" />';
268
- echo '<input class="cmb_timepicker text_time" type="text" name="', $field['id'], '[time]" id="', $field['id'], '_time" value="', '' !== $meta ? date( 'h:i A', $meta ) : $field['std'], '" />', self::desc( $field['desc'] );
269
- }
270
-
271
- public static function text_datetime_timestamp_timezone( $field, $meta ) {
272
-
273
- $datetime = unserialize($meta);
274
- $meta = $tzstring = false;
275
-
276
-
277
- if ( $datetime && $datetime instanceof DateTime ) {
278
- $tz = $datetime->getTimezone();
279
- $tzstring = $tz->getName();
280
-
281
- $meta = $datetime->getTimestamp() + $tz->getOffset( new DateTime('NOW') );
282
- }
283
-
284
- echo '<input class="cmb_text_small cmb_datepicker" type="text" name="', $field['id'], '[date]" id="', $field['id'], '_date" value="', '' !== $meta ? date( 'm\/d\/Y', $meta ) : $field['std'], '" />';
285
- echo '<input class="cmb_timepicker text_time" type="text" name="', $field['id'], '[time]" id="', $field['id'], '_time" value="', '' !== $meta ? date( 'h:i A', $meta ) : $field['std'], '" />';
286
-
287
- echo '<select name="', $field['id'], '[timezone]" id="', $field['id'], '_timezone">';
288
- echo wp_timezone_choice( $tzstring );
289
- echo '</select>', self::desc( $field['desc'] );
290
- }
291
-
292
- public static function text_time( $field, $meta ) {
293
- echo '<input class="cmb_timepicker text_time" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', '' !== $meta ? $meta : $field['std'], '" />', self::desc( $field['desc'] );
294
- }
295
-
296
- public static function select_timezone( $field, $meta ) {
297
- $meta = '' !== $meta ? $meta : $field['std'];
298
- if ( '' === $meta )
299
- $meta = cmb_Meta_Box::timezone_string();
300
-
301
- echo '<select name="', $field['id'], '" id="', $field['id'], '">';
302
- echo wp_timezone_choice( $meta );
303
- echo '</select>';
304
- }
305
-
306
- public static function text_money( $field, $meta ) {
307
- echo ! empty( $field['before'] ) ? '' : '$', ' <input class="cmb_text_money" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', '' !== $meta ? $meta : $field['std'], '" />', self::desc( $field['desc'] );
308
- }
309
-
310
- public static function text_money_repeat( $field, $meta ) {
311
- self::repeat_text_field( $field, $meta, 'cmb_text_money' );
312
- }
313
-
314
- public static function colorpicker( $field, $meta ) {
315
- $meta = '' !== $meta ? $meta : $field['std'];
316
- $hex_color = '(([a-fA-F0-9]){3}){1,2}$';
317
- if ( preg_match( '/^' . $hex_color . '/i', $meta ) ) // Value is just 123abc, so prepend #.
318
- $meta = '#' . $meta;
319
- elseif ( ! preg_match( '/^#' . $hex_color . '/i', $meta ) ) // Value doesn't match #123abc, so sanitize to just #.
320
- $meta = "#";
321
- echo '<input class="cmb_colorpicker cmb_text_small" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', $meta, '" />', self::desc( $field['desc'] );
322
- }
323
-
324
- public static function textarea( $field, $meta ) {
325
- echo '<textarea name="', $field['id'], '" id="', $field['id'], '" cols="60" rows="10">', '' !== $meta ? $meta : $field['std'], '</textarea>', self::desc( $field['desc'], true );
326
- }
327
-
328
- public static function textarea_small( $field, $meta ) {
329
- echo '<textarea name="', $field['id'], '" id="', $field['id'], '" cols="60" rows="4">', '' !== $meta ? $meta : $field['std'], '</textarea>', self::desc( $field['desc'], true );
330
- }
331
-
332
- public static function textarea_code( $field, $meta ) {
333
- echo '<textarea name="', $field['id'], '" id="', $field['id'], '" cols="60" rows="10" class="cmb_textarea_code">', '' !== $meta ? $meta : $field['std'], '</textarea>', self::desc( $field['desc'], true );
334
- }
335
-
336
- public static function select( $field, $meta ) {
337
- if( empty( $meta ) && !empty( $field['std'] ) ) $meta = $field['std'];
338
- echo '<select name="', $field['id'], '" id="', $field['id'], '">';
339
- foreach ($field['options'] as $option) {
340
- echo '<option value="', $option['value'], '"', $meta == $option['value'] ? ' selected="selected"' : '', '>', $option['name'], '</option>';
341
- }
342
- echo '</select>', self::desc( $field['desc'], true );
343
- }
344
-
345
- public static function radio_inline( $field, $meta ) {
346
- if( empty( $meta ) && !empty( $field['std'] ) ) $meta = $field['std'];
347
- echo '<ul class="cmb_radio_inline">';
348
- $i = 1;
349
- foreach ($field['options'] as $option) {
350
- echo '<li class="cmb_radio_inline_option"><input type="radio" name="', $field['id'], '" id="', $field['id'], $i, '" value="', $option['value'], '"', checked( $meta == $option['value'] ), ' /> <label for="', $field['id'], $i, '">', $option['name'], '</label></li>';
351
- $i++;
352
- }
353
- echo '</ul>', self::desc( $field['desc'], true );
354
- }
355
-
356
- public static function radio( $field, $meta ) {
357
- if( empty( $meta ) && !empty( $field['std'] ) ) $meta = $field['std'];
358
- echo '<ul>';
359
- $i = 1;
360
- foreach ($field['options'] as $option) {
361
- echo '<li class="cmb_radio_inline_option"><input type="radio" name="', $field['id'], '" id="', $field['id'], $i,'" value="', $option['value'], '" ', checked( $meta == $option['value'] ), ' /> <label for="', $field['id'], $i, '">', $option['name'].'</label></li>';
362
- $i++;
363
- }
364
- echo '</ul>', self::desc( $field['desc'], true );
365
- }
366
-
367
- public static function checkbox( $field, $meta ) {
368
- echo '<input type="checkbox" name="', $field['id'], '" id="', $field['id'], '" ', checked( ! empty( $meta ) ), ' /> <label for="', $field['id'], '">', self::desc( $field['desc'] ) ,'</label>';
369
- }
370
-
371
- public static function multicheck( $field, $meta ) {
372
- echo '<ul>';
373
- $i = 1;
374
- foreach ( $field['options'] as $value => $name ) {
375
- echo '<li><input type="checkbox" name="', $field['id'], '[]" id="', $field['id'], $i, '" value="', $value, '" ', checked( in_array( $value, $meta ) ), ' /> <label for="', $field['id'], $i, '">', $name, '</label></li>';
376
- $i++;
377
- }
378
- echo '</ul>', self::desc( $field['desc'] );
379
- }
380
-
381
- public static function title( $field, $meta, $object_id, $object_type ) {
382
- $tag = $object_type == 'post' ? 'h5' : 'h3';
383
- echo '<'. $tag .' class="cmb_metabox_title">', $field['name'], '</'. $tag .'>', self::desc( $field['desc'], true );
384
- }
385
-
386
- public static function wysiwyg( $field, $meta ) {
387
- wp_editor( $meta ? $meta : $field['std'], $field['id'], isset( $field['options'] ) ? $field['options'] : array() );
388
- echo self::desc( $field['desc'], true );
389
- }
390
-
391
- public static function taxonomy_select( $field, $meta, $object_id ) {
392
-
393
- echo '<select name="', $field['id'], '" id="', $field['id'], '">';
394
- $names = wp_get_object_terms( $object_id, $field['taxonomy'] );
395
- $terms = get_terms( $field['taxonomy'], 'hide_empty=0' );
396
- foreach ( $terms as $term ) {
397
- if ( !is_wp_error( $names ) && !empty( $names ) && ! strcmp( $term->slug, $names[0]->slug ) ) {
398
- echo '<option value="' . $term->slug . '" selected>' . $term->name . '</option>';
399
- } else {
400
- echo '<option value="' . $term->slug . ' ' , $meta == $term->slug ? $meta : ' ' ,' ">' . $term->name . '</option>';
401
- }
402
- }
403
- echo '</select>', self::desc( $field['desc'], true );
404
- }
405
-
406
- public static function taxonomy_radio( $field, $meta, $object_id ) {
407
-
408
- $names = wp_get_object_terms( $object_id, $field['taxonomy'] );
409
- $terms = get_terms( $field['taxonomy'], 'hide_empty=0' );
410
- echo '<ul>';
411
- $i = 1;
412
- foreach ( $terms as $term ) {
413
- $checked = ( !is_wp_error( $names ) && !empty( $names ) && !strcmp( $term->slug, $names[0]->slug ) );
414
-
415
- echo '<li class="cmb_radio_inline_option"><input type="radio" name="', $field['id'], '" id="', $field['id'], $i,'" value="'. $term->slug . '" ', checked( $checked ), ' /> <label for="', $field['id'], $i, '">' . $term->name . '</label></li>';
416
- $i++;
417
- }
418
- echo '</ul>', self::desc( $field['desc'], true );
419
- }
420
-
421
- public static function taxonomy_multicheck( $field, $meta, $object_id ) {
422
- echo '<ul>';
423
- $names = wp_get_object_terms( $object_id, $field['taxonomy'] );
424
- $terms = get_terms( $field['taxonomy'], 'hide_empty=0' );
425
- $i = 1;
426
- foreach ( $terms as $term ) {
427
- echo '<li><input type="checkbox" name="', $field['id'], '[]" id="', $field['id'], $i,'" value="'. $term->slug . '" ';
428
- foreach ($names as $name) {
429
- checked( $term->slug == $name->slug );
430
- }
431
-
432
- echo ' /> <label for="', $field['id'], $i, '">' . $term->name . '</label></li>';
433
- $i++;
434
- }
435
- echo '</ul>', self::desc( $field['desc'] );
436
- }
437
-
438
- public static function file_list( $field, $meta, $object_id ) {
439
-
440
- echo '<input class="cmb_upload_file cmb_upload_list" type="hidden" size="45" id="', $field['id'], '" name="', $field['id'], '" value="', $meta, '" />';
441
- echo '<input class="cmb_upload_button button cmb_upload_list" type="button" value="'. __( 'Add or Upload File', 'cmb' ) .'" />', self::desc( $field['desc'], true );
442
-
443
- echo '<ul id="', $field['id'], '_status" class="cmb_media_status attach_list">';
444
-
445
- if ( $meta ) {
446
-
447
- foreach ( $meta as $id => $fullurl ) {
448
- if ( self::is_valid_img_ext( $fullurl ) ) {
449
- echo
450
- '<li class="img_status">',
451
- wp_get_attachment_image( $id, array( 50, 50 ) ),
452
- '<p><a href="#" class="cmb_remove_file_button">'. __( 'Remove Image', 'cmb' ) .'</a></p>
453
- <input type="hidden" id="filelist-', $id ,'" name="', $field['id'] ,'[', $id ,']" value="', $fullurl ,'" />
454
- </li>';
455
-
456
- } else {
457
- $parts = explode( '/', $fullurl );
458
- for ( $i = 0; $i < count( $parts ); ++$i ) {
459
- $title = $parts[$i];
460
- }
461
- echo
462
- '<li>',
463
- __( 'File:', 'cmb' ), ' <strong>', $title, '</strong>&nbsp;&nbsp;&nbsp; (<a href="', $fullurl, '" target="_blank" rel="external">'. __( 'Download', 'cmb' ) .'</a> / <a href="#" class="cmb_remove_file_button">'. __( 'Remove', 'cmb' ) .'</a>)
464
- <input type="hidden" id="filelist-', $id ,'" name="', $field['id'] ,'[', $id ,']" value="', $fullurl ,'" />
465
- </li>';
466
- }
467
- }
468
- }
469
-
470
- echo '</ul>';
471
- }
472
-
473
- public static function file( $field, $meta, $object_id, $object_type ) {
474
-
475
- $input_type_url = 'hidden';
476
- if ( 'url' == $field['allow'] || ( is_array( $field['allow'] ) && in_array( 'url', $field['allow'] ) ) )
477
- $input_type_url = 'text';
478
- echo '<input class="cmb_upload_file" type="' . $input_type_url . '" size="45" id="', $field['id'], '" name="', $field['id'], '" value="', $meta, '" />';
479
- echo '<input class="cmb_upload_button button" type="button" value="'. __( 'Add or Upload File', 'cmb' ) .'" />';
480
-
481
- $_id_name = $field['id'] .'_id';
482
-
483
- $_id_meta = get_metadata( $object_type, $object_id, $_id_name, ( ! isset( $field['multiple'] ) || ! $field['multiple'] ) );
484
-
485
- // If there is no ID saved yet, try to get it from the url
486
- if ( $meta && ! $_id_meta ) {
487
- $_id_meta = cmb_Meta_Box::image_id_from_url( esc_url_raw( $meta ) );
488
- }
489
-
490
- echo '<input class="cmb_upload_file_id" type="hidden" id="', $_id_name, '" name="', $_id_name, '" value="', $_id_meta, '" />',
491
- self::desc( $field['desc'], true ),
492
- '<div id="', $field['id'], '_status" class="cmb_media_status">';
493
- if ( ! empty( $meta ) ) {
494
-
495
- if ( self::is_valid_img_ext( $meta ) ) {
496
- echo '<div class="img_status">';
497
- echo '<img style="max-width: 350px; width: 100%; height: auto;" src="', $meta, '" alt="" />';
498
- echo '<p><a href="#" class="cmb_remove_file_button" rel="', $field['id'], '">'. __( 'Remove Image', 'cmb' ) .'</a></p>';
499
- echo '</div>';
500
- } else {
501
- // $file_ext = self::get_file_ext( $meta );
502
- $parts = explode( '/', $meta );
503
- for ( $i = 0; $i < count( $parts ); ++$i ) {
504
- $title = $parts[$i];
505
- }
506
- echo __( 'File:', 'cmb' ), ' <strong>', $title, '</strong>&nbsp;&nbsp;&nbsp; (<a href="', $meta, '" target="_blank" rel="external">'. __( 'Download', 'cmb' ) .'</a> / <a href="#" class="cmb_remove_file_button" rel="', $field['id'], '">'. __( 'Remove', 'cmb' ) .'</a>)';
507
- }
508
- }
509
- echo '</div>';
510
- }
511
-
512
- public static function oembed( $field, $meta, $object_id, $object_type ) {
513
- echo '<input class="cmb_oembed" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', '' !== $meta ? $meta : $field['std'], '" />', self::desc( $field['desc'], true );
514
- echo '<p class="cmb-spinner spinner" style="display:none;"><img src="'. admin_url( '/images/wpspin_light.gif' ) .'" alt="spinner"/></p>';
515
- echo '<div id="', $field['id'], '_status" class="cmb_media_status ui-helper-clearfix embed_wrap">';
516
-
517
- if ( $meta != '' )
518
- echo cmb_Meta_Box_ajax::get_oembed( $meta, $object_id, array(
519
- 'object_type' => $object_type,
520
- 'oembed_args' => array( 'width' => '640' ),
521
- 'field_id' => $field['id'],
522
- ) );
523
-
524
- echo '</div>';
525
- }
526
-
527
- /**
528
- * Default fallback. Allows rendering fields via "cmb_render_$name" hook
529
- * @since 1.0.0
530
- * @param string $name Non-existent method name
531
- * @param array $arguments All arguments passed to the method
532
- */
533
- public function __call( $name, $arguments ) {
534
- list( $field, $meta, $object_id, $object_type ) = $arguments;
535
- // When a non-registered field is called, send it through an action.
536
- do_action( "cmb_render_$name", $field, $meta, $object_id, $object_type );
537
- }
538
-
539
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/metabox/init.php DELETED
@@ -1,944 +0,0 @@
1
- <?php
2
- /*
3
- Script Name: Custom Metaboxes and Fields
4
- Contributors: Andrew Norcross (@norcross / andrewnorcross.com)
5
- Jared Atchison (@jaredatch / jaredatchison.com)
6
- Bill Erickson (@billerickson / billerickson.net)
7
- Justin Sternberg (@jtsternberg / dsgnwrks.pro)
8
- Description: This will create metaboxes with custom fields that will blow your mind.
9
- Version: 1.0.0
10
- */
11
-
12
- /**
13
- * Released under the GPL license
14
- * http://www.opensource.org/licenses/gpl-license.php
15
- *
16
- * This is an add-on for WordPress
17
- * http://wordpress.org/
18
- *
19
- * **********************************************************************
20
- * This program is free software; you can redistribute it and/or modify
21
- * it under the terms of the GNU General Public License as published by
22
- * the Free Software Foundation; either version 2 of the License, or
23
- * (at your option) any later version.
24
- *
25
- * This program is distributed in the hope that it will be useful,
26
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
27
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28
- * GNU General Public License for more details.
29
- * **********************************************************************
30
- */
31
-
32
- /************************************************************************
33
- You should not edit the code below or things might explode!
34
- *************************************************************************/
35
-
36
- // Autoload helper classes
37
- spl_autoload_register('timeline_express_MetaBoxes::autoload_helpers');
38
-
39
- // for PHP versions < 5.3
40
- if ( !defined( '__DIR__' ) ) {
41
- define( '__DIR__', dirname( __FILE__ ) );
42
- }
43
-
44
- $meta_boxes = array();
45
- $meta_boxes = apply_filters( 'cmb_meta_boxes' , $meta_boxes );
46
- foreach ( $meta_boxes as $meta_box ) {
47
- $my_box = new timeline_express_MetaBoxes( $meta_box );
48
- }
49
-
50
- /**
51
- * Validate value of meta fields
52
- * Define ALL validation methods inside this class and use the names of these
53
- * methods in the definition of meta boxes (key 'validate_func' of each field)
54
- */
55
- class timeline_express_Meta_Box_Validate {
56
- function check_text( $text ) {
57
- if ($text != 'hello') {
58
- return false;
59
- }
60
- return true;
61
- }
62
- }
63
-
64
- /**
65
- * Defines the url to which is used to load local resources.
66
- * This may need to be filtered for local Window installations.
67
- * If resources do not load, please check the wiki for details.
68
- */
69
- function get_timeline_express_meta_box_url() {
70
-
71
- if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
72
- // Windows
73
- $content_dir = str_replace( '/', DIRECTORY_SEPARATOR, WP_CONTENT_DIR );
74
- $content_url = str_replace( $content_dir, WP_CONTENT_URL, dirname(__FILE__) );
75
- $cmb_url = str_replace( DIRECTORY_SEPARATOR, '/', $content_url );
76
-
77
- } else {
78
- $cmb_url = str_replace(
79
- array(WP_CONTENT_DIR, WP_PLUGIN_DIR),
80
- array(WP_CONTENT_URL, WP_PLUGIN_URL),
81
- dirname( __FILE__ )
82
- );
83
- }
84
-
85
- return trailingslashit( apply_filters('cmb_meta_box_url', $cmb_url ) );
86
- }
87
-
88
- define( 'CMB_META_BOX_URL', get_timeline_express_meta_box_url() );
89
-
90
- /**
91
- * Create meta boxes
92
- */
93
- class timeline_express_MetaBoxes {
94
- protected $_meta_box;
95
- protected $form_id = 'post';
96
- protected static $field = array();
97
- protected static $object_id = 0;
98
- // Type of object being saved. (e.g., post, user, or comment)
99
- protected static $object_type = false;
100
- protected static $is_enqueued = false;
101
- protected static $mb_object_type = 'post';
102
- const CMB_VERSION = '1.0.0';
103
-
104
- /**
105
- * Get started
106
- */
107
- function __construct( $meta_box ) {
108
-
109
- $allow_frontend = apply_filters( 'cmb_allow_frontend', true, $meta_box );
110
-
111
- if ( ! is_admin() && ! $allow_frontend )
112
- return;
113
-
114
- $this->_meta_box = $meta_box;
115
-
116
- self::set_mb_type( $meta_box );
117
-
118
- $types = wp_list_pluck( $meta_box['fields'], 'type' );
119
- $upload = in_array( 'file', $types ) || in_array( 'file_list', $types );
120
-
121
- global $pagenow;
122
-
123
- $show_filters = 'timeline_express_MetaBox_filters';
124
- foreach ( get_class_methods( $show_filters ) as $filter ) {
125
- add_filter( 'cmb_show_on', array( $show_filters, $filter ), 10, 2 );
126
- }
127
-
128
- // register our scripts and styles for cmb
129
- add_action( 'admin_enqueue_scripts', array( $this, 'register_scripts' ), 8 );
130
-
131
- if ( self::get_object_type() == 'post' ) {
132
- add_action( 'admin_menu', array( $this, 'add_metaboxes' ) );
133
- add_action( 'save_post', array( $this, 'save_post' ), 10, 2 );
134
- add_action( 'admin_enqueue_scripts', array( $this, 'do_scripts' ) );
135
-
136
- if ( $upload && in_array( $pagenow, array( 'page.php', 'page-new.php', 'post.php', 'post-new.php' ) ) ) {
137
- add_action( 'admin_head', array( $this, 'add_post_enctype' ) );
138
- }
139
-
140
- }
141
- if ( self::get_object_type() == 'user' ) {
142
-
143
- $priority = 10;
144
- if ( isset( $meta_box['priority'] ) ) {
145
- if ( is_numeric( $meta_box['priority'] ) )
146
- $priority = $meta_box['priority'];
147
- elseif ( $meta_box['priority'] == 'high' )
148
- $priority = 5;
149
- elseif ( $meta_box['priority'] == 'low' )
150
- $priority = 20;
151
- }
152
- add_action( 'show_user_profile', array( $this, 'user_metabox' ), $priority );
153
- add_action( 'edit_user_profile', array( $this, 'user_metabox' ), $priority );
154
-
155
- add_action( 'personal_options_update', array( $this, 'save_user' ) );
156
- add_action( 'edit_user_profile_update', array( $this, 'save_user' ) );
157
- if ( $upload && in_array( $pagenow, array( 'profile.php', 'user-edit.php' ) ) ) {
158
- $this->form_id = 'your-profile';
159
- add_action( 'admin_head', array( $this, 'add_post_enctype' ) );
160
- }
161
- }
162
-
163
- }
164
-
165
- /**
166
- * Autoloads files with classes when needed
167
- * @since 1.0.0
168
- * @param string $class_name Name of the class being requested
169
- */
170
- public static function autoload_helpers( $class_name ) {
171
- if ( class_exists( $class_name, false ) )
172
- return;
173
-
174
- $file = __DIR__ .'/helpers/'. $class_name .'.php';
175
- if ( file_exists( $file ) )
176
- @include( $file );
177
- }
178
-
179
- /**
180
- * Registers scripts and styles for CMB
181
- * @since 1.0.0
182
- */
183
- function register_scripts() {
184
-
185
- // Should only be run once
186
- if ( self::$is_enqueued )
187
- return;
188
-
189
- global $wp_version;
190
- // Only use minified files if SCRIPT_DEBUG is off
191
- $min = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min';
192
-
193
- // scripts required for cmb
194
- $scripts = array( 'jquery', 'jquery-ui-core', 'jquery-ui-datepicker', /*'media-upload', */'cmb-timepicker' );
195
- // styles required for cmb
196
- $styles = array();
197
-
198
- // if we're 3.5 or later, user wp-color-picker
199
- if ( 3.5 <= $wp_version ) {
200
- $scripts[] = 'wp-color-picker';
201
- $styles[] = 'wp-color-picker';
202
- if ( ! is_admin() ) {
203
- // we need to register colorpicker on the front-end
204
- wp_register_script( 'iris', admin_url( 'js/iris.min.js' ), array( 'jquery-ui-draggable', 'jquery-ui-slider', 'jquery-touch-punch' ), self::CMB_VERSION );
205
- wp_register_script( 'wp-color-picker', admin_url( 'js/color-picker.min.js' ), array( 'iris' ), self::CMB_VERSION );
206
- wp_localize_script( 'wp-color-picker', 'wpColorPickerL10n', array(
207
- 'clear' => __( 'Clear' ),
208
- 'defaultString' => __( 'Default' ),
209
- 'pick' => __( 'Select Color' ),
210
- 'current' => __( 'Current Color' ),
211
- ) );
212
- }
213
- } else {
214
- // otherwise use the older 'farbtastic'
215
- $scripts[] = 'farbtastic';
216
- $styles[] = 'farbtastic';
217
- }
218
- wp_register_script( 'cmb-timepicker', CMB_META_BOX_URL . 'js/jquery.timePicker.min.js' );
219
- wp_register_script( 'cmb-scripts', CMB_META_BOX_URL .'js/cmb'. $min .'.js', $scripts, self::CMB_VERSION );
220
-
221
- wp_enqueue_media();
222
-
223
- wp_localize_script( 'cmb-scripts', 'cmb_l10', array(
224
- 'ajax_nonce' => wp_create_nonce( 'ajax_nonce' ),
225
- 'object_id' => self::get_object_id(),
226
- 'object_type' => self::get_object_type(),
227
- 'upload_file' => 'Use this file',
228
- 'remove_image' => 'Remove Image',
229
- 'remove_file' => 'Remove',
230
- 'file' => 'File:',
231
- 'download' => 'Download',
232
- 'ajaxurl' => admin_url( '/admin-ajax.php' ),
233
- ) );
234
-
235
- wp_register_style( 'cmb-styles', CMB_META_BOX_URL . 'style'. $min .'.css', $styles );
236
-
237
- // Ok, we've enqueued our scripts/styles
238
- self::$is_enqueued = true;
239
- }
240
-
241
- /**
242
- * Enqueues scripts and styles for CMB
243
- * @since 1.0.0
244
- */
245
- function do_scripts( $hook ) {
246
- // only enqueue our scripts/styles on the proper pages
247
- if ( $hook == 'post.php' || $hook == 'post-new.php' || $hook == 'page-new.php' || $hook == 'page.php' ) {
248
- wp_enqueue_script( 'cmb-scripts' );
249
-
250
- // default is to show cmb styles on post pages
251
- if ( ! isset( $this->_meta_box['cmb_styles'] ) || $this->_meta_box['cmb_styles'] != false )
252
- wp_enqueue_style( 'cmb-styles' );
253
- }
254
- }
255
-
256
- /**
257
- * Add encoding attribute
258
- */
259
- function add_post_enctype() {
260
- echo '
261
- <script type="text/javascript">
262
- jQuery(document).ready(function(){
263
- jQuery("#'. $this->form_id .'").attr("enctype", "multipart/form-data");
264
- jQuery("#'. $this->form_id .'").attr("encoding", "multipart/form-data");
265
- });
266
- </script>';
267
- }
268
-
269
- /**
270
- * Add metaboxes (to 'post' object type)
271
- */
272
- function add_metaboxes() {
273
- $this->_meta_box['context'] = empty( $this->_meta_box['context'] ) ? 'normal' : $this->_meta_box['context'];
274
- $this->_meta_box['priority'] = empty( $this->_meta_box['priority'] ) ? 'high' : $this->_meta_box['priority'];
275
- $this->_meta_box['show_on'] = empty( $this->_meta_box['show_on'] ) ? array( 'key' => false, 'value' => false ) : $this->_meta_box['show_on'];
276
-
277
- foreach ( $this->_meta_box['pages'] as $page ) {
278
- if ( apply_filters( 'cmb_show_on', true, $this->_meta_box ) )
279
- add_meta_box( $this->_meta_box['id'], $this->_meta_box['title'], array( $this, 'post_metabox' ), $page, $this->_meta_box['context'], $this->_meta_box['priority']) ;
280
- }
281
- }
282
-
283
- /**
284
- * Display metaboxes for a post object
285
- * @since 1.0.0
286
- */
287
- function post_metabox() {
288
- if ( ! $this->_meta_box )
289
- return;
290
-
291
- self::show_form( $this->_meta_box, get_the_ID(), 'post' );
292
-
293
- }
294
-
295
- /**
296
- * Display metaboxes for a user object
297
- * @since 1.0.0
298
- */
299
- function user_metabox() {
300
- if ( ! $this->_meta_box )
301
- return;
302
-
303
- if ( 'user' != self::set_mb_type( $this->_meta_box ) )
304
- return;
305
-
306
- if ( ! apply_filters( 'cmb_show_on', true, $this->_meta_box ) )
307
- return;
308
-
309
- wp_enqueue_script( 'cmb-scripts' );
310
-
311
- // default is to NOT show cmb styles on user profile page
312
- if ( isset( $this->_meta_box['cmb_styles'] ) && $this->_meta_box['cmb_styles'] == true )
313
- wp_enqueue_style( 'cmb-styles' );
314
-
315
- self::show_form( $this->_meta_box );
316
-
317
- }
318
-
319
- /**
320
- * Loops through and displays fields
321
- * @since 1.0.0
322
- * @param array $meta_box Metabox config array
323
- * @param int $object_id Object ID
324
- * @param string $object_type Type of object being saved. (e.g., post, user, or comment)
325
- */
326
- public static function show_form( $meta_box, $object_id = 0, $object_type = '' ) {
327
-
328
- // Set/get type
329
- $object_type = self::set_object_type( $object_type ? $object_type : self::set_mb_type( $meta_box ) );
330
- // Set/get ID
331
- $object_id = self::set_object_id( $object_id ? $object_id : self::get_object_id() );
332
-
333
- // get box types
334
- $types = timeline_express_MetaBox_types::get();
335
-
336
- // Use nonce for verification
337
- echo "\n<!-- Begin CMB Fields -->\n";
338
- wp_nonce_field( self::nonce(), 'wp_meta_box_nonce', false, true );
339
- do_action( 'cmb_before_table', $meta_box, $object_id, $object_type );
340
- echo '<table class="form-table cmb_metabox">';
341
-
342
- foreach ( $meta_box['fields'] as $field ) {
343
-
344
- if ( isset( $field['on_front'] ) && $field['on_front'] == false )
345
- continue;
346
-
347
- self::$field =& $field;
348
-
349
- // Set up blank or default values for empty ones
350
- if ( !isset( $field['name'] ) ) $field['name'] = '';
351
- if ( !isset( $field['desc'] ) ) $field['desc'] = '';
352
- if ( !isset( $field['std'] ) ) $field['std'] = '';
353
- // filter default value
354
- $field['std'] = apply_filters( 'cmb_std_filter', $field['std'], $field, $object_id, $object_type );
355
- if ( 'file' == $field['type'] && !isset( $field['allow'] ) )
356
- $field['allow'] = array( 'url', 'attachment' );
357
- if ( 'file' == $field['type'] && !isset( $field['save_id'] ) )
358
- $field['save_id'] = false;
359
- if ( 'multicheck' == $field['type'] )
360
- $field['multiple'] = true;
361
-
362
- // Allow an override for the field's value
363
- // (assuming no one would want to save 'cmb_override_val' as a value)
364
- $meta = apply_filters( 'cmb_override_meta_value', 'cmb_override_val', $object_id, $field, $object_type );
365
-
366
- // If no override, get our meta
367
- if ( $meta === 'cmb_override_val' )
368
- $meta = get_metadata( $object_type, $object_id, $field['id'], 'multicheck' != $field['type'] /* If multicheck this can be multiple values */ );
369
-
370
- $repeat = isset( $field['repeatable'] ) && $field['repeatable'];
371
- $repeatclass = $repeat ? ' cmb-repeat' : '';
372
- $repeatmethod = $repeat ? '_repeat' : '';
373
-
374
- echo '<tr class="cmb-type-'. sanitize_html_class( $field['type'] ) .' cmb_id_'. sanitize_html_class( $field['id'] ) . $repeatclass .'">';
375
-
376
- if ( $field['type'] == "title" ) {
377
- echo '<td colspan="2">';
378
- } else {
379
- if ( isset( $meta_box['show_names'] ) && $meta_box['show_names'] == true ) {
380
- $style = $object_type == 'post' ? ' style="width:18%"' : '';
381
- echo '<th'. $style .'><label for="', $field['id'], '">', $field['name'], '</label></th>';
382
- } else {
383
- echo '<label style="display:none;" for="', $field['id'], '">', $field['name'], '</label></th>';
384
- }
385
- echo '<td>';
386
- }
387
-
388
- echo empty( $field['before'] ) ? '' : $field['before'];
389
-
390
- call_user_func( array( $types, $field['type'].$repeatmethod ), $field, $meta, $object_id, $object_type );
391
-
392
- echo empty( $field['after'] ) ? '' : $field['after'];
393
-
394
- echo '</td>','</tr>';
395
- }
396
- echo '</table>';
397
- do_action( 'cmb_after_table', $meta_box, $object_id, $object_type );
398
- echo "\n<!-- End CMB Fields -->\n";
399
-
400
- }
401
-
402
- /**
403
- * Save data from metabox
404
- */
405
- function save_post( $post_id, $post ) {
406
-
407
- // check permissions
408
- if (
409
- // check nonce
410
- ! isset( $_POST['wp_meta_box_nonce'] )
411
- || ! wp_verify_nonce( $_POST['wp_meta_box_nonce'], self::nonce() )
412
- // check if autosave
413
- || defined('DOING_AUTOSAVE' ) && DOING_AUTOSAVE
414
- // check user editing permissions
415
- || ( 'page' == $_POST['post_type'] && ! current_user_can( 'edit_page', $post_id ) )
416
- || ! current_user_can( 'edit_post', $post_id )
417
- // get the metabox post_types & compare it to this post_type
418
- || ! in_array( $post->post_type, $this->_meta_box['pages'] )
419
- )
420
- return $post_id;
421
-
422
- self::save_fields( $this->_meta_box, $post_id, 'post' );
423
- }
424
-
425
- /**
426
- * Save data from metabox
427
- */
428
- function save_user( $user_id ) {
429
-
430
- // check permissions
431
- // @todo more hardening?
432
- if (
433
- // check nonce
434
- ! isset( $_POST['wp_meta_box_nonce'] )
435
- || ! wp_verify_nonce( $_POST['wp_meta_box_nonce'], self::nonce() )
436
- )
437
- return $user_id;
438
-
439
- self::save_fields( $this->_meta_box, $user_id, 'user' );
440
- }
441
-
442
- /**
443
- * Loops through and saves field data
444
- * @since 1.0.0
445
- * @param array $meta_box Metabox config array
446
- * @param int $object_id Object ID
447
- * @param string $object_type Type of object being saved. (e.g., post, user, or comment)
448
- */
449
- public static function save_fields( $meta_box, $object_id, $object_type = '' ) {
450
-
451
- $meta_box['show_on'] = empty( $meta_box['show_on'] ) ? array( 'key' => false, 'value' => false ) : $meta_box['show_on'];
452
-
453
- if ( ! apply_filters( 'cmb_show_on', true, $meta_box ) )
454
- return;
455
-
456
- self::set_object_id( $object_id );
457
- // Set/get type
458
- $object_type = self::set_object_type( $object_type ? $object_type : self::set_mb_type( $meta_box ) );
459
-
460
- // save field ids of those that are updated
461
- $updated = array();
462
-
463
- foreach ( $meta_box['fields'] as $field ) {
464
-
465
- self::$field =& $field;
466
-
467
- $name = $field['id'];
468
-
469
- if ( ! isset( $field['multiple'] ) )
470
- $field['multiple'] = ( 'multicheck' == $field['type'] ) ? true : false;
471
-
472
- $old = get_metadata( $object_type, $object_id, $name, !$field['multiple'] /* If multicheck this can be multiple values */ );
473
- $new = isset( $_POST[$field['id']] ) ? $_POST[$field['id']] : null;
474
-
475
- if ( $object_type == 'post' ) {
476
-
477
- if (
478
- isset( $field['taxonomy'] )
479
- && in_array( $field['type'], array( 'taxonomy_select', 'taxonomy_radio', 'taxonomy_multicheck' ) )
480
- )
481
- $new = wp_set_object_terms( $object_id, $new, $field['taxonomy'] );
482
-
483
- }
484
-
485
- if ( isset( $field['repeatable'] ) && $field['repeatable'] && is_array( $new ) ) {
486
- $new = array_filter( $new );
487
- }
488
-
489
- switch ( $field['type'] ) {
490
- case 'text_datetime_timestamp':
491
- $new = strtotime( $new['date'] .' '. $new['time'] );
492
-
493
- if ( $tz_offset = self::field_timezone_offset( $object_id ) )
494
- $new += $tz_offset;
495
- break;
496
- case 'text_datetime_timestamp_timezone':
497
- $tzstring = null;
498
-
499
- if ( array_key_exists( 'timezone', $new ) )
500
- $tzstring = $new['timezone'];
501
-
502
- if ( empty( $tzstring ) )
503
- $tzstring = self::timezone_string();
504
-
505
- $offset = self::timezone_offset( $tzstring );
506
-
507
- if ( substr( $tzstring, 0, 3 ) === 'UTC' )
508
- $tzstring = timezone_name_from_abbr( "", $offset, 0 );
509
-
510
- $new = new DateTime( $new['date'] .' '. $new['time'], new DateTimeZone( $tzstring ) );
511
- $new = serialize( $new );
512
-
513
- break;
514
- case 'text_url':
515
- if ( ! empty( $new ) ) {
516
- $protocols = isset( $field['protocols'] ) ? (array) $field['protocols'] : null;
517
- $new = esc_url_raw( $new, $protocols );
518
- }
519
- break;
520
- case 'textarea':
521
- case 'textarea_small':
522
- $new = htmlspecialchars( $new );
523
- break;
524
- case 'textarea_code':
525
- $new = htmlspecialchars_decode( $new );
526
- break;
527
- case 'text_email':
528
- $new = trim( $new );
529
- $new = is_email( $new ) ? $new : '';
530
- break;
531
- case 'text_date_timestamp':
532
- $new = strtotime( $new );
533
- break;
534
- case 'file':
535
- $_id_name = $field['id'] .'_id';
536
- // get _id old value
537
- $_id_old = get_metadata( $object_type, $object_id, $_id_name, !$field['multiple'] /* If multicheck this can be multiple values */ );
538
-
539
- // If specified NOT to save the file ID
540
- if ( isset( $field['save_id'] ) && ! $field['save_id'] ) {
541
- $_new_id = '';
542
- } else {
543
- // otherwise get the file ID
544
- $_new_id = isset( $_POST[$_id_name] ) ? $_POST[$_id_name] : null;
545
-
546
- // If there is no ID saved yet, try to get it from the url
547
- if ( isset( $_POST[ $field['id'] ] ) && $_POST[ $field['id'] ] && ! $_new_id ) {
548
- $_new_id = self::image_id_from_url( esc_url_raw( $_POST[ $field['id'] ] ) );
549
- }
550
-
551
- }
552
-
553
- if ( $_new_id && $_new_id != $_id_old ) {
554
- $updated[] = $_id_name;
555
- update_metadata( $object_type, $object_id, $_id_name, $_new_id );
556
-
557
- } elseif ( '' == $_new_id && $_id_old ) {
558
- $updated[] = $_id_name;
559
- delete_metadata( $object_type, $object_id, $_id_name, $old );
560
- }
561
- break;
562
- }
563
-
564
- // Allow validation via filter
565
- $new = apply_filters( 'cmb_validate_'. $field['type'], $new, $object_id, $field, $object_type );
566
-
567
- // Allow validation via metabox flag
568
- if ( isset( $field['validate_func'] ) ) {
569
- $ok = call_user_func( array( 'timeline_express_Meta_Box_Validate', $field['validate_func'] ), $new );
570
- // move along when meta value is invalid
571
- if ( $ok === false )
572
- continue;
573
-
574
- } elseif ( $field['multiple'] ) {
575
-
576
- $updated[] = $name;
577
- delete_metadata( $object_type, $object_id, $name );
578
- if ( ! empty( $new ) ) {
579
- foreach ( $new as $add_new ) {
580
- add_metadata( $object_type, $object_id, $name, $add_new, false );
581
- }
582
- }
583
- } elseif ( '' !== $new && $new != $old ) {
584
- $updated[] = $name;
585
- update_metadata( $object_type, $object_id, $name, $new );
586
- } elseif ( '' == $new ) {
587
- $updated[] = $name;
588
- delete_metadata( $object_type, $object_id, $name );
589
- }
590
-
591
- }
592
-
593
- do_action( "cmb_save_{$object_type}_fields", $object_id, $meta_box['id'], $updated, $meta_box );
594
-
595
- }
596
-
597
- /**
598
- * Returns a timezone string representing the default timezone for the site.
599
- *
600
- * Roughly copied from WordPress, as get_option('timezone_string') will return
601
- * and empty string if no value has beens set on the options page.
602
- * A timezone string is required by the wp_timezone_choice() used by the
603
- * select_timezone field.
604
- *
605
- * @since 1.0.0
606
- * @return string Timezone string
607
- */
608
- public static function timezone_string() {
609
- $current_offset = get_option( 'gmt_offset' );
610
- $tzstring = get_option( 'timezone_string' );
611
-
612
- if ( empty( $tzstring ) ) { // Create a UTC+- zone if no timezone string exists
613
- if ( 0 == $current_offset )
614
- $tzstring = 'UTC+0';
615
- elseif ( $current_offset < 0 )
616
- $tzstring = 'UTC' . $current_offset;
617
- else
618
- $tzstring = 'UTC+' . $current_offset;
619
- }
620
-
621
- return $tzstring;
622
- }
623
-
624
- /**
625
- * Returns time string offset by timezone
626
- * @since 1.0.0
627
- * @param string $tzstring Time string
628
- * @return string Offset time string
629
- */
630
- public static function timezone_offset( $tzstring ) {
631
- if ( !empty( $tzstring ) ) {
632
-
633
- if ( substr( $tzstring, 0, 3 ) === 'UTC' ) {
634
- $tzstring = str_replace( array( ':15',':30',':45' ), array( '.25','.5','.75' ), $tzstring );
635
- return intval( floatval( substr( $tzstring, 3 ) ) * HOUR_IN_SECONDS );
636
- }
637
-
638
- $date_time_zone_selected = new DateTimeZone( $tzstring );
639
- $tz_offset = timezone_offset_get( $date_time_zone_selected, date_create() );
640
-
641
- return $tz_offset;
642
- }
643
-
644
- return 0;
645
- }
646
-
647
- /**
648
- * Offset a time value based on timezone
649
- * @since 1.0.0
650
- * @param integer $object_id Object ID
651
- * @return string Offset time string
652
- */
653
- public static function field_timezone_offset( $object_id = 0 ) {
654
-
655
- $tzstring = self::field_timezone( $object_id );
656
-
657
- return self::timezone_offset( $tzstring );
658
- }
659
-
660
- /**
661
- * Return timezone string
662
- * @since 1.0.0
663
- * @param integer $object_id Object ID
664
- * @return string Timezone string
665
- */
666
- public static function field_timezone( $object_id = 0 ) {
667
- $tzstring = null;
668
- if ( ! ( $object_id = self::get_object_id( $object_id ) ) )
669
- return $tzstring;
670
-
671
- if ( array_key_exists( 'timezone', self::$field ) && self::$field['timezone'] ) {
672
- $tzstring = self::$field['timezone'];
673
- } else if ( array_key_exists( 'timezone_meta_key', self::$field ) && self::$field['timezone_meta_key'] ) {
674
- $timezone_meta_key = self::$field['timezone_meta_key'];
675
-
676
- $tzstring = get_metadata( self::get_mb_type(), $object_id, $timezone_meta_key, true );
677
-
678
- return $tzstring;
679
- }
680
-
681
- return false;
682
- }
683
-
684
- /**
685
- * Get object id from global space if no id is provided
686
- * @since 1.0.0
687
- * @param integer $object_id Object ID
688
- * @return integer $object_id Object ID
689
- */
690
- public static function get_object_id( $object_id = 0 ) {
691
-
692
- if ( $object_id )
693
- return $object_id;
694
-
695
- if ( self::$object_id )
696
- return self::$object_id;
697
-
698
- // Try to get our object ID from the global space
699
- switch ( self::get_object_type() ) {
700
- case 'user':
701
- $object_id = isset( $GLOBALS['user_ID'] ) ? $GLOBALS['user_ID'] : $object_id;
702
- $object_id = isset( $_REQUEST['user_id'] ) ? $_REQUEST['user_id'] : $object_id;
703
- break;
704
-
705
- default:
706
- $has_id = @get_the_id();
707
- $object_id = $has_id ? $has_id : $object_id;
708
- $object_id = isset( $GLOBALS['post']->ID ) ? $GLOBALS['post']->ID : $object_id;
709
- $object_id = isset( $_REQUEST['post'] ) ? $_REQUEST['post'] : $object_id;
710
- break;
711
- }
712
-
713
- // reset to id or 0
714
- self::set_object_id( $object_id ? $object_id : 0 );
715
-
716
- return self::$object_id;
717
- }
718
-
719
- /**
720
- * Explicitly Set object id
721
- * @since 1.0.0
722
- * @param integer $object_id Object ID
723
- * @return integer $object_id Object ID
724
- */
725
- public static function set_object_id( $object_id ) {
726
- return self::$object_id = $object_id;
727
- }
728
-
729
- /**
730
- * Sets the $object_type based on metabox settings
731
- * @since 1.0.0
732
- * @param array|string $meta_box Metabox config array or explicit setting
733
- * @return string Object type
734
- */
735
- public static function set_mb_type( $meta_box ) {
736
-
737
- if ( is_string( $meta_box ) ) {
738
- self::$mb_object_type = $meta_box;
739
- return self::get_mb_type();
740
- }
741
-
742
- if ( ! isset( $meta_box['pages'] ) )
743
- return self::get_mb_type();
744
-
745
- $type = false;
746
- // check if 'pages' is a string
747
- if ( is_string( $meta_box['pages'] ) )
748
- $type = $meta_box['pages'];
749
- // if it's an array of one, extract it
750
- elseif ( is_array( $meta_box['pages'] ) && count( $meta_box['pages'] === 1 ) )
751
- $type = is_string( end( $meta_box['pages'] ) ) ? end( $meta_box['pages'] ) : false;
752
-
753
- if ( !$type )
754
- return self::get_mb_type();
755
-
756
- // Get our object type
757
- if ( 'user' == $type )
758
- self::$mb_object_type = 'user';
759
- elseif ( 'comment' == $type )
760
- self::$mb_object_type = 'comment';
761
- else
762
- self::$mb_object_type = 'post';
763
-
764
- return self::get_mb_type();
765
- }
766
-
767
- /**
768
- * Returns the object type
769
- * @since 1.0.0
770
- * @return string Object type
771
- */
772
- public static function get_object_type() {
773
- if ( self::$object_type )
774
- return self::$object_type;
775
-
776
- global $pagenow;
777
-
778
- if (
779
- $pagenow == 'user-edit.php'
780
- || $pagenow == 'profile.php'
781
- )
782
- self::set_object_type( 'user' );
783
-
784
- elseif (
785
- $pagenow == 'edit-comments.php'
786
- || $pagenow == 'comment.php'
787
- )
788
- self::set_object_type( 'comment' );
789
- else
790
- self::set_object_type( 'post' );
791
-
792
- return self::$object_type;
793
- }
794
-
795
- /**
796
- * Sets the object type
797
- * @since 1.0.0
798
- * @return string Object type
799
- */
800
- public static function set_object_type( $object_type ) {
801
- return self::$object_type = $object_type;
802
- }
803
-
804
- /**
805
- * Returns the object type
806
- * @since 1.0.0
807
- * @return string Object type
808
- */
809
- public static function get_mb_type() {
810
- return self::$mb_object_type;
811
- }
812
-
813
- /**
814
- * Returns the nonce value for wp_meta_box_nonce
815
- * @since 1.0.0
816
- * @return string Nonce value
817
- */
818
- public static function nonce() {
819
- return basename( __FILE__ );
820
- }
821
-
822
- /**
823
- * Utility method that attempts to get an attachment's ID by it's url
824
- * @since 1.0.0
825
- * @param string $img_url Attachment url
826
- * @return mixed Attachment ID or false
827
- */
828
- public static function image_id_from_url( $img_url ) {
829
- global $wpdb;
830
-
831
- // Get just the file name
832
- if ( false !== strpos( $img_url, '/' ) ) {
833
- $explode = explode( '/', $img_url );
834
- $img_url = end( $explode );
835
- }
836
-
837
- // And search for a fuzzy match of the file name
838
- $attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid LIKE '%%%s%%' LIMIT 1;", $img_url ) );
839
-
840
- // If we found an attachement ID, return it
841
- if ( !empty( $attachment ) && is_array( $attachment ) )
842
- return $attachment[0];
843
-
844
- // No luck
845
- return false;
846
- }
847
-
848
- }
849
-
850
- // Handle oembed Ajax
851
- add_action( 'wp_ajax_cmb_oembed_handler', array( 'timeline_express_MetaBox_ajax', 'oembed_handler' ) );
852
- add_action( 'wp_ajax_nopriv_cmb_oembed_handler', array( 'timeline_express_MetaBox_ajax', 'oembed_handler' ) );
853
-
854
- /**
855
- * Loop and output multiple metaboxes
856
- * @since 1.0.0
857
- * @param array $meta_boxes Metaboxes config array
858
- * @param int $object_id Object ID
859
- */
860
- function timeline_express_print_metaboxes( $meta_boxes, $object_id ) {
861
- foreach ( (array) $meta_boxes as $meta_box ) {
862
- timeline_express_print_metaboxe( $meta_box, $object_id );
863
- }
864
- }
865
-
866
- /**
867
- * Output a metabox
868
- * @since 1.0.0
869
- * @param array $meta_box Metabox config array
870
- * @param int $object_id Object ID
871
- */
872
- function timeline_express_print_metaboxe( $meta_box, $object_id ) {
873
- $cmb = new timeline_express_MetaBoxes( $meta_box );
874
- if ( $cmb ) {
875
-
876
- timeline_express_MetaBoxes::set_object_id( $object_id );
877
-
878
- if ( ! wp_script_is( 'cmb-scripts', 'registered' ) )
879
- $cmb->register_scripts();
880
-
881
- wp_enqueue_script( 'cmb-scripts' );
882
-
883
- // default is to show cmb styles
884
- if ( ! isset( $meta_box['cmb_styles'] ) || $meta_box['cmb_styles'] != false )
885
- wp_enqueue_style( 'cmb-styles' );
886
-
887
- timeline_express_MetaBoxes::show_form( $meta_box );
888
- }
889
-
890
- }
891
-
892
- /**
893
- * Saves a particular metabox's fields
894
- * @since 1.0.0
895
- * @param array $meta_box Metabox config array
896
- * @param int $object_id Object ID
897
- */
898
- function timeline_express_save_metabox_fields( $meta_box, $object_id ) {
899
- timeline_express_MetaBoxes::save_fields( $meta_box, $object_id );
900
- }
901
-
902
- /**
903
- * Display a metabox form & save it on submission
904
- * @since 1.0.0
905
- * @param array $meta_box Metabox config array
906
- * @param int $object_id Object ID
907
- * @param boolean $return Whether to return or echo form
908
- * @return string CMB html form markup
909
- */
910
- function timeline_express_metabox_form( $meta_box, $object_id, $echo = true ) {
911
-
912
- // Make sure that our object type is explicitly set by the metabox config
913
- timeline_express_MetaBoxes::set_object_type( timeline_express_MetaBoxes::set_mb_type( $meta_box ) );
914
-
915
- // Save the metabox if it's been submitted
916
- // check permissions
917
- // @todo more hardening?
918
- if (
919
- // check nonce
920
- isset( $_POST['submit-cmb'], $_POST['object_id'], $_POST['wp_meta_box_nonce'] )
921
- && wp_verify_nonce( $_POST['wp_meta_box_nonce'], timeline_express_MetaBoxes::nonce() )
922
- && $_POST['object_id'] == $object_id
923
- )
924
- timeline_express_save_metabox_fields( $meta_box, $object_id );
925
-
926
- // Show specific metabox form
927
-
928
- // Get cmb form
929
- ob_start();
930
- timeline_express_print_metaboxe( $meta_box, $object_id );
931
- $form = ob_get_contents();
932
- ob_end_clean();
933
-
934
- $form_format = apply_filters( 'cmb_frontend_form_format', '<form class="cmb-form" method="post" id="%s" enctype="multipart/form-data" encoding="multipart/form-data"><input type="hidden" name="object_id" value="%s">%s<input type="submit" name="submit-cmb" value="%s"></form>', $object_id, $meta_box, $form );
935
-
936
- $form = sprintf( $form_format, $meta_box['id'], $object_id, $form, __( 'Save', 'cmb' ) );
937
-
938
- if ( $echo )
939
- echo $form;
940
-
941
- return $form;
942
- }
943
-
944
- // End. That's it, folks! //
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/metabox/js/cmb.js DELETED
@@ -1,335 +0,0 @@
1
- /**
2
- * Controls the behaviours of custom metabox fields.
3
- *
4
- * @author Andrew Norcross
5
- * @author Jared Atchison
6
- * @author Bill Erickson
7
- * @author Justin Sternberg
8
- * @see https://github.com/jaredatch/Custom-Metaboxes-and-Fields-for-WordPress
9
- */
10
-
11
- /*jslint browser: true, devel: true, indent: 4, maxerr: 50, sub: true */
12
- /*global jQuery, tb_show, tb_remove */
13
-
14
- /**
15
- * Custom jQuery for Custom Metaboxes and Fields
16
- */
17
- jQuery(document).ready( function($) {
18
- 'use strict';
19
-
20
- var formfield;
21
- // Uploading files
22
- var file_frames = {};
23
- var iterator = 0;
24
-
25
- /**
26
- * Initialize timepicker (this will be moved inline in a future release)
27
- */
28
- $('.cmb_timepicker').each( function() {
29
- $('#' + jQuery(this).attr('id')).timePicker({
30
- startTime: "00:00",
31
- endTime: "23:59",
32
- show24Hours: false,
33
- separator: ':',
34
- step: 30
35
- });
36
- });
37
-
38
- /**
39
- * Initialize jQuery UI datepicker (this will be moved inline in a future release)
40
- */
41
- $('.cmb_datepicker').each( function() {
42
- $('#' + jQuery(this).attr('id')).datepicker();
43
- // $('#' + jQuery(this).attr('id')).datepicker({ dateFormat: 'yy-mm-dd' });
44
- // For more options see http://jqueryui.com/demos/datepicker/#option-dateFormat
45
- });
46
- // Wrap date picker in class to narrow the scope of jQuery UI CSS and prevent conflicts
47
- $("#ui-datepicker-div").wrap('<div class="cmb_element" />');
48
-
49
- /**
50
- * Initialize color picker
51
- */
52
- if (typeof jQuery.wp === 'object' && typeof jQuery.wp.wpColorPicker === 'function') {
53
- $('input:text.cmb_colorpicker').wpColorPicker();
54
- } else {
55
- $('input:text.cmb_colorpicker').each( function(i) {
56
- $(this).after('<div id="picker-' + i + '" style="z-index: 1000; background: #EEE; border: 1px solid #CCC; position: absolute; display: block;"></div>');
57
- $('#picker-' + i).hide().farbtastic($(this));
58
- })
59
- .focus( function() {
60
- $(this).next().show();
61
- })
62
- .blur( function() {
63
- $(this).next().hide();
64
- });
65
- }
66
-
67
- /**
68
- * File and image upload handling
69
- */
70
-
71
-
72
- $('.cmb_metabox')
73
- .on( 'change', '.cmb_upload_file', function() {
74
- formfield = $(this).attr('name');
75
- $('#' + formfield + '_id').val("");
76
- })
77
- .on( 'click', '.cmb_upload_button', function(event) {
78
-
79
- event.preventDefault();
80
-
81
- var $self = $(this);
82
- formfield = $self.prev('input').attr('name');
83
- var $formfield = $('#'+formfield);
84
- var uploadStatus = true;
85
- var attachment = true;
86
- var isList = $self.hasClass( 'cmb_upload_list' );
87
-
88
-
89
- // If this field's media frame already exists, reopen it.
90
- if ( formfield in file_frames ) {
91
- file_frames[formfield].open();
92
- return;
93
- }
94
-
95
- // Create the media frame.
96
- file_frames[formfield] = wp.media.frames.file_frame = wp.media({
97
- title: $('label[for=' + formfield + ']').text(),
98
- button: {
99
- text: window.cmb_l10.upload_file
100
- },
101
- multiple: isList ? true : false
102
- });
103
-
104
- // When an file is selected, run a callback.
105
- file_frames[formfield].on( 'select', function() {
106
-
107
-
108
- if ( isList ) {
109
-
110
- // Get all of our selected files
111
- attachment = file_frames[formfield].state().get('selection').toJSON();
112
-
113
- $formfield.val(attachment.url);
114
- $('#'+ formfield +'_id').val(attachment.id);
115
-
116
- // Setup our fileGroup array
117
- var fileGroup = [];
118
-
119
- // Loop through each attachment
120
- $( attachment ).each( function() {
121
- if ( this.type && this.type === 'image' ) {
122
- // image preview
123
- uploadStatus = '<li class="img_status">'+
124
- '<img width="50" height="50" src="' + this.url + '" class="attachment-50x50" alt="'+ this.filename +'">'+
125
- '<p><a href="#" class="cmb_remove_file_button" rel="'+ formfield +'['+ this.id +']">'+ cmb_l10.remove_image +'</a></p>'+
126
- '<input type="hidden" id="filelist-'+ this.id +'" name="'+ formfield +'['+ this.id +']" value="' + this.url + '">'+
127
- '</li>';
128
-
129
- } else {
130
- // Standard generic output if it's not an image.
131
- uploadStatus = '<li>'+ cmb_l10.file +' <strong>'+ this.filename +'</strong>&nbsp;&nbsp;&nbsp; (<a href="' + this.url + '" target="_blank" rel="external">'+ cmb_l10.download +'</a> / <a href="#" class="cmb_remove_file_button" rel="'+ formfield +'['+ this.id +']">'+ cmb_l10.remove_file +'</a>)'+
132
- '<input type="hidden" id="filelist-'+ this.id +'" name="'+ formfield +'['+ this.id +']" value="' + this.url + '">'+
133
- '</li>';
134
-
135
- }
136
-
137
- // Add our file to our fileGroup array
138
- fileGroup.push( uploadStatus );
139
- });
140
-
141
- // Append each item from our fileGroup array to .cmb_media_status
142
- $( fileGroup ).each( function() {
143
- $formfield.siblings('.cmb_media_status').slideDown().append(this);
144
- });
145
-
146
- } else {
147
-
148
- // Only get one file from the uploader
149
- attachment = file_frames[formfield].state().get('selection').first().toJSON();
150
-
151
- $formfield.val(attachment.url);
152
- $('#'+ formfield +'_id').val(attachment.id);
153
-
154
- if ( attachment.type && attachment.type === 'image' ) {
155
- // image preview
156
- uploadStatus = '<div class="img_status"><img style="max-width: 350px; width: 100%; height: auto;" src="' + attachment.url + '" alt="'+ attachment.filename +'" title="'+ attachment.filename +'" /><p><a href="#" class="cmb_remove_file_button" rel="' + formfield + '">'+ cmb_l10.remove_image +'</a></p></div>';
157
- } else {
158
- // Standard generic output if it's not an image.
159
- uploadStatus = cmb_l10.file +' <strong>'+ attachment.filename +'</strong>&nbsp;&nbsp;&nbsp; (<a href="'+ attachment.url +'" target="_blank" rel="external">'+ cmb_l10.download +'</a> / <a href="#" class="cmb_remove_file_button" rel="'+ formfield +'">'+ cmb_l10.remove_file +'</a>)';
160
- }
161
-
162
- // add/display our output
163
- $formfield.siblings('.cmb_media_status').slideDown().html(uploadStatus);
164
- }
165
- });
166
-
167
- // Finally, open the modal
168
- file_frames[formfield].open();
169
- })
170
- .on( 'click', '.cmb_remove_file_button', function(event) {
171
- var $self = $(this);
172
- if ( $self.is( '.attach_list .cmb_remove_file_button' ) ){
173
- $self.parents('li').remove();
174
- return false;
175
- }
176
- formfield = $self.attr('rel');
177
- var $container = $self.parents('.img_status');
178
-
179
- $('input#' + formfield).val('');
180
- $('input#' + formfield + '_id').val('');
181
- if ( ! $container.length ) {
182
- $self.parents('.cmb_media_status').html('');
183
- } else {
184
- $container.html('');
185
- }
186
- return false;
187
- })
188
- .on( 'click', '.add-row-button', function(e) {
189
-
190
- e.preventDefault();
191
- self = $(this);
192
-
193
- var tableselector = '#'+ self.data('selector');
194
- var $table = $(tableselector);
195
- var row = $('.empty-row', $table).clone(true);
196
- row.removeClass('empty-row').addClass('repeat-row');
197
- row.insertBefore( tableselector +' tbody>tr:last' );
198
- var input = $('input.cmb_datepicker',row);
199
- var id = input.attr('id');
200
- input.attr('id', id + iterator );
201
- iterator++;
202
-
203
- // @todo Make a colorpicker field repeatable
204
- // row.find('.wp-color-result').remove();
205
- // row.find('input:text.cmb_colorpicker').wpColorPicker();
206
-
207
- })
208
- .on( 'click', '.remove-row-button', function(e) {
209
- e.preventDefault();
210
- var $self = $(this);
211
- var $parent = $self.parents('.cmb-repeat-table');
212
- console.log( 'number of tbodys', $parent.length );
213
- console.log( 'number of trs', $('tr', $parent).length );
214
- if ( $('tr', $parent).length > 2 )
215
- $self.parents('.cmb-repeat-table tr').remove();
216
- })
217
-
218
- /**
219
- * Ajax oEmbed display
220
- */
221
-
222
- // ajax when typing
223
- .on( 'keyup', '.cmb_oembed', function(event) {
224
- // fire our ajax function
225
- doCMBajax($(this), event);
226
- });
227
-
228
- // ajax on paste
229
- $('.cmb_oembed').bind( 'paste', function(e) {
230
- var pasteitem = $(this);
231
- // paste event is fired before the value is filled, so wait a bit
232
- setTimeout( function() {
233
- // fire our ajax function
234
- doCMBajax(pasteitem, 'paste');
235
- }, 100);
236
- }).blur( function() {
237
- // when leaving the input
238
- setTimeout( function() {
239
- // if it's been 2 seconds, hide our spinner
240
- $('.postbox table.cmb_metabox .cmb-spinner').hide();
241
- }, 2000);
242
- });
243
-
244
- // function for running our ajax
245
- function doCMBajax(obj, e) {
246
- // get typed value
247
- var oembed_url = obj.val();
248
- // only proceed if the field contains more than 6 characters
249
- if (oembed_url.length < 6)
250
- return;
251
-
252
- // only proceed if the user has pasted, pressed a number, letter, or whitelisted characters
253
- if (e === 'paste' || e.which <= 90 && e.which >= 48 || e.which >= 96 && e.which <= 111 || e.which == 8 || e.which == 9 || e.which == 187 || e.which == 190) {
254
-
255
- // get field id
256
- var field_id = obj.attr('id');
257
- // get our inputs context for pinpointing
258
- var context = obj.parents('.cmb_metabox tr td');
259
-
260
- var embed_container = $('.embed_status', context);
261
- var oembed_width = obj.width();
262
- var child_el = $(':first-child', embed_container);
263
-
264
- oembed_width = ( embed_container.length && child_el.length )
265
- ? child_el.width()
266
- : obj.width();
267
-
268
- // show our spinner
269
- $('.cmb-spinner', context).show();
270
- // clear out previous results
271
- $('.embed_wrap', context).html('');
272
- // and run our ajax function
273
- setTimeout( function() {
274
- // if they haven't typed in 500 ms
275
- if ($('.cmb_oembed:focus').val() != oembed_url)
276
- return;
277
- $.ajax({
278
- type : 'post',
279
- dataType : 'json',
280
- url : window.cmb_l10.ajaxurl,
281
- data : {
282
- 'action': 'cmb_oembed_handler',
283
- 'oembed_url': oembed_url,
284
- 'oembed_width': oembed_width > 300 ? oembed_width : 300,
285
- 'field_id': field_id,
286
- 'object_id': window.cmb_l10.object_id,
287
- 'object_type': window.cmb_l10.object_type,
288
- 'cmb_ajax_nonce': window.cmb_l10.ajax_nonce
289
- },
290
- success: function(response) {
291
- // Make sure we have a response id
292
- if (typeof response.id === 'undefined')
293
- return;
294
-
295
- // hide our spinner
296
- $('.cmb-spinner', context).hide();
297
- // and populate our results from ajax response
298
- $('.embed_wrap', context).html(response.result);
299
- }
300
- });
301
-
302
- }, 500);
303
- }
304
- }
305
-
306
- /**
307
- * Resize oEmbed videos to fit in their respective metaboxes
308
- */
309
- function resizeoEmbeds() {
310
- $('table.cmb_metabox').each( function( index ) {
311
- var self = $(this);
312
- var parents = self.parents('.inside');
313
- if ( ! parents.length )
314
- return true; // continue
315
-
316
- var tWidth = parents.width();
317
- var newWidth = Math.round((tWidth * 0.82)*0.97) - 30;
318
- if ( newWidth > 639 )
319
- return true; // continue
320
-
321
- var child_el = $('.cmb-type-oembed .embed_status', self).children().first();
322
- var iwidth = child_el.width();
323
- var iheight = child_el.height();
324
- var newHeight = Math.round((newWidth * iheight)/iwidth);
325
- child_el.width(newWidth).height(newHeight);
326
-
327
- });
328
- }
329
-
330
- // on pageload
331
- setTimeout( resizeoEmbeds, 500);
332
- // and on window resize
333
- $(window).on( 'resize', resizeoEmbeds );
334
-
335
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/metabox/js/cmb.min.js DELETED
@@ -1,24 +0,0 @@
1
- jQuery(document).ready(function(e){var b;var d={};var c=0;e(".cmb_timepicker").each(function(){e("#"+jQuery(this).attr("id")).timePicker({startTime:"00:00",endTime:"23:59",show24Hours:false,separator:":",step:30});
2
- });e(".cmb_datepicker").each(function(){e("#"+jQuery(this).attr("id")).datepicker();});e("#ui-datepicker-div").wrap('<div class="cmb_element" />');if(typeof jQuery.wp==="object"&&typeof jQuery.wp.wpColorPicker==="function"){e("input:text.cmb_colorpicker").wpColorPicker();
3
- }else{e("input:text.cmb_colorpicker").each(function(g){e(this).after('<div id="picker-'+g+'" style="z-index: 1000; background: #EEE; border: 1px solid #CCC; position: absolute; display: block;"></div>');
4
- e("#picker-"+g).hide().farbtastic(e(this));}).focus(function(){e(this).next().show();}).blur(function(){e(this).next().hide();});}e(".cmb_metabox").on("change",".cmb_upload_file",function(){b=e(this).attr("name");
5
- e("#"+b+"_id").val("");}).on("click",".cmb_upload_button",function(h){h.preventDefault();var l=e(this);b=l.prev("input").attr("name");var k=e("#"+b);var g=true;
6
- var j=true;var i=l.hasClass("cmb_upload_list");if(b in d){d[b].open();return;}d[b]=wp.media.frames.file_frame=wp.media({title:e("label[for="+b+"]").text(),button:{text:window.cmb_l10.upload_file},multiple:i?true:false});
7
- d[b].on("select",function(){if(i){j=d[b].state().get("selection").toJSON();k.val(j.url);e("#"+b+"_id").val(j.id);var m=[];e(j).each(function(){if(this.type&&this.type==="image"){g='<li class="img_status"><img width="50" height="50" src="'+this.url+'" class="attachment-50x50" alt="'+this.filename+'"><p><a href="#" class="cmb_remove_file_button" rel="'+b+"["+this.id+']">'+cmb_l10.remove_image+'</a></p><input type="hidden" id="filelist-'+this.id+'" name="'+b+"["+this.id+']" value="'+this.url+'"></li>';
8
- }else{g="<li>"+cmb_l10.file+" <strong>"+this.filename+'</strong>&nbsp;&nbsp;&nbsp; (<a href="'+this.url+'" target="_blank" rel="external">'+cmb_l10.download+'</a> / <a href="#" class="cmb_remove_file_button" rel="'+b+"["+this.id+']">'+cmb_l10.remove_file+'</a>)<input type="hidden" id="filelist-'+this.id+'" name="'+b+"["+this.id+']" value="'+this.url+'"></li>';
9
- }m.push(g);});e(m).each(function(){k.siblings(".cmb_media_status").slideDown().append(this);});}else{j=d[b].state().get("selection").first().toJSON();k.val(j.url);
10
- e("#"+b+"_id").val(j.id);if(j.type&&j.type==="image"){g='<div class="img_status"><img style="max-width: 350px; width: 100%; height: auto;" src="'+j.url+'" alt="'+j.filename+'" title="'+j.filename+'" /><p><a href="#" class="cmb_remove_file_button" rel="'+b+'">'+cmb_l10.remove_image+"</a></p></div>";
11
- }else{g=cmb_l10.file+" <strong>"+j.filename+'</strong>&nbsp;&nbsp;&nbsp; (<a href="'+j.url+'" target="_blank" rel="external">'+cmb_l10.download+'</a> / <a href="#" class="cmb_remove_file_button" rel="'+b+'">'+cmb_l10.remove_file+"</a>)";
12
- }k.siblings(".cmb_media_status").slideDown().html(g);}});d[b].open();}).on("click",".cmb_remove_file_button",function(g){var i=e(this);if(i.is(".attach_list .cmb_remove_file_button")){i.parents("li").remove();
13
- return false;}b=i.attr("rel");var h=i.parents(".img_status");e("input#"+b).val("");e("input#"+b+"_id").val("");if(!h.length){i.parents(".cmb_media_status").html("");
14
- }else{h.html("");}return false;}).on("click",".add-row-button",function(j){j.preventDefault();self=e(this);var i="#"+self.data("selector");var h=e(i);var k=e(".empty-row",h).clone(true);
15
- k.removeClass("empty-row").addClass("repeat-row");k.insertBefore(i+" tbody>tr:last");var g=e("input.cmb_datepicker",k);var l=g.attr("id");g.attr("id",l+c);
16
- c++;}).on("click",".remove-row-button",function(h){h.preventDefault();var i=e(this);var g=i.parents(".cmb-repeat-table");console.log("number of tbodys",g.length);
17
- console.log("number of trs",e("tr",g).length);if(e("tr",g).length>2){i.parents(".cmb-repeat-table tr").remove();}}).on("keyup",".cmb_oembed",function(g){f(e(this),g);
18
- });e(".cmb_oembed").bind("paste",function(h){var g=e(this);setTimeout(function(){f(g,"paste");},100);}).blur(function(){setTimeout(function(){e(".postbox table.cmb_metabox .cmb-spinner").hide();
19
- },2000);});function f(n,m){var i=n.val();if(i.length<6){return;}if(m==="paste"||m.which<=90&&m.which>=48||m.which>=96&&m.which<=111||m.which==8||m.which==9||m.which==187||m.which==190){var k=n.attr("id");
20
- var h=n.parents(".cmb_metabox tr td");var l=e(".embed_status",h);var g=n.width();var j=e(":first-child",l);g=(l.length&&j.length)?j.width():n.width();e(".cmb-spinner",h).show();
21
- e(".embed_wrap",h).html("");setTimeout(function(){if(e(".cmb_oembed:focus").val()!=i){return;}e.ajax({type:"post",dataType:"json",url:window.cmb_l10.ajaxurl,data:{action:"cmb_oembed_handler",oembed_url:i,oembed_width:g>300?g:300,field_id:k,object_id:window.cmb_l10.object_id,object_type:window.cmb_l10.object_type,cmb_ajax_nonce:window.cmb_l10.ajax_nonce},success:function(o){if(typeof o.id==="undefined"){return;
22
- }e(".cmb-spinner",h).hide();e(".embed_wrap",h).html(o.result);}});},500);}}function a(){e("table.cmb_metabox").each(function(l){var o=e(this);var n=o.parents(".inside");
23
- if(!n.length){return true;}var k=n.width();var j=Math.round((k*0.82)*0.97)-30;if(j>639){return true;}var h=e(".cmb-type-oembed .embed_status",o).children().first();
24
- var i=h.width();var m=h.height();var g=Math.round((j*m)/i);h.width(j).height(g);});}setTimeout(a,500);e(window).on("resize",a);});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/metabox/readme.md DELETED
@@ -1,159 +0,0 @@
1
- # Custom Metaboxes and Fields for WordPress
2
-
3
- **Contributors**:
4
-
5
- * Andrew Norcross ( [@norcross](http://twitter.com/norcross ) / [andrewnorcross.com](http://andrewnorcross.com/) )
6
- * Jared Atchison ( [@jaredatch](http://twitter.com/jaredatch ) / [jaredatchison.com](http://jaredatchison.com/) )
7
- * Bill Erickson ( [@billerickson](http://twitter.com/billerickson ) / [billerickson.net](http://billerickson.net/) )
8
- * Justin Sternberg ( [@jtsternberg](http://twitter.com/jtsternberg ) / [dsgnwrks.pro](http://dsgnwrks.pro) )
9
-
10
- **Version**: 1.0.0
11
- **Requires at least**: 3.5
12
- **Tested up to**: 3.8
13
- **License**: GPLv2
14
-
15
- ## Description
16
-
17
- Custom Metaboxes and Fields (CMB for short) will create metaboxes with custom fields that will blow your mind.
18
-
19
- Now in version 1.0.0:
20
- * Bring your metaboxes to the frontend!
21
- * Create metaboxes to handle user meta and display them on user profile add/edit pages! Or even on the front-end!
22
-
23
- ##### Links
24
- * [Github project page](https://github.com/webdevstudios/Custom-Metaboxes-and-Fields-for-WordPress)
25
- * [Documentation (GitHub wiki)](https://github.com/webdevstudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki)
26
-
27
- ##### Field Types:
28
- * text (optionally repeatable)
29
- * text small (optionally repeatable)
30
- * text medium (optionally repeatable)
31
- * text url (optionally repeatable)
32
- * text email (optionally repeatable)
33
- * text money (optionally repeatable)
34
- * date picker
35
- * date picker (unix timestamp)
36
- * date time picker combo (unix timestamp)
37
- * date time picker with time zone combo (serialized DateTime object)
38
- * time zone dropdown
39
- * time picker
40
- * color picker
41
- * textarea
42
- * textarea small
43
- * textarea code
44
- * select
45
- * radio
46
- * radio inline
47
- * taxonomy radio
48
- * taxonomy select
49
- * checkbox
50
- * multicheck
51
- * WYSIWYG/TinyMCE
52
- * Image/file upload
53
- * oEmbed
54
-
55
- [More on field types (GitHub wiki)](https://github.com/webdevstudios/Custom-Metaboxes-and-Fields-for-WordPress/wiki/Field-Types)
56
-
57
- ## Installation
58
-
59
- This script is easy to install. If you can't figure it out you probably shouldn't be using it.
60
-
61
- 1. Place `metabox` directory inside of your (activated) theme. E.g. inside `/themes/twentyten/lib/metabox/`.
62
- 2. Include `init.php` (preferably on the 'init' WordPress hook).
63
- 3. See `example-functions.php` for further guidance.
64
- 4. Profit.
65
-
66
- ## Known Issues
67
-
68
- * Problem inserting file url inside field for image with caption (issue #50) May be fixed, needs testing.
69
- * `CMB_META_BOX_URL` does not define properly in WAMP/XAMP (Windows) (issue #31) May be fixed, needs testing.
70
- * Metabox containing WYSIWYG editor cannot be moved (this is a TinyMCE issue)
71
-
72
- ## To-do
73
- * Fix known issues (above)
74
- * clean up code
75
- * improve inline documentation
76
- * move timepicker and datepicker jQuery inline
77
- * support for multiple configurable timepickers/datepickers
78
- * add ability to save fields in a single custom field
79
- * add ability to mark fields as required
80
- * add ability to define `placeholder` text
81
- * repeatable fields (halfway there)
82
- * look at possiblity of tabs
83
- * look at preserving taxonomy hierarchies
84
-
85
- ## Changelog
86
-
87
- ### 1.0.0
88
- * Added `text_datetime_timestamp_timezone` type, a datetime combo field with an additional timezone drop down, props [@dessibelle](https://github.com/dessibelle)
89
- * Added `select_timezone` type, a standalone time zone select dropdown. The time zone select can be used with standalone `text_datetime_timestamp` if desired. Props [@dessibelle](https://github.com/dessibelle)
90
- * Added `text_url` type, a basic url field. Props [@dessibelle](https://github.com/dessibelle)
91
- * Added `text_email` type, a basic email field. Props [@dessibelle](https://github.com/dessibelle)
92
- * Added ability to display metabox fields in frontend. Default is true, but can be overriden using the `cmb_allow_frontend filter`. If set to true, an entire metabox form can be output with the `cmb_metabox_form( $meta_box, $object_id, $echo )` function. Props [@dessibelle](https://github.com/dessibelle), [@messenlehner](https://github.com/messenlehner) & [@jtsternberg](https://github.com/jtsternberg).
93
- * Added hook `cmb_after_table` after all metabox output. Props [@wpsmith](https://github.com/wpsmith)
94
- * `file_list` now works like a repeatable field. Add as many files as you want. Props [@coreymcollins](https://github.com/coreymcollins)
95
- * `text`, `text_small`, `text_medium`, `text_url`, `text_email`, & `text_money` fields now all have the option to be repeatable. Props [@jtsternberg](https://github.com/jtsternberg)
96
- * Custom metaboxes can now be added for user meta. Add them on the user add/edit screen, or in a custom user profile edit page on the front-end. Props [@tw2113](https://github.com/tw2113), [@jtsternberg](https://github.com/jtsternberg)
97
-
98
- ### 0.9.4
99
- * Added field "before" and "after" options for each field. Solves issue with '$' not being the desired text_money monetary symbol, props [@GaryJones](https://github.com/GaryJones)
100
- * Added filter for 'std' default fallback value, props [@messenlehner](https://github.com/messenlehner)
101
- * Ensure oEmbed videos fit in their respective metaboxes, props [@jtsternberg](https://github.com/jtsternberg)
102
- * Fixed issue where an upload field with 'show_names' disabled wouldn't have the correct button label, props [@jtsternberg](https://github.com/jtsternberg)
103
- * Better file-extension check for images, props [@GhostToast](https://github.com/GhostToast)
104
- * New filter, `cmb_valid_img_types`, for whitelisted image file-extensions, props [@jtsternberg](https://github.com/jtsternberg)
105
-
106
- ### 0.9.3
107
- * Added field type and field id classes to each cmb table row, props [@jtsternberg](https://github.com/jtsternberg)
108
-
109
- ### 0.9.2
110
- * Added post type comparison to prevent storing null values for taxonomy selectors, props [@norcross](https://github.com/norcross)
111
-
112
- ### 0.9.1
113
- * Added `oEmbed` field type with ajax display, props [@jtsternberg](https://github.com/jtsternberg)
114
-
115
- ### 0.9
116
- * __Note: This release requires WordPress 3.3+__
117
- * Cleaned up scripts being queued, props [@jaredatch](https://github.com/jaredatch)
118
- * Cleaned up and reorganized jQuery, props [@GaryJones](https://github.com/GaryJones)
119
- * Use $pagenow instead of custom $current_page, props [@jaredatch](https://github.com/jaredatch)
120
- * Fixed CSS, removed inline styles, now all in style.css, props [@jaredatch](https://github.com/jaredatch)
121
- * Fixed multicheck issues (issue #48), props [@jaredatch](https://github.com/jaredatch)
122
- * Fixed jQuery UI datepicker CSS conflicting with WordPress UI elements, props [@jaredatch](https://github.com/jaredatch)
123
- * Fixed zeros not saving in fields, props [@GaryJones](https://github.com/GaryJones)
124
- * Fixed improper labels on radio and multicheck fields, props [@jaredatch](https://github.com/jaredatch)
125
- * Fixed fields not rendering properly when in sidebar, props [@jaredatch](https://github.com/jaredatch)
126
- * Fixed bug where datepicker triggers extra space after footer in Firefox (issue #14), props [@jaredatch](https://github.com/jaredatch)
127
- * Added jQuery UI datepicker packaged with 3.3 core, props [@jaredatch](https://github.com/jaredatch)
128
- * Added date time combo picker, props [@jaredatch](https://github.com/jaredatch)
129
- * Added color picker, props [@jaredatch](https://github.com/jaredatch)
130
- * Added readme.md markdown file, props [@jaredatch](https://github.com/jaredatch)
131
-
132
- ### 0.8
133
- * Added jQuery timepicker, props [@norcross](https://github.com/norcross)
134
- * Added 'raw' textarea to convert special HTML entities back to characters, props [@norcross](https://github.com/norcross)
135
- * Added missing examples on example-functions.php, props [@norcross](https://github.com/norcross)
136
-
137
- ### 0.7
138
- * Added the new wp_editor() function for the WYSIWYG dialog box, props [@jcpry](https://github.com/jcpry)
139
- * Created 'cmb_show_on' filter to define your own Show On Filters, props [@billerickson](https://github.com/billerickson)
140
- * Added page template show_on filter, props [@billerickson](https://github.com/billerickson)
141
- * Improvements to the 'file' field type, props [@randyhoyt](https://github.com/randyhoyt)
142
- * Allow for default values on 'radio' and 'radio_inline' field types, props [@billerickson](https://github.com/billerickson)
143
-
144
- ### 0.6.1
145
- * Enabled the ability to define your own custom field types (issue #28). props [@randyhoyt](https://github.com/randyhoyt)
146
-
147
- ### 0.6
148
- * Added the ability to limit metaboxes to certain posts by id. props [@billerickson](https://github.com/billerickson)
149
-
150
- ### 0.5
151
- * Fixed define to prevent notices. props [@destos](https://github.com/destos)
152
- * Added text_date_timestap option. props [@andrewyno](https://github.com/andrewyno)
153
- * Fixed WYSIWYG paragraph breaking/spacing bug. props [@wpsmith](https://github.com/wpsmith)
154
- * Added taxonomy_radio and taxonomies_select options. props [@c3mdigital](https://github.com/c3mdigital)
155
- * Fixed script causing the dashboard widgets to not be collapsible.
156
- * Fixed various spacing and whitespace inconsistencies
157
-
158
- ### 0.4
159
- * Think we have a release that is mostly working. We'll say the initial release :)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/metabox/style.min.css DELETED
@@ -1,125 +0,0 @@
1
- table.cmb_metabox tr:first-of-type td,table.cmb_metabox tr:first-of-type th{border:0}table.cmb_metabox td,table.cmb_metabox th{border-top:1px solid #e9e9e9}
2
- table.cmb_metabox th{text-align:right;font-weight:bold}table.cmb_metabox th label{margin-top:5px;display:block}p.cmb_metabox_description{color:#AAA;font-style:italic;margin:2px 0!important}
3
- span.cmb_metabox_description{color:#AAA;font-style:italic}table.cmb_metabox input,table.cmb_metabox textarea{font-size:12px;padding:5px}table.cmb_metabox input[type=text],table.cmb_metabox textarea{width:97%}
4
- table.cmb_metabox textarea.cmb_textarea_code{font-family:Consolas,Monaco,monospace;line-height:16px}table.cmb_metabox input.cmb_text_small{width:100px;margin-right:15px}
5
- table.cmb_metabox input.cmb_timepicker{width:100px;margin-right:15px}table.cmb_metabox input.cmb_text_money{width:90px;margin-right:15px}table.cmb_metabox input.cmb_text_medium{width:230px;margin-right:15px}
6
- table.cmb_metabox input.cmb_upload_file{width:65%}table.cmb_metabox input.ed_button{padding:2px 4px}table.cmb_metabox li{font-size:12px;margin:1px 0 5px 0;line-height:16px}table.cmb_metabox ul{padding-top:5px;margin:0}
7
- table.cmb_metabox select{font-size:12px;margin-top:3px}table.cmb_metabox input:focus,table.cmb_metabox textarea:focus{background:#fffff8}.cmb_metabox_title{margin:0 0 5px 0;padding:5px 0 0 0;font:italic 24px/35px Georgia,"Times New Roman","Bitstream Charter",Times,serif}
8
- .cmb_radio_inline{padding:4px 0 0 0}.cmb_radio_inline_option{display:inline;padding-right:18px}table.cmb_metabox input[type="radio"]{margin:0 5px 0 0;padding:0}
9
- table.cmb_metabox input[type="checkbox"]{margin:0 5px 0 0;padding:0}table.cmb_metabox .mceLayout{border:1px solid #dfdfdf!important}
10
- table.cmb_metabox .mceIframeContainer{background:#FFF}table.cmb_metabox .meta_mce{width:97%}table.cmb_metabox .meta_mce textarea{width:100%}table.cmb_metabox .cmb_media_status{margin:10px 0 0 0}
11
- table.cmb_metabox .cmb_media_status .img_status,table.cmb_metabox .cmb_media_status .embed_status{position:relative}table.cmb_metabox .cmb_media_status .img_status img,table.cmb_metabox .cmb_media_status .embed_status{border:1px solid #dfdfdf;background:#fafafa;max-width:350px;padding:5px;-moz-border-radius:2px;border-radius:2px}
12
- table.cmb_metabox .cmb_media_status .embed_status{float:left;max-width:800px}table.cmb_metabox .cmb_media_status .img_status .cmb_remove_file_button,table.cmb_metabox .cmb_media_status .embed_status .cmb_remove_file_button{text-indent:-9999px;background:url(images/ico-delete.png);width:16px;height:16px;position:absolute;top:-5px;left:-5px}
13
- table.cmb_metabox .attach_list li{clear:both;display:inline-block;margin-bottom:25px;width:100%}table.cmb_metabox .attach_list li img{float:left;margin-right:10px}
14
- .inner-sidebar table.cmb_metabox input[type=text],#side-sortables table.cmb_metabox input[type=text],table.cmb_metabox textarea{width:95%}.inner-sidebar table.cmb_metabox .cmb_media_status .img_status img,#side-sortables table.cmb_metabox .cmb_media_status .img_status img,.inner-sidebar table.cmb_metabox .cmb_media_status .embed_status img,#side-sortables table.cmb_metabox .cmb_media_status .embed_status img{width:90%}
15
- .postbox table.cmb_metabox .cmb-spinner{float:left}table.cmb_metabox .wp-color-result,table.cmb_metabox .wp-picker-input-wrap{vertical-align:middle}table.cmb_metabox .wp-color-result,table.cmb_metabox .wp-picker-container{margin:0 10px 0 0}
16
- div.time-picker{position:absolute;height:191px;width:6em;overflow:auto;background:#fff;border:1px solid #aaa;z-index:99;margin:0}div.time-picker-12hours{width:8em}
17
- div.time-picker ul{list-style-type:none;margin:0;padding:0}div.time-picker li{cursor:pointer;height:10px;font:12px/1 Helvetica,Arial,sans-serif;padding:4px 3px}
18
- div.time-picker li.selected{background:#0063ce;color:#fff}.cmb_element .ui-helper-hidden{display:none}.cmb_element .ui-helper-hidden-accessible{position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}
19
- .cmb_element .ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.cmb_element .ui-helper-clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden}
20
- .cmb_element .ui-helper-clearfix{display:inline-block}* html .ui-helper-clearfix{height:1%}.cmb_element .ui-helper-clearfix{display:block}.cmb_element .ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}
21
- .cmb_element .ui-state-disabled{cursor:default!important}.cmb_element .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}
22
- .cmb_element .ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.cmb_element .ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}
23
- .cmb_element .ui-widget .ui-widget{font-size:1em}.cmb_element .ui-widget input,.cmb_element .ui-widget select,.cmb_element .ui-widget textarea,.cmb_element .ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}
24
- .cmb_element .ui-widget-content{border:1px solid #aaa;background:#fff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x;color:#222}.cmb_element .ui-widget-content a{color:#222}
25
- .cmb_element .ui-widget-header{border:1px solid #aaa;background:#ccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x;color:#222;font-weight:bold}
26
- .cmb_element .ui-widget-header a{color:#222}.cmb_element .ui-state-default,.cmb_element .ui-widget-content .ui-state-default,.cmb_element .ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#555}
27
- .cmb_element .ui-state-default a,.cmb_element .ui-state-default a:link,.cmb_element .ui-state-default a:visited{color:#555;text-decoration:none}.cmb_element .ui-state-hover,.cmb_element .ui-widget-content .ui-state-hover,.cmb_element .ui-widget-header .ui-state-hover,.cmb_element .ui-state-focus,.cmb_element .ui-widget-content .ui-state-focus,.cmb_element .ui-widget-header .ui-state-focus{border:1px solid #999;background:#dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}
28
- .cmb_element .ui-state-hover a,.cmb_element .ui-state-hover a:hover{color:#212121;text-decoration:none}.cmb_element .ui-state-active,.cmb_element .ui-widget-content .ui-state-active,.cmb_element .ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}
29
- .cmb_element .ui-state-active a,.cmb_element .ui-state-active a:link,.cmb_element .ui-state-active a:visited{color:#212121;text-decoration:none}.cmb_element .ui-widget :active{outline:0}
30
- .cmb_element .ui-state-highlight,.cmb_element .ui-widget-content .ui-state-highlight,.cmb_element .ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x;color:#363636}
31
- .cmb_element .ui-state-highlight a,.cmb_element .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.cmb_element .ui-state-error,.cmb_element .ui-widget-content .ui-state-error,.cmb_element .ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;color:#cd0a0a}
32
- .cmb_element .ui-state-error a,.cmb_element .ui-widget-content .ui-state-error a,.cmb_element .ui-widget-header .ui-state-error a{color:#cd0a0a}.cmb_element .ui-state-error-text,.cmb_element .ui-widget-content .ui-state-error-text,.cmb_element .ui-widget-header .ui-state-error-text{color:#cd0a0a}
33
- .cmb_element .ui-priority-primary,.cmb_element .ui-widget-content .ui-priority-primary,.cmb_element .ui-widget-header .ui-priority-primary{font-weight:bold}
34
- .cmb_element .ui-priority-secondary,.cmb_element .ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}
35
- .cmb_element .ui-state-disabled,.cmb_element .ui-widget-content .ui-state-disabled,.cmb_element .ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}
36
- .cmb_element .ui-icon{width:16px;height:16px;background-image:url(images/ui-icons_222222_256x240.png)}.cmb_element .ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}
37
- .cmb_element .ui-widget-header .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.cmb_element .ui-state-default .ui-icon{background-image:url(images/ui-icons_888888_256x240.png)}
38
- .cmb_element .ui-state-hover .ui-icon,.cmb_element .ui-state-focus .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.cmb_element .ui-state-active .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}
39
- .cmb_element .ui-state-highlight .ui-icon{background-image:url(images/ui-icons_2e83ff_256x240.png)}.cmb_element .ui-state-error .ui-icon,.cmb_element .ui-state-error-text .ui-icon{background-image:url(images/ui-icons_cd0a0a_256x240.png)}
40
- .cmb_element .ui-icon-carat-1-n{background-position:0 0}.cmb_element .ui-icon-carat-1-ne{background-position:-16px 0}.cmb_element .ui-icon-carat-1-e{background-position:-32px 0}
41
- .cmb_element .ui-icon-carat-1-se{background-position:-48px 0}.cmb_element .ui-icon-carat-1-s{background-position:-64px 0}.cmb_element .ui-icon-carat-1-sw{background-position:-80px 0}
42
- .cmb_element .ui-icon-carat-1-w{background-position:-96px 0}.cmb_element .ui-icon-carat-1-nw{background-position:-112px 0}.cmb_element .ui-icon-carat-2-n-s{background-position:-128px 0}
43
- .cmb_element .ui-icon-carat-2-e-w{background-position:-144px 0}.cmb_element .ui-icon-triangle-1-n{background-position:0 -16px}.cmb_element .ui-icon-triangle-1-ne{background-position:-16px -16px}
44
- .cmb_element .ui-icon-triangle-1-e{background-position:-32px -16px}.cmb_element .ui-icon-triangle-1-se{background-position:-48px -16px}.cmb_element .ui-icon-triangle-1-s{background-position:-64px -16px}
45
- .cmb_element .ui-icon-triangle-1-sw{background-position:-80px -16px}.cmb_element .ui-icon-triangle-1-w{background-position:-96px -16px}.cmb_element .ui-icon-triangle-1-nw{background-position:-112px -16px}
46
- .cmb_element .ui-icon-triangle-2-n-s{background-position:-128px -16px}.cmb_element .ui-icon-triangle-2-e-w{background-position:-144px -16px}.cmb_element .ui-icon-arrow-1-n{background-position:0 -32px}
47
- .cmb_element .ui-icon-arrow-1-ne{background-position:-16px -32px}.cmb_element .ui-icon-arrow-1-e{background-position:-32px -32px}.cmb_element .ui-icon-arrow-1-se{background-position:-48px -32px}
48
- .cmb_element .ui-icon-arrow-1-s{background-position:-64px -32px}.cmb_element .ui-icon-arrow-1-sw{background-position:-80px -32px}.cmb_element .ui-icon-arrow-1-w{background-position:-96px -32px}
49
- .cmb_element .ui-icon-arrow-1-nw{background-position:-112px -32px}.cmb_element .ui-icon-arrow-2-n-s{background-position:-128px -32px}.cmb_element .ui-icon-arrow-2-ne-sw{background-position:-144px -32px}
50
- .cmb_element .ui-icon-arrow-2-e-w{background-position:-160px -32px}.cmb_element .ui-icon-arrow-2-se-nw{background-position:-176px -32px}.cmb_element .ui-icon-arrowstop-1-n{background-position:-192px -32px}
51
- .cmb_element .ui-icon-arrowstop-1-e{background-position:-208px -32px}.cmb_element .ui-icon-arrowstop-1-s{background-position:-224px -32px}.cmb_element .ui-icon-arrowstop-1-w{background-position:-240px -32px}
52
- .cmb_element .ui-icon-arrowthick-1-n{background-position:0 -48px}.cmb_element .ui-icon-arrowthick-1-ne{background-position:-16px -48px}.cmb_element .ui-icon-arrowthick-1-e{background-position:-32px -48px}
53
- .cmb_element .ui-icon-arrowthick-1-se{background-position:-48px -48px}.cmb_element .ui-icon-arrowthick-1-s{background-position:-64px -48px}.cmb_element .ui-icon-arrowthick-1-sw{background-position:-80px -48px}
54
- .cmb_element .ui-icon-arrowthick-1-w{background-position:-96px -48px}.cmb_element .ui-icon-arrowthick-1-nw{background-position:-112px -48px}.cmb_element .ui-icon-arrowthick-2-n-s{background-position:-128px -48px}
55
- .cmb_element .ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.cmb_element .ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.cmb_element .ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}
56
- .cmb_element .ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.cmb_element .ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.cmb_element .ui-icon-arrowthickstop-1-s{background-position:-224px -48px}
57
- .cmb_element .ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.cmb_element .ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.cmb_element .ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}
58
- .cmb_element .ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.cmb_element .ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}
59
- .cmb_element .ui-icon-arrowreturn-1-w{background-position:-64px -64px}.cmb_element .ui-icon-arrowreturn-1-n{background-position:-80px -64px}.cmb_element .ui-icon-arrowreturn-1-e{background-position:-96px -64px}
60
- .cmb_element .ui-icon-arrowreturn-1-s{background-position:-112px -64px}.cmb_element .ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.cmb_element .ui-icon-arrowrefresh-1-n{background-position:-144px -64px}
61
- .cmb_element .ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.cmb_element .ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.cmb_element .ui-icon-arrow-4{background-position:0 -80px}
62
- .cmb_element .ui-icon-arrow-4-diag{background-position:-16px -80px}.cmb_element .ui-icon-extlink{background-position:-32px -80px}.cmb_element .ui-icon-newwin{background-position:-48px -80px}
63
- .cmb_element .ui-icon-refresh{background-position:-64px -80px}.cmb_element .ui-icon-shuffle{background-position:-80px -80px}.cmb_element .ui-icon-transfer-e-w{background-position:-96px -80px}
64
- .cmb_element .ui-icon-transferthick-e-w{background-position:-112px -80px}.cmb_element .ui-icon-folder-collapsed{background-position:0 -96px}.cmb_element .ui-icon-folder-open{background-position:-16px -96px}
65
- .cmb_element .ui-icon-document{background-position:-32px -96px}.cmb_element .ui-icon-document-b{background-position:-48px -96px}.cmb_element .ui-icon-note{background-position:-64px -96px}
66
- .cmb_element .ui-icon-mail-closed{background-position:-80px -96px}.cmb_element .ui-icon-mail-open{background-position:-96px -96px}.cmb_element .ui-icon-suitcase{background-position:-112px -96px}
67
- .cmb_element .ui-icon-comment{background-position:-128px -96px}.cmb_element .ui-icon-person{background-position:-144px -96px}.cmb_element .ui-icon-print{background-position:-160px -96px}
68
- .cmb_element .ui-icon-trash{background-position:-176px -96px}.cmb_element .ui-icon-locked{background-position:-192px -96px}.cmb_element .ui-icon-unlocked{background-position:-208px -96px}
69
- .cmb_element .ui-icon-bookmark{background-position:-224px -96px}.cmb_element .ui-icon-tag{background-position:-240px -96px}.cmb_element .ui-icon-home{background-position:0 -112px}
70
- .cmb_element .ui-icon-flag{background-position:-16px -112px}.cmb_element .ui-icon-calendar{background-position:-32px -112px}.cmb_element .ui-icon-cart{background-position:-48px -112px}
71
- .cmb_element .ui-icon-pencil{background-position:-64px -112px}.cmb_element .ui-icon-clock{background-position:-80px -112px}.cmb_element .ui-icon-disk{background-position:-96px -112px}
72
- .cmb_element .ui-icon-calculator{background-position:-112px -112px}.cmb_element .ui-icon-zoomin{background-position:-128px -112px}.cmb_element .ui-icon-zoomout{background-position:-144px -112px}
73
- .cmb_element .ui-icon-search{background-position:-160px -112px}.cmb_element .ui-icon-wrench{background-position:-176px -112px}.cmb_element .ui-icon-gear{background-position:-192px -112px}
74
- .cmb_element .ui-icon-heart{background-position:-208px -112px}.cmb_element .ui-icon-star{background-position:-224px -112px}.cmb_element .ui-icon-link{background-position:-240px -112px}
75
- .cmb_element .ui-icon-cancel{background-position:0 -128px}.cmb_element .ui-icon-plus{background-position:-16px -128px}.cmb_element .ui-icon-plusthick{background-position:-32px -128px}
76
- .cmb_element .ui-icon-minus{background-position:-48px -128px}.cmb_element .ui-icon-minusthick{background-position:-64px -128px}.cmb_element .ui-icon-close{background-position:-80px -128px}
77
- .cmb_element .ui-icon-closethick{background-position:-96px -128px}.cmb_element .ui-icon-key{background-position:-112px -128px}.cmb_element .ui-icon-lightbulb{background-position:-128px -128px}
78
- .cmb_element .ui-icon-scissors{background-position:-144px -128px}.cmb_element .ui-icon-clipboard{background-position:-160px -128px}.cmb_element .ui-icon-copy{background-position:-176px -128px}
79
- .cmb_element .ui-icon-contact{background-position:-192px -128px}.cmb_element .ui-icon-image{background-position:-208px -128px}.cmb_element .ui-icon-video{background-position:-224px -128px}
80
- .cmb_element .ui-icon-script{background-position:-240px -128px}.cmb_element .ui-icon-alert{background-position:0 -144px}.cmb_element .ui-icon-info{background-position:-16px -144px}
81
- .cmb_element .ui-icon-notice{background-position:-32px -144px}.cmb_element .ui-icon-help{background-position:-48px -144px}.cmb_element .ui-icon-check{background-position:-64px -144px}
82
- .cmb_element .ui-icon-bullet{background-position:-80px -144px}.cmb_element .ui-icon-radio-off{background-position:-96px -144px}.cmb_element .ui-icon-radio-on{background-position:-112px -144px}
83
- .cmb_element .ui-icon-pin-w{background-position:-128px -144px}.cmb_element .ui-icon-pin-s{background-position:-144px -144px}.cmb_element .ui-icon-play{background-position:0 -160px}
84
- .cmb_element .ui-icon-pause{background-position:-16px -160px}.cmb_element .ui-icon-seek-next{background-position:-32px -160px}.cmb_element .ui-icon-seek-prev{background-position:-48px -160px}
85
- .cmb_element .ui-icon-seek-end{background-position:-64px -160px}.cmb_element .ui-icon-seek-start{background-position:-80px -160px}.cmb_element .ui-icon-seek-first{background-position:-80px -160px}
86
- .cmb_element .ui-icon-stop{background-position:-96px -160px}.cmb_element .ui-icon-eject{background-position:-112px -160px}.cmb_element .ui-icon-volume-off{background-position:-128px -160px}
87
- .cmb_element .ui-icon-volume-on{background-position:-144px -160px}.cmb_element .ui-icon-power{background-position:0 -176px}.cmb_element .ui-icon-signal-diag{background-position:-16px -176px}
88
- .cmb_element .ui-icon-signal{background-position:-32px -176px}.cmb_element .ui-icon-battery-0{background-position:-48px -176px}.cmb_element .ui-icon-battery-1{background-position:-64px -176px}
89
- .cmb_element .ui-icon-battery-2{background-position:-80px -176px}.cmb_element .ui-icon-battery-3{background-position:-96px -176px}.cmb_element .ui-icon-circle-plus{background-position:0 -192px}
90
- .cmb_element .ui-icon-circle-minus{background-position:-16px -192px}.cmb_element .ui-icon-circle-close{background-position:-32px -192px}.cmb_element .ui-icon-circle-triangle-e{background-position:-48px -192px}
91
- .cmb_element .ui-icon-circle-triangle-s{background-position:-64px -192px}.cmb_element .ui-icon-circle-triangle-w{background-position:-80px -192px}.cmb_element .ui-icon-circle-triangle-n{background-position:-96px -192px}
92
- .cmb_element .ui-icon-circle-arrow-e{background-position:-112px -192px}.cmb_element .ui-icon-circle-arrow-s{background-position:-128px -192px}.cmb_element .ui-icon-circle-arrow-w{background-position:-144px -192px}
93
- .cmb_element .ui-icon-circle-arrow-n{background-position:-160px -192px}.cmb_element .ui-icon-circle-zoomin{background-position:-176px -192px}.cmb_element .ui-icon-circle-zoomout{background-position:-192px -192px}
94
- .cmb_element .ui-icon-circle-check{background-position:-208px -192px}.cmb_element .ui-icon-circlesmall-plus{background-position:0 -208px}.cmb_element .ui-icon-circlesmall-minus{background-position:-16px -208px}
95
- .cmb_element .ui-icon-circlesmall-close{background-position:-32px -208px}.cmb_element .ui-icon-squaresmall-plus{background-position:-48px -208px}.cmb_element .ui-icon-squaresmall-minus{background-position:-64px -208px}
96
- .cmb_element .ui-icon-squaresmall-close{background-position:-80px -208px}.cmb_element .ui-icon-grip-dotted-vertical{background-position:0 -224px}.cmb_element .ui-icon-grip-dotted-horizontal{background-position:-16px -224px}
97
- .cmb_element .ui-icon-grip-solid-vertical{background-position:-32px -224px}.cmb_element .ui-icon-grip-solid-horizontal{background-position:-48px -224px}
98
- .cmb_element .ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.cmb_element .ui-icon-grip-diagonal-se{background-position:-80px -224px}.cmb_element .ui-corner-all,.cmb_element .ui-corner-top,.cmb_element .ui-corner-left,.cmb_element .ui-corner-tl{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;-khtml-border-top-left-radius:4px;border-top-left-radius:4px}
99
- .cmb_element .ui-corner-all,.cmb_element .ui-corner-top,.cmb_element .ui-corner-right,.cmb_element .ui-corner-tr{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;-khtml-border-top-right-radius:4px;border-top-right-radius:4px}
100
- .cmb_element .ui-corner-all,.cmb_element .ui-corner-bottom,.cmb_element .ui-corner-left,.cmb_element .ui-corner-bl{-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;-khtml-border-bottom-left-radius:4px;border-bottom-left-radius:4px}
101
- .cmb_element .ui-corner-all,.cmb_element .ui-corner-bottom,.cmb_element .ui-corner-right,.cmb_element .ui-corner-br{-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;-khtml-border-bottom-right-radius:4px;border-bottom-right-radius:4px}
102
- .cmb_element .ui-widget-overlay{background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.30;filter:Alpha(Opacity=30)}.cmb_element .ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.30;filter:Alpha(Opacity=30);-moz-border-radius:8px;-khtml-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}
103
- .cmb_element .ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.cmb_element .ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}
104
- .cmb_element .ui-datepicker .ui-datepicker-prev,.cmb_element .ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.cmb_element .ui-datepicker .ui-datepicker-prev-hover,.cmb_element .ui-datepicker .ui-datepicker-next-hover{top:1px}
105
- .cmb_element .ui-datepicker .ui-datepicker-prev{left:2px}.cmb_element .ui-datepicker .ui-datepicker-next{right:2px}.cmb_element .ui-datepicker .ui-datepicker-prev-hover{left:1px}
106
- .cmb_element .ui-datepicker .ui-datepicker-next-hover{right:1px}.cmb_element .ui-datepicker .ui-datepicker-prev span,.cmb_element .ui-datepicker .ui-datepicker-next span{display:block;position:absolute;margin-left:5px;margin-top:5px}
107
- .cmb_element .ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.cmb_element .ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}
108
- .cmb_element .ui-datepicker select.ui-datepicker-month-year{width:100%}.cmb_element .ui-datepicker select.ui-datepicker-month,.cmb_element .ui-datepicker select.ui-datepicker-year{width:49%}
109
- .cmb_element .ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.cmb_element .ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}
110
- .cmb_element .ui-datepicker td{border:0;padding:1px}.cmb_element .ui-datepicker td span,.cmb_element .ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}
111
- .cmb_element .ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}
112
- .cmb_element .ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}
113
- .cmb_element .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.cmb_element .ui-datepicker.ui-datepicker-multi{width:auto}
114
- .cmb_element .ui-datepicker-multi .ui-datepicker-group{float:left}.cmb_element .ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}
115
- .cmb_element .ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.cmb_element .ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.cmb_element .ui-datepicker-multi-4 .ui-datepicker-group{width:25%}
116
- .cmb_element .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header{border-left-width:0}.cmb_element .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}
117
- .cmb_element .ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.cmb_element .ui-datepicker-row-break{clear:both;width:100%;font-size:0}.cmb_element .ui-datepicker-rtl{direction:rtl}
118
- .cmb_element .ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}
119
- .cmb_element .ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}
120
- .cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current{float:right}.cmb_element .ui-datepicker-rtl .ui-datepicker-group{float:right}
121
- .cmb_element .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header{border-right-width:0;border-left-width:1px}.cmb_element .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}
122
- .cmb_element .ui-datepicker-cover{display:none;display:block;position:absolute;z-index:-1;filter:mask();top:-4px;left:-4px;width:200px;height:200px}
123
- #ui-datepicker-div { z-index: 999999 !important; }
124
- .ui-datepicker-prev:hover,.ui-datepicker-next:hover { cursor: pointer !important; }
125
- .wp-picker-holder { position: absolute; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: http://www.evan-herman.com/contact/?contact-reason=I%20want%20to%20
4
  Tags: vertical, timeline, animated, css3, animations, evan, herman, evan herman, easy, time, line, font awesome, font, awesome, announcements, notifications, simple, events, calendar, scroll, triggered, scrolling, animated, fade, in, fade in
5
  Requires at least: 3.9
6
  Tested up to: 4.1
7
- Stable tag: 1.1.4.1
8
  License: GPLv2 or later
9
 
10
  Timeline express allows you to create a beautiful vertical animated and responsive timeline of posts , without writing a single line of code. Sweet!
@@ -44,6 +44,44 @@ Timeline express comes ready for translation. I would love to get things transla
44
 
45
  **Hooks + Filters**
46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  **Customize the 'announcement' slug (New v1.1.4)**
48
 
49
  Users can now define their own slug for announcement posts using the provided filter `'timeline-express-slug'`. This alters the URL structure of the announcement, possibly for SEO purposes. You would enter the following code into your active themes functions.php file.
@@ -245,6 +283,11 @@ Have an idea for a future release feature? I love hearing about new ideas! You c
245
 
246
  == Changelog ==
247
 
 
 
 
 
 
248
  = 1.1.4.1 - January 2nd, 2015 =
249
  * Fixed: Issue with date storing different on backend vs front end
250
  * Fixed: Settings link on the Timeline Express welcome page
@@ -327,6 +370,15 @@ Have an idea for a future release feature? I love hearing about new ideas! You c
327
 
328
  == Upgrade Notice ==
329
 
 
 
 
 
 
 
 
 
 
330
  = 1.1.4 - December 24th, 2014 =
331
  * Enhancement: Implemented premium support licensing. Any issues that require immediate response, or custom code should purchase a support license.
332
  * Enhancement: Added a new filter to customize the announcement slug (possibly for SEO purposes) (timeline-express-slug , check documentation for examples)
@@ -387,4 +439,4 @@ We have now included Chinese language translation (zh_CN) - thanks goes to <a hr
387
  * Update masonry function to include .imagesLoaded(); to prevent overlapping containers in the timeline
388
 
389
  = 1.0 =
390
- * Initial Release to the WordPress repository
4
  Tags: vertical, timeline, animated, css3, animations, evan, herman, evan herman, easy, time, line, font awesome, font, awesome, announcements, notifications, simple, events, calendar, scroll, triggered, scrolling, animated, fade, in, fade in
5
  Requires at least: 3.9
6
  Tested up to: 4.1
7
+ Stable tag: 1.1.5
8
  License: GPLv2 or later
9
 
10
  Timeline express allows you to create a beautiful vertical animated and responsive timeline of posts , without writing a single line of code. Sweet!
44
 
45
  **Hooks + Filters**
46
 
47
+ **Define your own custom fields to use in Announcement posts (New v1.1.5)**
48
+
49
+ Users can now add custom fields to Timeline Express announcement posts. This allows for greater control over the announcements and the front end display. Using this hook in conjunction with a custom single announcement template will give you the greatest control.
50
+
51
+ Example:
52
+ <code>
53
+ function add_custom_timeline_express_field( $custom_fields ) {
54
+ $custom_fields = array(
55
+ array(
56
+ 'name' => __( 'Example Text Field', 'timeline-express' ),
57
+ 'desc' => __( 'this is an example user defined text field.', 'timeline-express' ),
58
+ 'id' => 'announcement_user_defined_text',
59
+ 'type' => 'text_medium',
60
+ ),
61
+ array(
62
+ 'name' => __( 'Example WYSIWYG', 'timeline-express' ),
63
+ 'desc' => __( 'this is an example wysiwyg field.', 'timeline-express' ),
64
+ 'id' => 'announcement_user_defined_wysiwyg',
65
+ 'type' => 'wysiwyg',
66
+ ),
67
+ array(
68
+ 'name' => __( 'Example Email Field', 'timeline-express' ),
69
+ 'desc' => __( 'this is an example user defined email field.', 'timeline-express' ),
70
+ 'id' => 'announcement_user_defined_money',
71
+ 'type' => 'text_email',
72
+ )
73
+ );
74
+ return $custom_fields;
75
+ }
76
+ add_filter( 'timeline_express_custom_fields' , 'add_custom_timeline_express_field' );
77
+ </code>
78
+
79
+ This example would add 3 new fields below the 'Announcement Image' field on the announcement post.
80
+
81
+ The first field is a simple text field. The second field is an example WYSIWYG, and the third is an email field.
82
+
83
+ Note: You can add as many fields as you would like, and display them on the front end using the <a href="http://codex.wordpress.org/Function_Reference/get_post_meta" target="_blank" title="WordPress Codex: get_post_meta()">get_post_meta()</a> function.
84
+
85
  **Customize the 'announcement' slug (New v1.1.4)**
86
 
87
  Users can now define their own slug for announcement posts using the provided filter `'timeline-express-slug'`. This alters the URL structure of the announcement, possibly for SEO purposes. You would enter the following code into your active themes functions.php file.
283
 
284
  == Changelog ==
285
 
286
+ = 1.1.5 - January 10th, 2015 =
287
+ Enhancement: Added new filter ( `timeline_express_custom_fields` ) which allows users to define their own custom fields to use on Timeline Announcement posts (see readme for example).
288
+ Fixed: CMB class file causing conflicts with other plugins, and removed the old version
289
+ Fixed: Adjusted a few styles on the announcement post page
290
+
291
  = 1.1.4.1 - January 2nd, 2015 =
292
  * Fixed: Issue with date storing different on backend vs front end
293
  * Fixed: Settings link on the Timeline Express welcome page
370
 
371
  == Upgrade Notice ==
372
 
373
+ = 1.1.5 - January 10th, 2015 =
374
+ Enhancement: Added new filter ( `timeline_express_custom_fields` ) which allows users to define their own custom fields to use on Timeline Announcement posts (see readme for example).
375
+ Fixed: CMB class file causing conflicts with other plugins, and removed the old version
376
+ Fixed: Adjusted a few styles on the announcement post page
377
+
378
+ = 1.1.4.1 - January 2nd, 2015 =
379
+ Fixed: Issue with date storing different on backend vs front end
380
+ Fixed: Settings link on the Timeline Express welcome page
381
+
382
  = 1.1.4 - December 24th, 2014 =
383
  * Enhancement: Implemented premium support licensing. Any issues that require immediate response, or custom code should purchase a support license.
384
  * Enhancement: Added a new filter to customize the announcement slug (possibly for SEO purposes) (timeline-express-slug , check documentation for examples)
439
  * Update masonry function to include .imagesLoaded(); to prevent overlapping containers in the timeline
440
 
441
  = 1.0 =
442
+ * Initial Release to the WordPress repository
timeline-express.php CHANGED
@@ -4,7 +4,7 @@
4
  Plugin Name: Timeline Express
5
  Plugin URI: http://www.evan-herman.com
6
  Description: Create a beautiful vertical, CSS3 animated and responsive timeline in minutes flat without writing code.
7
- Version: 1.1.4.1
8
  Author: Evan Herman
9
  Author URI: http://www.evan-herman.com
10
  License: GPL2
@@ -28,7 +28,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28
  #_________________________________________________ CONSTANTS
29
 
30
  /** Configuration **/
31
- if(!defined('TIMELINE_EXPRESS_VERSION_CURRENT')) define('TIMELINE_EXPRESS_VERSION_CURRENT', '1.1.4.1');
32
  if(!defined('TIMELINE_EXPRESS_PATH')) define('TIMELINE_EXPRESS_PATH', plugin_dir_path( __FILE__ ));
33
  if(!defined('TIMELINE_EXPRESS_URL')) define('TIMELINE_EXPRESS_URL', plugins_url('timeline-express/'));
34
  if(!defined('TIMELINE_EXPRESS_URL_WP')) define('TIMELINE_EXPRESS_URL_WP', get_bloginfo('url'));
4
  Plugin Name: Timeline Express
5
  Plugin URI: http://www.evan-herman.com
6
  Description: Create a beautiful vertical, CSS3 animated and responsive timeline in minutes flat without writing code.
7
+ Version: 1.1.5
8
  Author: Evan Herman
9
  Author URI: http://www.evan-herman.com
10
  License: GPL2
28
  #_________________________________________________ CONSTANTS
29
 
30
  /** Configuration **/
31
+ if(!defined('TIMELINE_EXPRESS_VERSION_CURRENT')) define('TIMELINE_EXPRESS_VERSION_CURRENT', '1.1.5');
32
  if(!defined('TIMELINE_EXPRESS_PATH')) define('TIMELINE_EXPRESS_PATH', plugin_dir_path( __FILE__ ));
33
  if(!defined('TIMELINE_EXPRESS_URL')) define('TIMELINE_EXPRESS_URL', plugins_url('timeline-express/'));
34
  if(!defined('TIMELINE_EXPRESS_URL_WP')) define('TIMELINE_EXPRESS_URL_WP', get_bloginfo('url'));