Team Members - Version 1.0.1

Version Description

  • SAFE UPDATE: No data loss for those upgrading from version 1.0 or higher
  • Preparing for PRO version
Download this release

Release Info

Developer spwebguy
Plugin Icon 128x128 Team Members
Version 1.0.1
Comparing to
See all releases

Version 1.0.1

Files changed (117) hide show
  1. css/tmm_custom_style.css +93 -0
  2. css/tmm_custom_style.min.css +1 -0
  3. drkfr/Gruntfile.js +39 -0
  4. drkfr/class.drkfr-meta-box.php +379 -0
  5. drkfr/classes.fields.php +1675 -0
  6. drkfr/css/dist/drkfr.css +63 -0
  7. drkfr/css/dist/drkfr.min.css +63 -0
  8. drkfr/css/legacy.css +319 -0
  9. drkfr/css/src/file.css +166 -0
  10. drkfr/css/src/generic.css +55 -0
  11. drkfr/css/src/group.css +82 -0
  12. drkfr/css/src/layout.css +57 -0
  13. drkfr/css/src/misc-fields.css +71 -0
  14. drkfr/css/src/repeatable.css +88 -0
  15. drkfr/css/src/sortable.css +40 -0
  16. drkfr/css/vendor/jquery-ui/images/animated-overlay.gif +0 -0
  17. drkfr/css/vendor/jquery-ui/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  18. drkfr/css/vendor/jquery-ui/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  19. drkfr/css/vendor/jquery-ui/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  20. drkfr/css/vendor/jquery-ui/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  21. drkfr/css/vendor/jquery-ui/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  22. drkfr/css/vendor/jquery-ui/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  23. drkfr/css/vendor/jquery-ui/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  24. drkfr/css/vendor/jquery-ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  25. drkfr/css/vendor/jquery-ui/images/ui-icons_222222_256x240.png +0 -0
  26. drkfr/css/vendor/jquery-ui/images/ui-icons_2e83ff_256x240.png +0 -0
  27. drkfr/css/vendor/jquery-ui/images/ui-icons_454545_256x240.png +0 -0
  28. drkfr/css/vendor/jquery-ui/images/ui-icons_888888_256x240.png +0 -0
  29. drkfr/css/vendor/jquery-ui/images/ui-icons_cd0a0a_256x240.png +0 -0
  30. drkfr/css/vendor/jquery-ui/jquery-ui.css +1175 -0
  31. drkfr/css/vendor/jquery-ui/jquery-ui.min.css +5 -0
  32. drkfr/css/vendor/jquery-ui/jquery.ui.theme.css +406 -0
  33. drkfr/custom-meta-boxes.php +136 -0
  34. drkfr/fields-anywhere.php +92 -0
  35. drkfr/images/drkfr-icon-remove.png +0 -0
  36. drkfr/images/drkfr-icon-remove@2x.png +0 -0
  37. drkfr/images/wpspin-2x.gif +0 -0
  38. drkfr/images/wpspin.gif +0 -0
  39. drkfr/js/drkfr.js +315 -0
  40. drkfr/js/field-gmap.js +93 -0
  41. drkfr/js/field-wysiwyg.js +106 -0
  42. drkfr/js/field.colorpicker.js +18 -0
  43. drkfr/js/field.datetime.js +47 -0
  44. drkfr/js/field.select.js +29 -0
  45. drkfr/js/file-upload.js +129 -0
  46. drkfr/js/jquery.timePicker.min.js +20 -0
  47. drkfr/js/vendor/select2/.bower.json +25 -0
  48. drkfr/js/vendor/select2/.gitignore +2 -0
  49. drkfr/js/vendor/select2/LICENSE +18 -0
  50. drkfr/js/vendor/select2/README.md +99 -0
  51. drkfr/js/vendor/select2/bower.json +8 -0
  52. drkfr/js/vendor/select2/component.json +66 -0
  53. drkfr/js/vendor/select2/composer.json +29 -0
  54. drkfr/js/vendor/select2/package.json +20 -0
  55. drkfr/js/vendor/select2/release.sh +79 -0
  56. drkfr/js/vendor/select2/select2-bootstrap.css +87 -0
  57. drkfr/js/vendor/select2/select2-spinner.gif +0 -0
  58. drkfr/js/vendor/select2/select2.css +704 -0
  59. drkfr/js/vendor/select2/select2.jquery.json +36 -0
  60. drkfr/js/vendor/select2/select2.js +3508 -0
  61. drkfr/js/vendor/select2/select2.min.js +23 -0
  62. drkfr/js/vendor/select2/select2.png +0 -0
  63. drkfr/js/vendor/select2/select2_locale_ar.js +19 -0
  64. drkfr/js/vendor/select2/select2_locale_az.js +20 -0
  65. drkfr/js/vendor/select2/select2_locale_bg.js +20 -0
  66. drkfr/js/vendor/select2/select2_locale_ca.js +19 -0
  67. drkfr/js/vendor/select2/select2_locale_cs.js +51 -0
  68. drkfr/js/vendor/select2/select2_locale_da.js +19 -0
  69. drkfr/js/vendor/select2/select2_locale_de.js +18 -0
  70. drkfr/js/vendor/select2/select2_locale_el.js +19 -0
  71. drkfr/js/vendor/select2/select2_locale_en.js.template +20 -0
  72. drkfr/js/vendor/select2/select2_locale_es.js +17 -0
  73. drkfr/js/vendor/select2/select2_locale_et.js +19 -0
  74. drkfr/js/vendor/select2/select2_locale_eu.js +45 -0
  75. drkfr/js/vendor/select2/select2_locale_fa.js +21 -0
  76. drkfr/js/vendor/select2/select2_locale_fi.js +30 -0
  77. drkfr/js/vendor/select2/select2_locale_fr.js +18 -0
  78. drkfr/js/vendor/select2/select2_locale_gl.js +45 -0
  79. drkfr/js/vendor/select2/select2_locale_he.js +19 -0
  80. drkfr/js/vendor/select2/select2_locale_hr.js +24 -0
  81. drkfr/js/vendor/select2/select2_locale_hu.js +17 -0
  82. drkfr/js/vendor/select2/select2_locale_id.js +19 -0
  83. drkfr/js/vendor/select2/select2_locale_is.js +17 -0
  84. drkfr/js/vendor/select2/select2_locale_it.js +17 -0
  85. drkfr/js/vendor/select2/select2_locale_ja.js +17 -0
  86. drkfr/js/vendor/select2/select2_locale_ka.js +19 -0
  87. drkfr/js/vendor/select2/select2_locale_ko.js +19 -0
  88. drkfr/js/vendor/select2/select2_locale_lt.js +26 -0
  89. drkfr/js/vendor/select2/select2_locale_lv.js +19 -0
  90. drkfr/js/vendor/select2/select2_locale_mk.js +19 -0
  91. drkfr/js/vendor/select2/select2_locale_ms.js +19 -0
  92. drkfr/js/vendor/select2/select2_locale_nl.js +17 -0
  93. drkfr/js/vendor/select2/select2_locale_no.js +20 -0
  94. drkfr/js/vendor/select2/select2_locale_pl.js +25 -0
  95. drkfr/js/vendor/select2/select2_locale_pt-BR.js +17 -0
  96. drkfr/js/vendor/select2/select2_locale_pt-PT.js +17 -0
  97. drkfr/js/vendor/select2/select2_locale_ro.js +17 -0
  98. drkfr/js/vendor/select2/select2_locale_rs.js +19 -0
  99. drkfr/js/vendor/select2/select2_locale_ru.js +23 -0
  100. drkfr/js/vendor/select2/select2_locale_sk.js +50 -0
  101. drkfr/js/vendor/select2/select2_locale_sv.js +19 -0
  102. drkfr/js/vendor/select2/select2_locale_th.js +19 -0
  103. drkfr/js/vendor/select2/select2_locale_tr.js +19 -0
  104. drkfr/js/vendor/select2/select2_locale_ug-CN.js +16 -0
  105. drkfr/js/vendor/select2/select2_locale_uk.js +25 -0
  106. drkfr/js/vendor/select2/select2_locale_vi.js +20 -0
  107. drkfr/js/vendor/select2/select2_locale_zh-CN.js +16 -0
  108. drkfr/js/vendor/select2/select2_locale_zh-TW.js +16 -0
  109. drkfr/js/vendor/select2/select2x2.png +0 -0
  110. drkfr/phpunit.xml +14 -0
  111. img/links/customlink.png +0 -0
  112. img/links/facebook.png +0 -0
  113. img/links/googleplus.png +0 -0
  114. img/links/linkedin.png +0 -0
  115. img/links/twitter.png +0 -0
  116. readme.txt +76 -0
  117. tmm.php +305 -0
css/tmm_custom_style.css ADDED
@@ -0,0 +1,93 @@
1
+ @charset "UTF-8";
2
+ .tmm_wrap {width:100%; margin-bottom:30px; text-align:center;}
3
+ .clearer {clear:both;}
4
+
5
+ .tmm_member {
6
+ margin-top:100px;
7
+ height:auto;
8
+ float: left;
9
+ text-align:center;
10
+ border-bottom:1px solid whitesmoke;
11
+ -webkit-box-shadow: 1px 0px 5px 0px rgba(0,0,0,0.05);
12
+ -moz-box-shadow: 1px 0px 5px 0px rgba(0,0,0,0.05);
13
+ box-shadow: 1px 0px 5px 0px rgba(0,0,0,0.05);
14
+ border-top:5px solid lightgrey;
15
+ border-bottom:8px solid whitesmoke;
16
+ }
17
+
18
+ .tmm_three_entries {clear:both;}
19
+
20
+ .tmm_3_columns .tmm_member {width: 31%; margin-right:1%; margin-left:1%;}
21
+ .tmm_4_columns .tmm_member {width: 23%; margin-right:1%; margin-left:1%;}
22
+
23
+ .tmm_member > img {
24
+ width:150px;
25
+ height:150px;
26
+ border:none;
27
+ -webkit-box-shadow: 2px 0px 15px 0px rgba(0,0,0,0.15);
28
+ -moz-box-shadow: 2px 0px 15px 0px rgba(0,0,0,0.15);
29
+ box-shadow: 2px 0px 15px 0px rgba(0,0,0,0.15);
30
+ border-radius:60px !important;
31
+ margin-top:-80px;
32
+ border:10px solid whitesmoke;
33
+ }
34
+
35
+ .tmm_4_columns .tmm_member > img {
36
+ width:100px;
37
+ height:100px;
38
+ margin-top:-70px;
39
+ border-radius:40px !important;
40
+ border:6px solid whitesmoke;
41
+ }
42
+
43
+ .tmm_member .tmm_textblock .tmm_scblock {padding-top:10px;}
44
+ .tmm_member .tmm_textblock {padding:10px 20px;}
45
+ .tmm_member .tmm_textblock .tmm_sociallink {clear:both; margin-bottom:20px;}
46
+ .tmm_member .tmm_textblock .tmm_sociallink img {border:none; width:24px; height:24px; box-shadow: 0 0 0 0;margin:10px 5px;}
47
+ .tmm_4_columns .tmm_member .tmm_textblock .tmm_sociallink img {width:21px; height:21px; margin:6px 3px;}
48
+ .tmm_member .tmm_textblock .tmm_sociallink img:hover {opacity:0.8;}
49
+
50
+ .tmm_names {font-size:22px; margin-bottom:8px; margin-top:10px; font-weight:300; line-height:24px;}
51
+ .tmm_4_columns .tmm_names {font-size:19px;}
52
+ .tmm_fname {display:inline;}
53
+ .tmm_lname {display:inline;}
54
+ .tmm_job {font-size:14px; color:#a2a5a4; text-transform:uppercase;}
55
+ .tmm_desc {padding:10px; margin-top:19px; margin-bottom:10px; font-size:14px;}
56
+ .tmm_4_columns .tmm_desc {padding:8px; margin-top:14px; margin-bottom:8px; font-size:13px;}
57
+
58
+ /* TABLETS */
59
+ @media only screen and (min-width: 40em) and (max-width: 64.063em) {
60
+ .tmm_4_columns .tmm_member {width: 40%; margin-left:5%; margin-right:5%;}
61
+ .tmm_names {font-size:17px; margin-bottom:8px; margin-top:10px; font-weight:300; line-height:24px;}
62
+ .tmm_job {font-size:13px; color:#a2a5a4; text-transform:uppercase;}
63
+ .tmm_desc {padding:10px; margin-top:19px; margin-bottom:10px; font-size:14px; line-height:23px;}
64
+ .tmm_4_columns .tmm_desc {font-size:15px; line-height:23px;}
65
+ .tmm_3_columns .tmm_member > img {
66
+ width:100px;
67
+ height:100px;
68
+ border-radius:40px !important;
69
+ border:9px solid whitesmoke;
70
+ }
71
+ .tmm_4_columns .tmm_member > img {
72
+ width:150px;
73
+ height:150px;
74
+ border-radius:60px !important;
75
+ border:9px solid whitesmoke;
76
+ }
77
+ .tmm_4_columns .tmm_member .tmm_textblock .tmm_sociallink img {width:24px; height:24px; margin:10px 5px;}
78
+ }
79
+
80
+ /* MOBILE */
81
+ @media only screen and (max-width: 40em) {
82
+ .tmm_member {width: 96%; margin:0 2%; margin-top:120px;}
83
+ .tmm_3_columns .tmm_member, .tmm_4_columns .tmm_member {width: 96%; margin:0 2%; margin-top:120px;}
84
+ .tmm_4_columns .tmm_desc {font-size:15px;}
85
+ .tmm_4_columns .tmm_member > img {
86
+ width:150px;
87
+ height:150px;
88
+ border-radius:60px !important;
89
+ border:9px solid whitesmoke;
90
+ }
91
+ .tmm_4_columns .tmm_names {font-size:22px;}
92
+ .tmm_4_columns .tmm_member .tmm_textblock .tmm_sociallink img {width:24px; height:24px; margin:10px 5px;}
93
+ }
css/tmm_custom_style.min.css ADDED
@@ -0,0 +1 @@
1
+ @charset "UTF-8";.tmm_wrap{width:100%;margin-bottom:30px;text-align:center}.clearer{clear:both}.tmm_member{margin-top:100px;height:auto;float:left;text-align:center;-webkit-box-shadow:1px 0 5px 0 rgba(0,0,0,.05);-moz-box-shadow:1px 0 5px 0 rgba(0,0,0,.05);box-shadow:1px 0 5px 0 rgba(0,0,0,.05);border-top:5px solid lightgrey;border-bottom:8px solid #f5f5f5}.tmm_three_entries{clear:both}.tmm_3_columns .tmm_member{width:31%;margin-right:1%;margin-left:1%}.tmm_4_columns .tmm_member{width:23%;margin-right:1%;margin-left:1%}.tmm_member>img{width:150px;height:150px;-webkit-box-shadow:2px 0 15px 0 rgba(0,0,0,.15);-moz-box-shadow:2px 0 15px 0 rgba(0,0,0,.15);box-shadow:2px 0 15px 0 rgba(0,0,0,.15);border-radius:60px!important;margin-top:-80px;border:10px solid #f5f5f5}.tmm_4_columns .tmm_member>img{width:100px;height:100px;margin-top:-70px;border-radius:40px!important;border:6px solid #f5f5f5}.tmm_member .tmm_textblock .tmm_scblock{padding-top:10px}.tmm_member .tmm_textblock{padding:10px 20px}.tmm_member .tmm_textblock .tmm_sociallink{clear:both;margin-bottom:20px}.tmm_member .tmm_textblock .tmm_sociallink img{border:none;width:24px;height:24px;box-shadow:0 0;margin:10px 5px}.tmm_4_columns .tmm_member .tmm_textblock .tmm_sociallink img{width:21px;height:21px;margin:6px 3px}.tmm_member .tmm_textblock .tmm_sociallink img:hover{opacity:.8}.tmm_names{font-size:22px;margin-bottom:8px;margin-top:10px;font-weight:300;line-height:24px}.tmm_4_columns .tmm_names{font-size:19px}.tmm_fname,.tmm_lname{display:inline}.tmm_job{font-size:14px;color:#a2a5a4;text-transform:uppercase}.tmm_desc{padding:10px;margin-top:19px;margin-bottom:10px;font-size:14px}.tmm_4_columns .tmm_desc{padding:8px;margin-top:14px;margin-bottom:8px;font-size:13px}@media only screen and (min-width:40em) and (max-width:64.063em){.tmm_4_columns .tmm_member{width:40%;margin-left:5%;margin-right:5%}.tmm_names{font-size:17px;margin-bottom:8px;margin-top:10px;font-weight:300;line-height:24px}.tmm_job{font-size:13px;color:#a2a5a4;text-transform:uppercase}.tmm_desc{padding:10px;margin-top:19px;margin-bottom:10px;font-size:14px;line-height:23px}.tmm_4_columns .tmm_desc{font-size:15px;line-height:23px}.tmm_3_columns .tmm_member>img{width:100px;height:100px;border-radius:40px!important;border:9px solid #f5f5f5}.tmm_4_columns .tmm_member>img{width:150px;height:150px;border-radius:60px!important;border:9px solid #f5f5f5}.tmm_4_columns .tmm_member .tmm_textblock .tmm_sociallink img{width:24px;height:24px;margin:10px 5px}}@media only screen and (max-width:40em){.tmm_3_columns .tmm_member,.tmm_4_columns .tmm_member,.tmm_member{width:96%;margin:120px 2% 0}.tmm_4_columns .tmm_desc{font-size:15px}.tmm_4_columns .tmm_member>img{width:150px;height:150px;border-radius:60px!important;border:9px solid #f5f5f5}.tmm_4_columns .tmm_names{font-size:22px}.tmm_4_columns .tmm_member .tmm_textblock .tmm_sociallink img{width:24px;height:24px;margin:10px 5px}}
drkfr/Gruntfile.js ADDED
@@ -0,0 +1,39 @@
1
+ /*global module:false*/
2
+ module.exports = function(grunt) {
3
+
4
+ // Project configuration.
5
+ grunt.initConfig({
6
+ // Metadata.
7
+ pkg: grunt.file.readJSON('package.json'),
8
+ banner: '/**\n' +
9
+ ' * <%= pkg.title || pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
10
+ '<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' +
11
+ ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>;' + ' License: <%= pkg.license %>\n' +
12
+ ' */',
13
+ cssmin: {
14
+ combine: {
15
+ options: {
16
+ banner: '<%= banner %>'
17
+ },
18
+ files: {
19
+ 'css/dist/DKTBS.min.css': [
20
+ 'css/src/layout.css',
21
+ 'css/src/generic.css',
22
+ 'css/src/repeatable.css',
23
+ 'css/src/sortable.css',
24
+ 'css/src/group.css',
25
+ 'css/src/file.css',
26
+ 'css/src/misc-fields.css'
27
+ ]
28
+ }
29
+ }
30
+ }
31
+ });
32
+
33
+ // These plugins provide necessary tasks.
34
+ grunt.loadNpmTasks('grunt-contrib-cssmin');
35
+
36
+ // Default task.
37
+ grunt.registerTask('default', [ 'cssmin' ] );
38
+
39
+ };
drkfr/class.drkfr-meta-box.php ADDED
@@ -0,0 +1,379 @@
1
+ <?php
2
+
3
+ /**
4
+ * Create meta boxes
5
+ */
6
+ class drkfr_Meta_Box {
7
+
8
+ protected $_meta_box;
9
+ private $fields = array();
10
+
11
+ function __construct( $meta_box ) {
12
+
13
+ $this->_meta_box = $meta_box;
14
+
15
+ if ( empty( $this->_meta_box['id'] ) )
16
+ $this->_meta_box['id'] = sanitize_title( $this->_meta_box['title'] );
17
+
18
+ add_action( 'dbx_post_advanced', array( &$this, 'init_fields_for_post' ) );
19
+ add_action( 'drkfr_init_fields', array( &$this, 'init_fields' ) );
20
+
21
+ global $pagenow;
22
+
23
+ add_action( 'admin_menu', array( &$this, 'add' ) );
24
+ add_action( 'save_post', array( &$this, 'save_for_post' ) );
25
+ add_action( 'edit_attachment', array( &$this, 'save_for_post' ) );
26
+ add_action( 'drkfr_save_fields', array( &$this, 'save' ) );
27
+
28
+ add_action( 'admin_enqueue_scripts', array( &$this, 'enqueue_scripts' ) );
29
+ add_action( 'admin_enqueue_scripts', array( &$this, 'enqueue_styles' ) );
30
+
31
+ }
32
+
33
+ public function init_fields( $post_id = 0 ) {
34
+
35
+ foreach ( $this->_meta_box['fields'] as $key => $field ) {
36
+
37
+ $values = array();
38
+
39
+ $args = $field;
40
+ unset( $args['id'] );
41
+ unset( $args['type'] );
42
+ unset( $args['name'] );
43
+
44
+ $class = _drkfr_field_class_for_type( $field['type'] );
45
+
46
+ // If we are on a post edit screen - get metadata value of the field for this post
47
+ if ( $post_id ) {
48
+ $values = (array) get_post_meta( $post_id, $field['id'], false );
49
+ }
50
+
51
+ if ( class_exists( $class ) ) {
52
+ $this->fields[] = new $class( $field['id'], $field['name'], (array) $values, $args );
53
+ }
54
+
55
+ }
56
+
57
+ }
58
+
59
+ public function init_fields_for_post() {
60
+
61
+ global $post, $temp_ID;
62
+
63
+ // Get the current ID
64
+ if( isset( $_GET['post'] ) )
65
+ $post_id = $_GET['post'];
66
+
67
+ elseif( isset( $_POST['post_ID'] ) )
68
+ $post_id = $_POST['post_ID'];
69
+
70
+ elseif ( ! empty( $post->ID ) )
71
+ $post_id = $post->ID;
72
+
73
+ if ( is_page() || ! isset( $post_id ) )
74
+ return false;
75
+
76
+ $this->init_fields( (int) $post_id );
77
+
78
+ }
79
+
80
+ function enqueue_scripts() {
81
+
82
+ wp_enqueue_script( 'drkfr-scripts', trailingslashit( drkfr_URL ) . 'js/drkfr.js', array( 'jquery' ) );
83
+
84
+ wp_localize_script( 'drkfr-scripts', 'drkfrData', array(
85
+ 'strings' => array(
86
+ 'confirmDeleteField' => __( 'Are you sure you want to delete this field?', 'drkfr' )
87
+ )
88
+ ) );
89
+
90
+ foreach ( $this->fields as $field )
91
+ $field->enqueue_scripts();
92
+
93
+ }
94
+
95
+ function enqueue_styles() {
96
+
97
+ $suffix = drkfr_DEV ? '' : '.min';
98
+
99
+ if ( version_compare( get_bloginfo( 'version' ), '3.8', '>=' ) )
100
+ wp_enqueue_style( 'drkfr-styles', trailingslashit( drkfr_URL ) . "css/dist/drkfr$suffix.css" );
101
+ else
102
+ wp_enqueue_style( 'drkfr-styles', trailingslashit( drkfr_URL ) . 'css/legacy.css' );
103
+
104
+ foreach ( $this->fields as $field )
105
+ $field->enqueue_styles();
106
+
107
+ }
108
+
109
+ // Add metabox
110
+ function add() {
111
+
112
+ $this->_meta_box['context'] = empty($this->_meta_box['context']) ? 'normal' : $this->_meta_box['context'];
113
+ $this->_meta_box['priority'] = empty($this->_meta_box['priority']) ? 'low' : $this->_meta_box['priority'];
114
+
115
+ // Backwards compatablilty.
116
+ if ( isset( $this->_meta_box['show_on']['key'] ) ) {
117
+ $this->_meta_box['show_on'][ $this->_meta_box['show_on']['key'] ] = $this->_meta_box['show_on']['value'];
118
+ unset( $this->_meta_box['show_on']['key'] );
119
+ unset( $this->_meta_box['show_on']['value'] );
120
+ }
121
+
122
+ foreach ( (array) $this->_meta_box['pages'] as $page ) {
123
+ if ( $this->is_metabox_displayed() ) {
124
+ add_meta_box( $this->_meta_box['id'], $this->_meta_box['title'], array(&$this, 'show'), $page, $this->_meta_box['context'], $this->_meta_box['priority'] ) ;
125
+ }
126
+ }
127
+
128
+ }
129
+
130
+ /**
131
+ * Handle 'Show On' and 'Hide On' Filters
132
+ */
133
+ function is_metabox_displayed() {
134
+ $display = true;
135
+ $display = $this->add_for_id( $display );
136
+ $display = $this->hide_for_id( $display );
137
+ $display = $this->add_for_page_template( $display );
138
+ $display = $this->hide_for_page_template( $display );
139
+ return $display;
140
+ }
141
+
142
+ // Add drkfr for ID
143
+ function add_for_id( $display ) {
144
+
145
+ if ( ! isset( $this->_meta_box['show_on']['id'] ) ) {
146
+ return $display;
147
+ }
148
+
149
+ // Don't show drkfr if we can't identify ID of a post
150
+ $post_id = $this->get_post_id();
151
+
152
+ if ( ! isset( $post_id ) ) {
153
+ return false;
154
+ }
155
+
156
+ // If value isn't an array, turn it into one
157
+ $this->_meta_box['show_on']['id'] = ! is_array( $this->_meta_box['show_on']['id'] ) ? array( $this->_meta_box['show_on']['id'] ) : $this->_meta_box['show_on']['id'];
158
+
159
+ return in_array( $post_id, $this->_meta_box['show_on']['id'] );
160
+
161
+ }
162
+
163
+ // Hide drkfr for ID
164
+ function hide_for_id( $display ) {
165
+
166
+ if ( ! isset( $this->_meta_box['hide_on']['id'] ) ) {
167
+ return $display;
168
+ }
169
+
170
+ // Return if we can't identify ID of a post
171
+ $post_id = $this->get_post_id();
172
+ if ( ! isset( $post_id ) ) {
173
+ return $display;
174
+ }
175
+
176
+ // If value isn't an array, turn it into one
177
+ $this->_meta_box['hide_on']['id'] = ! is_array( $this->_meta_box['hide_on']['id'] ) ? array( $this->_meta_box['hide_on']['id'] ) : $this->_meta_box['hide_on']['id'];
178
+
179
+ return ! in_array( $post_id, $this->_meta_box['hide_on']['id'] );
180
+
181
+ }
182
+
183
+ // Add drkfr for Page Template
184
+ function add_for_page_template( $display ) {
185
+
186
+ if ( ! isset( $this->_meta_box['show_on']['page-template'] ) ) {
187
+ return $display;
188
+ }
189
+
190
+ // Return false if we can't identify ID of a post
191
+ $post_id = $this->get_post_id();
192
+ if ( ! isset( $post_id ) ) {
193
+ return false;
194
+ }
195
+
196
+ // Get current template
197
+ $current_template = get_post_meta( $post_id, '_wp_page_template', true );
198
+
199
+ // If value isn't an array, turn it into one
200
+ $this->_meta_box['show_on']['page-template'] = ! is_array( $this->_meta_box['show_on']['page-template'] ) ? array( $this->_meta_box['show_on']['page-template'] ) : $this->_meta_box['show_on']['page-template'];
201
+
202
+ return in_array( $current_template, $this->_meta_box['show_on']['page-template'] );
203
+
204
+ }
205
+
206
+ // Hide drkfr for Page Template
207
+ function hide_for_page_template( $display ) {
208
+
209
+ if ( ! isset( $this->_meta_box['hide_on']['page-template'] ) ) {
210
+ return $display;
211
+ }
212
+
213
+ // Return $display if we can't identify ID of a post and hence its current template
214
+ $post_id = $this->get_post_id();
215
+
216
+ if ( ! isset( $post_id ) ) {
217
+ return $display;
218
+ }
219
+
220
+ // Get current template
221
+ $current_template = get_post_meta( $post_id, '_wp_page_template', true );
222
+
223
+ // If value isn't an array, turn it into one
224
+ $this->_meta_box['hide_on']['page-template'] = ! is_array( $this->_meta_box['hide_on']['page-template'] ) ? array( $this->_meta_box['hide_on']['page-template'] ) : $this->_meta_box['hide_on']['page-template'];
225
+
226
+ return ! in_array( $current_template, $this->_meta_box['hide_on']['page-template'] );
227
+
228
+ }
229
+
230
+ // display fields
231
+ function show() { ?>
232
+
233
+ <input type="hidden" name="wp_meta_box_nonce" value="<?php esc_attr_e( wp_create_nonce( basename(__FILE__) ) ); ?>" />
234
+
235
+ <?php self::layout_fields( $this->fields );
236
+
237
+ }
238
+
239
+ /**
240
+ * Layout an array of fields, depending on their 'cols' property.
241
+ *
242
+ * This is a static method so other fields can use it that rely on sub fields
243
+ *
244
+ * @param drkfr_Field[] $fields
245
+ */
246
+ static function layout_fields( array $fields ) { ?>
247
+
248
+ <div class="drkfr_metabox">
249
+
250
+ <?php $current_colspan = 0;
251
+
252
+ foreach ( $fields as $field ) :
253
+
254
+ if ( $current_colspan == 0 ) : ?>
255
+
256
+ <div class="drkfr-row">
257
+
258
+ <?php endif;
259
+
260
+ $current_colspan += $field->args['cols'];
261
+
262
+ $classes = array( 'field', get_class($field) );
263
+
264
+ if ( ! empty( $field->args['repeatable'] ) )
265
+ $classes[] = 'repeatable';
266
+
267
+ if ( ! empty( $field->args['sortable'] ) )
268
+ $classes[] = 'drkfr-sortable';
269
+
270
+ $attrs = array(
271
+ sprintf( 'id="%s"', sanitize_html_class( $field->id ) ),
272
+ sprintf( 'class="%s"', esc_attr( implode(' ', array_map( 'sanitize_html_class', $classes ) ) ) )
273
+ );
274
+
275
+ // Field Repeatable Max.
276
+ if ( isset( $field->args['repeatable_max'] ) )
277
+ $attrs[] = sprintf( 'data-rep-max="%s"', intval( $field->args['repeatable_max'] ) );
278
+
279
+ ?>
280
+
281
+ <div class="drkfr-cell-<?php echo intval( $field->args['cols'] ); ?>">
282
+
283
+ <div <?php echo implode( ' ', $attrs ); ?>>
284
+ <?php $field->display(); ?>
285
+ </div>
286
+
287
+ <input type="hidden" name="_drkfr_present_<?php esc_attr_e( $field->id ); ?>" value="1" />
288
+
289
+ </div>
290
+
291
+ <?php if ( $current_colspan == 12 || $field === end( $fields ) ) :
292
+
293
+ $current_colspan = 0; ?>
294
+
295
+ </div><!-- .drkfr-row -->
296
+
297
+ <?php endif; ?>
298
+
299
+ <?php endforeach; ?>
300
+
301
+ </div>
302
+
303
+ <?php }
304
+
305
+ function strip_repeatable( $values ) {
306
+
307
+ foreach ( $values as $key => $value ) {
308
+
309
+ if ( false !== strpos( $key, 'drkfr-group-x' ) || false !== strpos( $key, 'drkfr-field-x' ) )
310
+ unset( $values[$key] );
311
+
312
+ elseif ( is_array( $value ) )
313
+ $values[$key] = $this->strip_repeatable( $value );
314
+
315
+ }
316
+
317
+ return $values;
318
+ }
319
+
320
+ // Save data from metabox
321
+ function save( $post_id = 0 ) {
322
+
323
+ // Verify nonce
324
+ if ( ! isset( $_POST['wp_meta_box_nonce'] ) || ! wp_verify_nonce( $_POST['wp_meta_box_nonce'], basename( __FILE__ ) ) )
325
+ return $post_id;
326
+
327
+ foreach ( $this->_meta_box['fields'] as $field ) {
328
+
329
+ // Verify this meta box was shown on the page
330
+ if ( ! isset( $_POST['_drkfr_present_' . $field['id'] ] ) )
331
+ continue;
332
+
333
+ if ( isset( $_POST[ $field['id'] ] ) )
334
+ $value = (array) $_POST[ $field['id'] ];
335
+ else
336
+ $value = array();
337
+
338
+ $value = $this->strip_repeatable( $value );
339
+
340
+ if ( ! $class = _drkfr_field_class_for_type( $field['type'] ) ) {
341
+ do_action( 'drkfr_save_' . $field['type'], $field, $value );
342
+ }
343
+
344
+ $field_obj = new $class( $field['id'], $field['name'], $value, $field );
345
+
346
+ $field_obj->save( $post_id, $value );
347
+
348
+ }
349
+
350
+ // If we are not on a post, need to refresh the field objects to reflect new values, as we do not get a redirect
351
+ if ( ! $post_id ) {
352
+ $this->fields = array();
353
+ $this->init_fields();
354
+ }
355
+ }
356
+
357
+ // Save the on save_post hook
358
+ function save_for_post( $post_id ) {
359
+
360
+ // check autosave
361
+ if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
362
+ return $post_id;
363
+
364
+ $this->save( $post_id );
365
+
366
+ }
367
+
368
+ function get_post_id() {
369
+
370
+ $post_id = isset( $_GET['post'] ) ? $_GET['post'] : null;
371
+
372
+ if ( ! $post_id && isset( $_POST['post_id'] ) ) {
373
+ $post_id = $_POST['post_id'];
374
+ }
375
+
376
+ return $post_id;
377
+
378
+ }
379
+ }
drkfr/classes.fields.php ADDED
@@ -0,0 +1,1675 @@
1
+ <?php
2
+
3
+ /**
4
+ * Abstract class for all fields.
5
+ * Subclasses need only override html()
6
+ *
7
+ * @abstract
8
+ */
9
+ abstract class drkfr_Field {
10
+
11
+ public $value;
12
+ public $field_index = 0;
13
+
14
+ public function __construct( $name, $title, array $values, $args = array() ) {
15
+
16
+ $this->id = $name;
17
+ $this->name = $name . '[]';
18
+ $this->title = $title;
19
+ $this->args = wp_parse_args( $args, $this->get_default_args() );
20
+
21
+ // Deprecated argument: 'std'
22
+ if ( ! empty( $this->args['std'] ) && empty( $this->args['default'] ) ) {
23
+ $this->args['default'] = $this->args['std'];
24
+ _deprecated_argument( 'drkfr_Field', '0.9', "field argument 'std' is deprecated, use 'default' instead" );
25
+ }
26
+
27
+ if ( ! empty( $this->args['options'] ) && is_array( reset( $this->args['options'] ) ) ) {
28
+ $re_format = array();
29
+ foreach ( $this->args['options'] as $option ) {
30
+ $re_format[$option['value']] = $option['name'];
31
+ }
32
+ $this->args['options'] = $re_format;
33
+ }
34
+
35
+ // If the field has a custom value populator callback
36
+ if ( ! empty( $args['values_callback'] ) )
37
+ $this->values = call_user_func( $args['values_callback'], get_the_id() );
38
+ else
39
+ $this->values = $values;
40
+
41
+ $this->value = reset( $this->values );
42
+
43
+ }
44
+
45
+ /**
46
+ * Get the default args for the abstract field.
47
+ * These args are available to all fields.
48
+ *
49
+ * @return array $args
50
+ */
51
+ public function get_default_args() {
52
+ return apply_filters(
53
+ 'drkfr_field_default_args',
54
+ array(
55
+ 'desc' => '',
56
+ 'repeatable' => false,
57
+ 'sortable' => false,
58
+ 'repeatable_max' => null,
59
+ 'show_label' => false,
60
+ 'readonly' => false,
61
+ 'disabled' => false,
62
+ 'default' => '',
63
+ 'cols' => '12',
64
+ 'style' => '',
65
+ 'class' => '',
66
+ 'data_delegate' => null,
67
+ 'save_callback' => null,
68
+ 'string-repeat-field' => __( 'Add New', 'drkfr' ),
69
+ 'string-delete-field' => __( 'Remove Field', 'drkfr' ),
70
+ ),
71
+ get_class( $this )
72
+ );
73
+ }
74
+
75
+ /**
76
+ * Enqueue all scripts required by the field.
77
+ *
78
+ * @uses wp_enqueue_script()
79
+ */
80
+ public function enqueue_scripts() {
81
+
82
+ if ( isset( $this->args['sortable'] ) && $this->args['sortable'] )
83
+ wp_enqueue_script( 'jquery-ui-sortable' );
84
+
85
+ }
86
+
87
+ /**
88
+ * Enqueue all styles required by the field.
89
+ *
90
+ * @uses wp_enqueue_style()
91
+ */
92
+ public function enqueue_styles() {}
93
+
94
+ /**
95
+ * Output the field input ID attribute.
96
+ *
97
+ * If multiple inputs are required for a single field,
98
+ * use the append parameter to add unique identifier.
99
+ *
100
+ * @param string $append
101
+ * @return null
102
+ */
103
+ public function id_attr( $append = null ) {
104
+
105
+ printf( 'id="%s"', esc_attr( $this->get_the_id_attr( $append ) ) );
106
+
107
+ }
108
+
109
+ /**
110
+ * Output the for attribute for the field.
111
+ *
112
+ *
113
+ *
114
+ * If multiple inputs are required for a single field,
115
+ * use the append parameter to add unique identifier.
116
+ *
117
+ * @param string $append
118
+ * @return null
119
+ */
120
+ public function get_the_id_attr( $append = null ) {
121
+
122
+ $id = $this->id;
123
+
124
+ if ( isset( $this->parent ) ) {
125
+ $parent_id = preg_replace( '/drkfr\-field\-(\d+|x)/', 'drkfr-group-$1', $this->parent->get_the_id_attr() );
126
+ $id = $parent_id . '[' . $id . ']';
127
+ }
128
+
129
+ $id .= '-drkfr-field-' . $this->field_index;
130
+
131
+ if ( ! is_null( $append ) )
132
+ $id .= '-' . $append;
133
+
134
+ $id = str_replace( array( '[', ']', '--' ), '-', $id );
135
+
136
+ return $id;
137
+
138
+ }
139
+
140
+ /**
141
+ * Return the field input ID attribute value.
142
+ *
143
+ * If multiple inputs are required for a single field,
144
+ * use the append parameter to add unique identifier.
145
+ *
146
+ * @param string $append
147
+ * @return string id attribute value.
148
+ */
149
+ public function for_attr( $append = null ) {
150
+
151
+ printf( 'for="%s"', esc_attr( $this->get_the_id_attr( $append ) ) );
152
+
153
+ }
154
+
155
+ public function name_attr( $append = null ) {
156
+
157
+ printf( 'name="%s"', esc_attr( $this->get_the_name_attr( $append ) ) );
158
+
159
+ }
160
+
161
+ public function get_the_name_attr( $append = null ) {
162
+
163
+ $name = str_replace( '[]', '', $this->name );
164
+
165
+ if ( isset( $this->parent ) ) {
166
+ $parent_name = preg_replace( '/drkfr\-field\-(\d+|x)/', 'drkfr-group-$1', $this->parent->get_the_name_attr() );
167
+ $name = $parent_name . '[' . $name . ']';
168
+ }
169
+
170
+ $name .= "[drkfr-field-$this->field_index]";
171
+
172
+ if ( ! is_null( $append ) )
173
+ $name .= $append;
174
+
175
+ return $name;
176
+
177
+ }
178
+
179
+ public function class_attr( $classes = '' ) {
180
+
181
+ if ( $classes = implode( ' ', array_map( 'sanitize_html_class', array_filter( array_unique( explode( ' ', $classes . ' ' . $this->args['class'] ) ) ) ) ) ) { ?>
182
+
183
+ class="<?php echo esc_attr( $classes ); ?>"
184
+
185
+ <?php }
186
+
187
+ }
188
+
189
+ /**
190
+ * Get JS Safe ID.
191
+ *
192
+ * For use as a unique field identifier in javascript.
193
+ */
194
+ public function get_js_id() {
195
+
196
+ return str_replace( array( '-', '[', ']', '--' ),'_', $this->get_the_id_attr() ); // JS friendly ID
197
+
198
+ }
199
+
200
+ public function boolean_attr( $attrs = array() ) {
201
+
202
+ if ( $this->args['readonly'] )
203
+ $attrs[] = 'readonly';
204
+
205
+ if ( $this->args['disabled'] )
206
+ $attrs[] = 'disabled';
207
+
208
+ $attrs = array_filter( array_unique( $attrs ) );
209
+
210
+ foreach ( $attrs as $attr )
211
+ echo esc_html( $attr ) . '="' . esc_attr( $attr ) . '"';
212
+
213
+ }
214
+
215
+ /**
216
+ * Check if this field has a data delegate set
217
+ *
218
+ * @return boolean
219
+ */
220
+ public function has_data_delegate() {
221
+ return (bool) $this->args['data_delegate'];
222
+ }
223
+
224
+ /**
225
+ * Get the array of data from the data delegate
226
+ *
227
+ * @return array mixed
228
+ */
229
+ protected function get_delegate_data() {
230
+
231
+ if ( $this->args['data_delegate'] )
232
+ return call_user_func_array( $this->args['data_delegate'], array( $this ) );
233
+
234
+ return array();
235
+
236
+ }
237
+
238
+ public function get_value() {
239
+ return ( $this->value || $this->value === '0' ) ? $this->value : $this->args['default'];
240
+ }
241
+
242
+ public function &get_values() {
243
+ return $this->values;
244
+ }
245
+
246
+ public function set_values( array $values ) {
247
+
248
+ $this->values = $values;
249
+
250
+ unset( $this->value );
251
+
252
+ }
253
+
254
+ public function parse_save_values() {}
255
+
256
+ public function parse_save_value() {}
257
+
258
+ /**
259
+ * @todo this surely only works for posts
260
+ * @todo why do values need to be passed in, they can already be passed in on construct
261
+ */
262
+ public function save( $post_id, $values ) {
263
+
264
+ // Don't save readonly values.
265
+ if ( $this->args['readonly'] )
266
+ return;
267
+
268
+ $this->values = $values;
269
+ $this->parse_save_values();
270
+
271
+ // Allow override from args
272
+ if ( ! empty( $this->args['save_callback'] ) ) {
273
+
274
+ call_user_func( $this->args['save_callback'], $this->values, $post_id );
275
+
276
+ return;
277
+
278
+ }
279
+
280
+ // If we are not on a post edit screen
281
+ if ( ! $post_id )
282
+ return;
283
+
284
+ delete_post_meta( $post_id, $this->id );
285
+
286
+ foreach( $this->values as $v ) {
287
+
288
+ $this->value = $v;
289
+ $this->parse_save_value();
290
+
291
+ if ( $this->value || $this->value === '0' )
292
+ add_post_meta( $post_id, $this->id, $this->value );
293
+
294
+ }
295
+ }
296
+
297
+ public function title() {
298
+
299
+ if ( $this->title ) { ?>
300
+
301
+ <div class="field-title">
302
+ <label <?php $this->for_attr(); ?>>
303
+ <?php echo esc_html( $this->title ); ?>
304
+ </label>
305
+ </div>
306
+
307
+ <?php }
308
+
309
+ }
310
+
311
+ public function description() {
312
+
313
+ if ( ! empty( $this->args['desc'] ) ) { ?>
314
+
315
+ <div class="drkfr_metabox_description">
316
+ <?php echo wp_kses_post( $this->args['desc'] ); ?>
317
+ </div>
318
+
319
+ <?php }
320
+
321
+ }
322
+
323
+ public function display() {
324
+
325
+ // If there are no values and it's not repeateble, we want to do one with empty string
326
+ if ( ! $this->get_values() && ! $this->args['repeatable'] )
327
+ $values = array( '' );
328
+ else
329
+ $values = $this->get_values();
330
+
331
+ $this->title();
332
+
333
+ $this->description();
334
+
335
+ $i = 0;
336
+ foreach ( $values as $key => $value ) {
337
+
338
+ $this->field_index = $i;
339
+ $this->value = $value; ?>
340
+
341
+ <div class="field-item" data-class="<?php echo esc_attr( get_class( $this ) ); ?>" style="position: relative; <?php echo esc_attr( $this->args['style'] ); ?>">
342
+
343
+ <?php if ( $this->args['repeatable'] ) : ?>
344
+ <button class="drkfr-delete-field" title="<?php echo esc_attr( $this->args['string-delete-field'] ); ?>">
345
+ <span class="drkfr-delete-field-icon">&times;</span>
346
+ </button>
347
+ <?php endif; ?>
348
+
349
+ <?php $this->html(); ?>
350
+
351
+ </div>
352
+
353
+ <?php
354
+
355
+ $i++;
356
+
357
+ }
358
+
359
+ // Insert a hidden one if it's repeatable
360
+ if ( $this->args['repeatable'] ) {
361
+
362
+ $this->field_index = 'x'; // x used to distinguish hidden fields.
363
+ $this->value = ''; ?>
364
+
365
+ <div class="field-item hidden" data-class="<?php echo esc_attr( get_class( $this ) ); ?>" style="position: relative; <?php echo esc_attr( $this->args['style'] ); ?>">
366
+
367
+ <?php if ( $this->args['repeatable'] ) : ?>
368
+ <button class="drkfr-delete-field" title="<?php echo esc_attr( $this->args['string-delete-field'] ); ?>">
369
+ <span class="drkfr-delete-field-icon">&times;</span>
370
+ <?php echo esc_html( $this->args['string-delete-field'] ); ?>
371
+ </button>
372
+ <?php endif; ?>
373
+
374
+ <?php $this->html(); ?>
375
+
376
+ </div>
377
+
378
+ <button class="button repeat-field"><?php echo esc_html( $this->args['string-repeat-field'] ); ?></button>
379
+
380
+ <?php }
381
+
382
+ }
383
+
384
+ }
385
+
386
+ /**
387
+ * Standard text field.
388
+ *
389
+ * @extends drkfr_Field
390
+ */
391
+ class drkfr_Text_Field extends drkfr_Field {
392
+
393
+ public function html() { ?>
394
+
395
+ <input type="text" <?php $this->id_attr(); ?> <?php $this->boolean_attr(); ?> <?php $this->class_attr(); ?> <?php $this->name_attr(); ?> value="<?php echo esc_attr( $this->get_value() ); ?>" />
396
+
397
+ <?php }
398
+ }
399
+
400
+ class drkfr_Text_Small_Field extends drkfr_Text_Field {
401
+
402
+ public function html() {
403
+
404
+ $this->args['class'] .= ' drkfr_text_small';
405
+
406
+ parent::html();
407
+
408
+ }
409
+ }
410
+
411
+ /**
412
+ * Field for image upload / file updoad.
413
+ *
414
+ * @todo ability to set image size (preview image) from caller
415
+ */
416
+ class drkfr_File_Field extends drkfr_Field {
417
+
418
+ /**
419
+ * Return the default args for the File field.
420
+ *
421
+ * @return array $args
422
+ */
423
+ public function get_default_args() {
424
+ return array_merge(
425
+ parent::get_default_args(),
426
+ array(
427
+ 'library-type' => array( 'video', 'audio', 'text', 'application' )
428
+ )
429
+ );
430
+ }
431
+
432
+ function enqueue_scripts() {
433
+
434
+ global $post_ID;
435
+ $post_ID = isset($post_ID) ? (int) $post_ID : 0;
436
+
437
+ parent::enqueue_scripts();
438
+
439
+ wp_enqueue_media( array( 'post' => $post_ID ));
440
+ wp_enqueue_script( 'drkfr-file-upload', trailingslashit( drkfr_URL ) . 'js/file-upload.js', array( 'jquery', 'drkfr-scripts' ) );
441
+
442
+ }
443
+
444
+ public function html() {
445
+
446
+ if ( $this->get_value() ) {
447
+ $src = wp_mime_type_icon( $this->get_value() );
448
+ $size = getimagesize( str_replace( site_url(), ABSPATH, $src ) );
449
+ $icon_img = '<img src="' . $src . '" ' . $size[3] . ' />';
450
+ }
451
+
452
+ $data_type = ( ! empty( $this->args['library-type'] ) ? implode( ',', $this->args['library-type'] ) : null );
453
+
454
+ ?>
455
+
456
+ <div class="drkfr-file-wrap" <?php echo 'data-type="' . esc_attr( $data_type ) . '"'; ?>>
457
+
458
+ <div class="drkfr-file-wrap-placeholder"></div>
459
+
460
+ <button class="button drkfr-file-upload <?php echo esc_attr( $this->get_value() ) ? 'hidden' : '' ?>">
461
+ <?php esc_html_e( 'Add File', 'drkfr' ); ?>
462
+ </button>
463
+
464
+ <div class="drkfr-file-holder type-file <?php echo $this->get_value() ? '' : 'hidden'; ?>">
465
+
466
+ <?php if ( $this->get_value() ) : ?>
467
+
468
+ <?php if ( isset( $icon_img ) ) echo $icon_img; ?>
469
+
470
+ <div class="drkfr-file-name">
471
+ <strong><?php echo esc_html( basename( get_attached_file( $this->get_value() ) ) ); ?></strong>
472
+ </div>
473
+
474
+ <?php endif; ?>
475
+
476
+ </div>
477
+
478
+ <button class="drkfr-remove-file button <?php echo $this->get_value() ? '' : 'hidden'; ?>">
479
+ <?php esc_html_e( 'Remove', 'drkfr' ); ?>
480
+ </button>
481
+
482
+ <input type="hidden"
483
+ <?php $this->class_attr( 'drkfr-file-upload-input' ); ?>
484
+ <?php $this->name_attr(); ?>
485
+ value="<?php echo esc_attr( $this->value ); ?>"
486
+ />
487
+
488
+ </div>
489
+
490
+ <?php }
491
+
492
+ }
493
+
494
+ class drkfr_Image_Field extends drkfr_File_Field {
495
+
496
+ /**
497
+ * Return the default args for the Image field.
498
+ *
499
+ * @return array $args
500
+ */
501
+ public function get_default_args() {
502
+ return array_merge(
503
+ parent::get_default_args(),
504
+ array(
505
+ 'size' => 'thumbnail',
506
+ 'library-type' => array( 'image' ),
507
+ 'show_size' => false
508
+ )
509
+ );
510
+ }
511
+
512
+ public function html() {
513
+
514
+ if ( $this->get_value() )
515
+ $image = wp_get_attachment_image_src( $this->get_value(), $this->args['size'], true );
516
+
517
+ // Convert size arg to array of width, height, crop
518
+ $size = $this->parse_image_size( $this->args['size'] );
519
+
520
+ // Inline styles
521
+ $styles = sprintf( 'width: %1$dpx; height: %2$dpx; line-height: %2$dpx', intval( $size['width'] ), intval( $size['height'] ) );
522
+ $placeholder_styles = sprintf( 'width: %dpx; height: %dpx;', intval( $size['width'] ) - 8, intval( $size['height'] ) - 8 );
523
+
524
+ $data_type = ( ! empty( $this->args['library-type'] ) ? implode( ',', $this->args['library-type'] ) : null );
525
+
526
+ ?>
527
+
528
+ <div class="drkfr-file-wrap" style="<?php echo esc_attr( $styles ); ?>" data-type="<?php echo esc_attr( $data_type ); ?>">
529
+
530
+ <div class="drkfr-file-wrap-placeholder" style="<?php echo esc_attr( $placeholder_styles ); ?>">
531
+
532
+ <?php if ( $this->args['show_size'] ) : ?>
533
+ <span class="dimensions">
534
+ <?php printf( '%dpx &times; %dpx', intval( $size['width'] ), intval( $size['height'] ) ); ?>
535
+ </span>
536
+ <?php endif; ?>
537
+
538
+ </div>
539
+
540
+ <button class="button drkfr-file-upload <?php echo esc_attr( $this->get_value() ) ? 'hidden' : '' ?>" data-nonce="<?php echo wp_create_nonce( 'drkfr-file-upload-nonce' ); ?>">
541
+ <?php esc_html_e( 'Add Image', 'drkfr' ); ?>
542
+ </button>
543
+
544
+ <div class="drkfr-file-holder type-img <?php echo $this->get_value() ? '' : 'hidden'; ?>" data-crop="<?php echo (bool) $size['crop']; ?>">
545
+
546
+ <?php if ( ! empty( $image ) ) : ?>
547
+ <img src="<?php echo esc_url( $image[0] ); ?>" width="<?php echo intval( $image[1] ); ?>" height="<?php echo intval( $image[2] ); ?>" />
548
+ <?php endif; ?>
549
+
550
+ </div>
551
+
552
+ <button class="drkfr-remove-file button <?php echo $this->get_value() ? '' : 'hidden'; ?>">
553
+ <?php esc_html_e( 'Remove', 'drkfr' ); ?>
554
+ </button>
555
+
556
+ <input type="hidden"
557
+ <?php $this->class_attr( 'drkfr-file-upload-input' ); ?>
558
+ <?php $this->name_attr(); ?>
559
+ value="<?php echo esc_attr( $this->value ); ?>"
560
+ />
561
+
562
+ </div>
563
+
564
+ <?php }
565
+
566
+ /**
567
+ * Parse the size argument to get pixel width, pixel height and crop information.
568
+ *
569
+ * @param string $size
570
+ * @return array width, height, crop
571
+ */
572
+ private function parse_image_size( $size ) {
573
+
574
+ // Handle string for built-in image sizes
575
+ if ( is_string( $size ) && in_array( $size, array( 'thumbnail', 'medium', 'large' ) ) ) {
576
+ return array(
577
+ 'width' => get_option( $size . '_size_w' ),
578
+ 'height' => get_option( $size . '_size_h' ),
579
+ 'crop' => get_option( $size . '_crop' )
580
+ );
581
+ }
582
+
583
+ // Handle string for additional image sizes
584
+ global $_wp_additional_image_sizes;
585
+ if ( is_string( $size ) && isset( $_wp_additional_image_sizes[$size] ) ) {
586
+ return array(
587
+ 'width' => $_wp_additional_image_sizes[$size]['width'],
588
+ 'height' => $_wp_additional_image_sizes[$size]['height'],
589
+ 'crop' => $_wp_additional_image_sizes[$size]['crop']
590
+ );
591
+ }
592
+
593
+ // Handle default WP size format.
594
+ if ( is_array( $size ) && isset( $size[0] ) && isset( $size[1] ) )
595
+ $size = array( 'width' => $size[0], 'height' => $size[1] );
596
+
597
+ return wp_parse_args( $size, array(
598
+ 'width' => get_option( 'thumbnail_size_w' ),
599
+ 'height' => get_option( 'thumbnail_size_h' ),
600
+ 'crop' => get_option( 'thumbnail_crop' )
601
+ ) );
602
+
603
+ }
604
+
605
+ /**
606
+ * Ajax callback for outputing an image src based on post data.
607
+ *
608
+ * @return null
609
+ */
610
+ static function request_image_ajax_callback() {
611
+
612
+ if ( ! ( isset( $_POST['nonce'] ) && wp_verify_nonce( $_POST['nonce'], 'drkfr-file-upload-nonce' ) ) )
613
+ return;
614
+
615
+ $id = intval( $_POST['id'] );
616
+
617
+ $size = array(
618
+ intval( $_POST['width'] ),
619
+ intval( $_POST['height'] ),
620
+ 'crop' => (bool) $_POST['crop']
621
+ );
622
+
623
+ $image = wp_get_attachment_image_src( $id, $size );
624
+ echo reset( $image );
625
+
626
+ die(); // this is required to return a proper result
627
+ }
628
+
629
+ }
630
+ add_action( 'wp_ajax_drkfr_request_image', array( 'drkfr_Image_Field', 'request_image_ajax_callback' ) );
631
+
632
+ /**
633
+ * Standard text meta box for a URL.
634
+ *
635
+ */
636
+ class drkfr_URL_Field extends drkfr_Field {
637
+
638
+ public function html() { ?>
639
+
640
+ <input type="text" <?php $this->id_attr(); ?> <?php $this->boolean_attr(); ?> <?php $this->class_attr( 'drkfr_text_url code' ); ?> <?php $this->name_attr(); ?> value="<?php echo esc_attr( esc_url( $this->value ) ); ?>" />
641
+
642
+ <?php }
643
+ }
644
+
645
+ /**
646
+ * Date picker box.
647
+ *
648
+ */
649
+ class drkfr_Date_Field extends drkfr_Field {
650
+
651
+ public function enqueue_scripts() {
652
+
653
+ parent::enqueue_scripts();
654
+
655
+ wp_enqueue_style( 'drkfr-jquery-ui', trailingslashit( drkfr_URL ) . 'css/vendor/jquery-ui/jquery-ui.css', '1.10.3' );
656
+
657
+ wp_enqueue_script( 'drkfr-datetime', trailingslashit( drkfr_URL ) . 'js/field.datetime.js', array( 'jquery', 'jquery-ui-core', 'jquery-ui-datepicker', 'drkfr-scripts' ) );
658
+ }
659
+
660
+ public function html() { ?>
661
+
662
+ <input <?php $this->id_attr(); ?> <?php $this->boolean_attr(); ?> <?php $this->class_attr( 'drkfr_text_small drkfr_datepicker' ); ?> type="text" <?php $this->name_attr(); ?> value="<?php echo esc_attr( $this->value ); ?>" />
663
+
664
+ <?php }
665
+ }
666
+
667
+ class drkfr_Time_Field extends drkfr_Field {
668
+
669
+ public function enqueue_scripts() {
670
+
671
+ parent::enqueue_scripts();
672
+
673
+ wp_enqueue_style( 'drkfr-jquery-ui', trailingslashit( drkfr_URL ) . 'css/vendor/jquery-ui/jquery-ui.css', '1.10.3' );
674
+
675
+ wp_enqueue_script( 'drkfr-timepicker', trailingslashit( drkfr_URL ) . 'js/jquery.timePicker.min.js', array( 'jquery', 'drkfr-scripts' ) );
676
+ wp_enqueue_script( 'drkfr-datetime', trailingslashit( drkfr_URL ) . 'js/field.datetime.js', array( 'jquery', 'jquery-ui-core', 'jquery-ui-datepicker', 'drkfr-scripts' ) );
677
+ }
678
+
679
+ public function html() { ?>
680
+
681
+ <input <?php $this->id_attr(); ?> <?php $this->boolean_attr(); ?> <?php $this->class_attr( 'drkfr_text_small drkfr_timepicker' ); ?> type="text" <?php $this->name_attr(); ?> value="<?php echo esc_attr( $this->value ); ?>"/>
682
+
683
+ <?php }
684
+
685
+ }
686
+
687
+ /**
688
+ * Date picker for date only (not time) box.
689
+ *
690
+ */
691
+ class drkfr_Date_Timestamp_Field extends drkfr_Field {
692
+
693
+ public function enqueue_scripts() {
694
+
695
+ parent::enqueue_scripts();
696
+
697
+ wp_enqueue_style( 'drkfr-jquery-ui', trailingslashit( drkfr_URL ) . 'css/vendor/jquery-ui/jquery-ui.css', '1.10.3' );
698
+
699
+ wp_enqueue_script( 'drkfr-timepicker', trailingslashit( drkfr_URL ) . 'js/jquery.timePicker.min.js', array( 'jquery', 'drkfr-scripts' ) );
700
+ wp_enqueue_script( 'drkfr-datetime', trailingslashit( drkfr_URL ) . 'js/field.datetime.js', array( 'jquery', 'jquery-ui-core', 'jquery-ui-datepicker', 'drkfr-scripts' ) );
701
+
702
+ }
703
+
704
+ public function html() { ?>
705
+
706
+ <input <?php $this->id_attr(); ?> <?php $this->boolean_attr(); ?> <?php $this->class_attr( 'drkfr_text_small drkfr_datepicker' ); ?> type="text" <?php $this->name_attr(); ?> value="<?php echo $this->value ? esc_attr( date( 'm\/d\/Y', $this->value ) ) : '' ?>" />
707
+
708
+ <?php }
709
+
710
+ public function parse_save_values() {
711
+
712
+ foreach( $this->values as &$value )
713
+ $value = strtotime( $value );
714
+
715
+ sort( $this->values );
716
+
717
+ }
718
+
719
+ }
720
+
721
+ /**
722
+ * Date picker for date and time (seperate fields) box.
723
+ *
724
+ */
725
+ class drkfr_Datetime_Timestamp_Field extends drkfr_Field {
726
+
727
+ public function enqueue_scripts() {
728
+
729
+ parent::enqueue_scripts();
730
+
731
+ wp_enqueue_style( 'drkfr-jquery-ui', trailingslashit( drkfr_URL ) . 'css/vendor/jquery-ui/jquery-ui.css', '1.10.3' );
732
+
733
+ wp_enqueue_script( 'drkfr-timepicker', trailingslashit( drkfr_URL ) . 'js/jquery.timePicker.min.js', array( 'jquery', 'drkfr-scripts' ) );
734
+ wp_enqueue_script( 'drkfr-datetime', trailingslashit( drkfr_URL ) . 'js/field.datetime.js', array( 'jquery', 'jquery-ui-core', 'jquery-ui-datepicker', 'drkfr-scripts' ) );
735
+ }
736
+
737
+ public function html() { ?>
738
+
739
+ <input <?php $this->id_attr('date'); ?> <?php $this->boolean_attr(); ?> <?php $this->class_attr( 'drkfr_text_small drkfr_datepicker' ); ?> type="text" <?php $this->name_attr( '[date]' ); ?> value="<?php echo $this->value ? esc_attr( date( 'm\/d\/Y', $this->value ) ) : '' ?>" />
740
+ <input <?php $this->id_attr('time'); ?> <?php $this->boolean_attr(); ?> <?php $this->class_attr( 'drkfr_text_small drkfr_timepicker' ); ?> type="text" <?php $this->name_attr( '[time]' ); ?> value="<?php echo $this->value ? esc_attr( date( 'h:i A', $this->value ) ) : '' ?>" />
741
+
742
+ <?php }
743
+
744
+ public function parse_save_values() {
745
+
746
+ // Convert all [date] and [time] values to a unix timestamp.
747
+ // If date is empty, assume delete. If time is empty, assume 00:00.
748
+ foreach( $this->values as $key => &$value ) {
749
+ if ( empty( $value['date'] ) )
750
+ unset( $this->values[$key] );
751
+ else
752
+ $value = strtotime( $value['date'] . ' ' . $value['time'] );
753
+ }
754
+
755
+ $this->values = array_filter( $this->values );
756
+ sort( $this->values );
757
+
758
+ parent::parse_save_values();
759
+
760
+ }
761
+
762
+ }
763
+
764
+ /**
765
+ * Standard text field.
766
+ *
767
+ * Args:
768
+ * - int "rows" - number of rows in the <textarea>
769
+ */
770
+ class drkfr_Textarea_Field extends drkfr_Field {
771
+
772
+ public function html() { ?>
773
+
774
+ <textarea <?php $this->id_attr(); ?> <?php $this->boolean_attr(); ?> <?php $this->class_attr(); ?> rows="<?php echo ! empty( $this->args['rows'] ) ? esc_attr( $this->args['rows'] ) : 4; ?>" <?php $this->name_attr(); ?>><?php echo esc_html( $this->value ); ?></textarea>
775
+
776
+ <?php }
777
+
778
+ }
779
+
780
+ /**
781
+ * Code style text field.
782
+ *
783
+ * Args:
784
+ * - int "rows" - number of rows in the <textarea>
785
+ */
786
+ class drkfr_Textarea_Field_Code extends drkfr_Textarea_Field {
787
+
788
+ public function html() {
789
+
790
+ $this->args['class'] .= ' code';
791
+
792
+ parent::html();
793
+
794
+ }
795
+
796
+ }
797
+
798
+ /**
799
+ * Colour picker
800
+ *
801
+ */
802
+ class drkfr_Color_Picker extends drkfr_Field {
803
+
804
+ public function enqueue_scripts() {
805
+
806
+ parent::enqueue_scripts();
807
+
808
+ wp_enqueue_script( 'drkfr-colorpicker', trailingslashit( drkfr_URL ) . 'js/field.colorpicker.js', array( 'jquery', 'wp-color-picker', 'drkfr-scripts' ) );
809
+ wp_enqueue_style( 'wp-color-picker' );
810
+ }
811
+
812
+ public function html() { ?>
813
+
814
+ <input <?php $this->id_attr(); ?> <?php $this->boolean_attr(); ?> <?php $this->class_attr( 'drkfr_colorpicker drkfr_text_small' ); ?> type="text" <?php $this->name_attr(); ?> value="<?php echo esc_attr( $this->get_value() ); ?>" />
815
+
816
+ <?php }
817
+
818
+ }
819
+
820
+ /**
821
+ * Standard radio field.
822
+ *
823
+ * Args:
824
+ * - bool "inline" - display the radio buttons inline
825
+ */
826
+ class drkfr_Radio_Field extends drkfr_Field {
827
+
828
+ /**
829
+ * Return the default args for the Radio input field.
830
+ *
831
+ * @return array $args
832
+ */
833
+ public function get_default_args() {
834
+ return array_merge(
835
+ parent::get_default_args(),
836
+ array(
837
+ 'options' => array(),
838
+ )
839
+ );
840
+ }
841
+
842
+ public function html() {
843
+
844
+ if ( $this->has_data_delegate() )
845
+ $this->args['options'] = $this->get_delegate_data(); ?>
846
+
847
+ <?php foreach ( $this->args['options'] as $key => $value ): ?>
848
+
849
+ <input <?php $this->id_attr( 'item-' . $key ); ?> <?php $this->boolean_attr(); ?> <?php $this->class_attr(); ?> type="radio" <?php $this->name_attr(); ?> value="<?php echo esc_attr( $key ); ?>" <?php checked( $key, $this->get_value() ); ?> />
850
+ <label <?php $this->for_attr( 'item-' . $key ); ?> style="margin-right: 20px;">
851
+ <?php echo esc_html( $value ); ?>
852
+ </label>
853
+
854
+ <?php endforeach; ?>
855
+
856
+ <?php }
857
+
858
+ }
859
+
860
+ /**
861
+ * Standard checkbox field.
862
+ *
863
+ */
864
+ class drkfr_Checkbox extends drkfr_Field {
865
+
866
+ public function title() {}
867
+
868
+ public function html() { ?>
869
+
870
+ <input <?php $this->id_attr(); ?> <?php $this->boolean_attr(); ?> <?php $this->class_attr(); ?> type="checkbox" <?php $this->name_attr(); ?> value="1" <?php checked( $this->get_value() ); ?> />
871
+ <label <?php $this->for_attr(); ?>><?php echo esc_html( $this->title ); ?></label>
872
+
873
+ <?php }
874
+
875
+ }
876
+
877
+
878
+ /**
879
+ * Standard title used as a splitter.
880
+ *
881
+ */
882
+ class drkfr_Title extends drkfr_Field {
883
+
884
+ public function title() {
885
+ ?>
886
+
887
+ <div class="field-title">
888
+ <h2 <?php $this->class_attr(); ?>>
889
+ <?php echo esc_html( $this->title ); ?>
890
+ </h2>
891
+ </div>
892
+
893
+ <?php
894
+
895
+ }
896
+
897
+ public function html() {}
898
+
899
+ }
900
+
901
+ /**
902
+ * wysiwyg field.
903
+ *
904
+ */
905
+ class drkfr_wysiwyg extends drkfr_Field {
906
+
907
+ /**
908
+ * Return the default args for the WYSIWYG field.
909
+ *
910
+ * @return array $args
911
+ */
912
+ public function get_default_args() {
913
+ return array_merge(
914
+ parent::get_default_args(),
915
+ array(
916
+ 'options' => array(),
917
+ )
918
+ );
919
+ }
920
+
921
+ function enqueue_scripts() {
922
+
923
+ parent::enqueue_scripts();
924
+
925
+ wp_enqueue_script( 'drkfr-wysiwyg', trailingslashit( drkfr_URL ) . 'js/field-wysiwyg.js', array( 'jquery', 'drkfr-scripts' ) );
926
+ }
927
+
928
+ public function html() {
929
+
930
+ $id = $this->get_the_id_attr();
931
+ $name = $this->get_the_name_attr();
932
+
933
+ $field_id = $this->get_js_id();
934
+
935
+ printf( '<div class="drkfr-wysiwyg" data-id="%s" data-name="%s" data-field-id="%s">', $id, $name, $field_id );
936
+
937
+ if ( $this->is_placeholder() ) {
938
+
939
+ // For placeholder, output the markup for the editor in a JS var.
940
+ ob_start();
941
+ $this->args['options']['textarea_name'] = 'drkfr-placeholder-name-' . $field_id;
942
+ wp_editor( '', 'drkfr-placeholder-id-' . $field_id, $this->args['options'] );
943
+ $editor = ob_get_clean();
944
+ $editor = str_replace( array( "\n", "\r" ), "", $editor );
945
+ $editor = str_replace( array( "'" ), '"', $editor );
946
+
947
+ ?>
948
+
949
+ <script>
950
+ if ( 'undefined' === typeof( drkfr_wysiwyg_editors ) )
951
+ var drkfr_wysiwyg_editors = {};
952
+ drkfr_wysiwyg_editors.<?php echo $field_id; ?> = '<?php echo $editor; ?>';
953
+ </script>
954
+
955
+ <?php
956
+
957
+ } else {
958
+
959
+ $this->args['options']['textarea_name'] = $name;
960
+ echo wp_editor( $this->get_value(), $id, $this->args['options'] );
961
+
962
+ }
963
+
964
+ echo '</div>';
965
+
966
+ }
967
+
968
+ /**
969
+ * Check if this is a placeholder field.
970
+ * Either the field itself, or because it is part of a repeatable group.
971
+ *
972
+ * @return bool
973
+ */
974
+ public function is_placeholder() {
975
+
976
+ if ( isset( $this->parent ) && ! is_int( $this->parent->field_index ) )
977
+ return true;
978
+
979
+ else return ! is_int( $this->field_index );
980
+
981
+ }
982
+
983
+ }
984
+
985
+ /**
986
+ * Standard select field.
987
+ *
988
+ * @supports "data_delegate"
989
+ * @args
990
+ * 'options' => array Array of options to show in the select, optionally use data_delegate instead
991
+ * 'allow_none' => bool Allow no option to be selected (will palce a "None" at the top of the select)
992
+ * 'multiple' => bool whether multiple can be selected
993
+ */
994
+ class drkfr_Select extends drkfr_Field {
995
+
996
+ public function __construct() {
997
+
998
+ $args = func_get_args();
999
+
1000
+ call_user_func_array( array( 'parent', '__construct' ), $args );
1001
+
1002
+ }
1003
+
1004
+ /**
1005
+ * Return the default args for the Select field.
1006
+ *
1007
+ * @return array $args
1008
+ */
1009
+ public function get_default_args() {
1010
+ return array_merge(
1011
+ parent::get_default_args(),
1012
+ array(
1013
+ 'options' => array(),
1014
+ 'multiple' => false,
1015
+ 'select2_options' => array(),
1016
+ )
1017
+ );
1018
+ }
1019
+
1020
+ public function parse_save_values(){
1021
+
1022
+ if ( isset( $this->parent ) && isset( $this->args['multiple'] ) && $this->args['multiple'] )
1023
+ $this->values = array( $this->values );
1024
+
1025
+ }
1026
+
1027
+ public function get_options() {
1028
+
1029
+ if ( $this->has_data_delegate() )
1030
+ $this->args['options'] = $this->get_delegate_data();
1031
+
1032
+ return $this->args['options'];
1033
+ }
1034
+
1035
+ public function enqueue_scripts() {
1036
+
1037
+ parent::enqueue_scripts();
1038
+
1039
+ wp_enqueue_script( 'select2', trailingslashit( drkfr_URL ) . 'js/vendor/select2/select2.js', array( 'jquery' ) );
1040
+ wp_enqueue_script( 'field-select', trailingslashit( drkfr_URL ) . 'js/field.select.js', array( 'jquery', 'select2', 'drkfr-scripts' ) );
1041
+ }
1042
+
1043
+ public function enqueue_styles() {
1044
+
1045
+ parent::enqueue_styles();
1046
+
1047
+ wp_enqueue_style( 'select2', trailingslashit( drkfr_URL ) . 'js/vendor/select2/select2.css' );
1048
+ }
1049
+
1050
+ public function html() {
1051
+
1052
+ if ( $this->has_data_delegate() )
1053
+ $this->args['options'] = $this->get_delegate_data();
1054
+
1055
+ $this->output_field();
1056
+
1057
+ $this->output_script();
1058
+
1059
+ }
1060
+
1061
+ public function output_field() {
1062
+
1063
+ $val = (array) $this->get_value();
1064
+
1065
+ $name = $this->get_the_name_attr();
1066
+ $name .= ! empty( $this->args['multiple'] ) ? '[]' : null;
1067
+
1068
+ ?>
1069
+
1070
+ <select
1071
+ <?php $this->id_attr(); ?>
1072
+ <?php $this->boolean_attr(); ?>
1073
+ <?php printf( 'name="%s"', esc_attr( $name ) ); ?>
1074
+ <?php printf( 'data-field-id="%s" ', esc_attr( $this->get_js_id() ) ); ?>
1075
+ <?php echo ! empty( $this->args['multiple'] ) ? 'multiple' : '' ?>
1076
+ <?php $this->class_attr( 'drkfr_select' ); ?>
1077
+ style="width: 100%"
1078
+ >
1079
+
1080
+ <?php if ( ! empty( $this->args['allow_none'] ) ) : ?>
1081
+ <option value=""></option>
1082
+ <?php endif; ?>
1083
+
1084
+ <?php foreach ( $this->args['options'] as $value => $name ): ?>
1085
+ <option <?php selected( in_array( $value, $val ) ) ?> value="<?php echo esc_attr( $value ); ?>"><?php echo esc_html( $name ); ?></option>
1086
+ <?php endforeach; ?>
1087
+
1088
+ </select>
1089
+
1090
+ <?php
1091
+ }
1092
+
1093
+ public function output_script() {
1094
+
1095
+ $options = wp_parse_args( $this->args['select2_options'], array(
1096
+ 'placeholder' => __( 'Type to search', 'drkfr' ),
1097
+ 'allowClear' => true,
1098
+ ) );
1099
+
1100
+ ?>
1101
+
1102
+ <script type="text/javascript">
1103
+
1104
+ (function($) {
1105
+
1106
+ var options = <?php echo json_encode( $options ); ?>
1107
+
1108
+ if ( 'undefined' === typeof( window.drkfr_select_fields ) )
1109
+ window.drkfr_select_fields = {};
1110
+
1111
+ var id = <?php echo json_encode( $this->get_js_id() ); ?>;
1112
+ window.drkfr_select_fields[id] = options;
1113
+
1114
+ })( jQuery );
1115
+
1116
+ </script>
1117
+
1118
+ <?php
1119
+ }
1120
+
1121
+ }
1122
+
1123
+ class drkfr_Taxonomy extends drkfr_Select {
1124
+
1125
+ /**
1126
+ * Return the default args for the Taxonomy select field.
1127
+ *
1128
+ * @return array $args
1129
+ */
1130
+ public function get_default_args() {
1131
+ return array_merge(
1132
+ parent::get_default_args(),
1133
+ array(
1134
+ 'taxonomy' => '',
1135
+ 'hide_empty' => false,
1136
+ )
1137
+ );
1138
+ }
1139
+
1140
+
1141
+ public function __construct() {
1142
+
1143
+ $args = func_get_args();
1144
+
1145
+ call_user_func_array( array( 'parent', '__construct' ), $args );
1146
+
1147
+ $this->args['data_delegate'] = array( $this, 'get_delegate_data' );
1148
+
1149
+ }
1150
+
1151
+ public function get_delegate_data() {
1152
+
1153
+ $terms = $this->get_terms();
1154
+
1155
+ if ( is_wp_error( $terms ) ) {
1156
+ return array();
1157
+ }
1158
+
1159
+ $term_options = array();
1160
+
1161
+ foreach ( $terms as $term )
1162
+ $term_options[$term->term_id] = $term->name;
1163
+
1164
+ return $term_options;
1165
+
1166
+ }
1167
+
1168
+ private function get_terms() {
1169
+
1170
+ return get_terms( $this->args['taxonomy'], array( 'hide_empty' => $this->args['hide_empty'] ) );
1171
+
1172
+ }
1173
+
1174
+ }
1175
+
1176
+ /**
1177
+ * Post Select field.
1178
+ *
1179
+ * @supports "data_delegate"
1180
+ * @args
1181
+ * 'options' => array Array of options to show in the select, optionally use data_delegate instead
1182
+ * 'allow_none' => bool Allow no option to be selected (will palce a "None" at the top of the select)
1183
+ * 'multiple' => bool whether multiple can be selected
1184
+ */
1185
+ class drkfr_Post_Select extends drkfr_Select {
1186
+
1187
+ public function __construct() {
1188
+
1189
+ $args = func_get_args();
1190
+
1191
+ call_user_func_array( array( 'parent', '__construct' ), $args );
1192
+
1193
+ if ( ! $this->args['use_ajax'] ) {
1194
+
1195
+ $this->args['data_delegate'] = array( $this, 'get_delegate_data' );
1196
+
1197
+ }
1198
+
1199
+ }
1200
+
1201
+ /**
1202
+ * Return the default args for the Post select field.
1203
+ *
1204
+ * @return array $args
1205
+ */
1206
+ public function get_default_args() {
1207
+ return array_merge(
1208
+ parent::get_default_args(),
1209
+ array(
1210
+ 'query' => array(),
1211
+ 'use_ajax' => false,
1212
+ 'multiple' => false,
1213
+ )
1214
+ );
1215
+ }
1216
+
1217
+ public function get_delegate_data() {
1218
+
1219
+ $data = array();
1220